Баг в следующем:
Имеется давно отлаженный и работающий и используемый код:
Код
unsigned short crc16_P(const void __farflash *ptr,unsigned long count)
{
unsigned short crc=0;
for(s=(unsigned char __farflash*)ptr;count;count--,s++) {
crc=crctab[(unsigned char)((crc>>8) ^ *s) & 0xff ]^(crc<<8);
__watchdog_reset();
}
return crc;
}
, считает свою crc16 неверно.
Естественно, раз он отлаженный то на него я подумал в последнюю очередь.
В листинге дает следующее:
Код
\ In segment CODE, align 2, keep-with-next
55 unsigned short crc16_P(const void __farflash *ptr,unsigned long count)
\ ??crc16_P:
56 {
\ 00000000 93BA ST -Y, R27
\ 00000002 93AA ST -Y, R26
57 unsigned char __farflash *s;
58 unsigned short crc=0;
\ 00000004 2422 CLR R2
\ 00000006 2433 CLR R3
59 for(s=(unsigned char __farflash*)ptr;count;count--,s++) {
\ 00000008 01D8 MOVW R27:R26, R17:R16
\ 0000000A 2F04 MOV R16, R20
\ 0000000C 2B05 OR R16, R21
\ 0000000E 2B06 OR R16, R22
\ 00000010 2B07 OR R16, R23
\ 00000012 F0E1 BREQ ??crc16_P_1
60 crc=crctab[(unsigned char)((crc>>8) ^ *s) & 0xff ]^(crc<<8);
\ ??crc16_P_2:
\ 00000014 2D03 MOV R16, R3
\ 00000016 01FD MOVW R31:R30, R27:R26
\ 00000018 BF2B OUT 0x3B, R18
\ 0000001A 9117 ELPM R17, Z+
\ 0000001C 01DF MOVW R27:R26, R31:R30
\ 0000001E 2701 EOR R16, R17
\ 00000020 E012 LDI R17, 2
\ 00000022 9F01 MUL R16, R17
\ 00000024 01F0 MOVW R31:R30, R1:R0
\ 00000026 .... SUBI R30, LOW((-(crctab) & 0xFFFFFF))
\ 00000028 .... SBCI R31, HIGH((-(crctab) & 0xFFFFFF))
\ 0000002A .... LDI R19, (crctab) >> 16
\ 0000002C BF3B OUT 0x3B, R19
\ 0000002E 9007 ELPM R0, Z+
\ 00000030 9036 ELPM R3, Z
\ 00000032 2D12 MOV R17, R2
\ 00000034 2C20 MOV R2, R0
\ 00000036 2631 EOR R3, R17
61 __watchdog_reset();
\ 00000038 95A8 WDR
62 }
\ 0000003A 5041 SUBI R20, 1
\ 0000003C 4050 SBCI R21, 0
\ 0000003E 4060 SBCI R22, 0
\ 00000040 4070 SBCI R23, 0
\ 00000042 2F04 MOV R16, R20
\ 00000044 2B05 OR R16, R21
\ 00000046 2B06 OR R16, R22
\ 00000048 2B07 OR R16, R23
\ 0000004A F721 BRNE ??crc16_P_2
63 return crc;
\ ??crc16_P_1:
\ 0000004C 0181 MOVW R17:R16, R3:R2
\ 0000004E 91A9 LD R26, Y+
\ 00000050 91B9 LD R27, Y+
\ 00000052 9508 RET
64 }
Те компилятор зная что указатель на __farflash char -24 ,бита длиной, местами( при инкременте Z+), обращается с ним как с 16 битным.
Отключение оптимизации ничего не дает, проблема решается только так:
Код
unsigned short crc16_P(const void __farflash *ptr,unsigned long count)
{
unsigned char __farflash *s;
volatile unsigned long ds;
unsigned short crc=0;
for(s=(unsigned char __farflash*)ptr;count;count--/*,s++*/) {
crc=crctab[(unsigned char)((crc>>8) ^ *s) & 0xff ]^(crc<<8);
__watchdog_reset();
ds=(unsigned long)s;
ds++;
s=(__farflash unsigned char*) ds;
}
return crc;
}
Хотя может это гдето уже было, плохо искал
Сообщение отредактировал Константин Якушев - May 7 2009, 08:22