Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Подсчет CRC32
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
KSN
IAR AVR 5.20, Atmega8. Bootloader располагается с адреса 0х1800, используетя одно прерывание от таймера 2. Область памяти с 0x1400-0x17FF является общей для Bootloader & Application (здесь расположены общие функции). По адресу 0x00A2 находится указатель на память, где хранится значение CRC32 (считается IARом). Проблема заключается в следующем: делаю несколько посылок команды "посчитать CRC32" и получаю иногда неправильный результат. Если на момент подсчета CRC32 запретить прерывания, то CRC32 считается нормально. Не могу понять в чем дело? Гляньте часть кода, что не так? Проект компилировался и под IAR AVR 4.30 - результат такой же, значит дело не в компиляторе.
CODE

Uint32 __flash *pchecksum;

#pragma location=0x60
__no_init volatile unsigned int Tictime;

Uint32 slow_crc32(Uint32 sum, Uint8 __flash *p, Uint16 len)
{
while (len--)
{
Uint8 i;
unsigned char byte = *p++;

for (i = 0; i < 8; ++i)
{
unsigned long osum = sum;
sum <<= 1;
if (byte & 0x80)
sum |= 1 ;
if (osum & 0x80000000)
sum ^= POLY;
byte <<= 1;
}
}
return sum;
}

#pragma vector=TIMER2_COMP_vect
__interrupt void TIMER2_COMP_isr(void)
{ Tictime++; }



__C_task void main(void)
{
__no_init Uint32 addr;

GICR = (1<<IVCE); // Таблицу векторов в область загрузчика
GICR = (1<<IVSEL);
__enable_interrupt();

/* ....Здесь идет кое-какой код.... В частности обмен по SPI.
Во время обмена по SPI прерывания запрещаются....*/
// Прилетела команда по SPI посчитать CRC32.
pchecksum = (Uint32 __flash *)(*((Uint16 __flash *)(0x00A2)));
addr = 0;
addr = slow_crc32(addr,(Uint8 __flash *)0, ((Uint16)pchecksum)&0x013FF);
addr = slow_crc32(addr,(Uint8 __flash *)&zero,4);
// далее addr посылаю по SPI.
/* ... продолжение программы...*/

}
sergeeff
Судя по вашему рассказу, проблема в неверной обработке прерываний. Все ли правильно установлено в обработчике прерываний?
KSN
Возможно, что и с прерыванием не порядок. Глянул листинг - особого криминала не увидел.
Код
   \   00000000   93FA               ST      -Y, R31
   \   00000002   93EA               ST      -Y, R30
   \   00000004   932A               ST      -Y, R18
   \   00000006   931A               ST      -Y, R17
   \   00000008   930A               ST      -Y, R16
   \   0000000A   B72F               IN      R18, 0x3F
   \   0000000C   E6E0               LDI     R30, 96
   \   0000000E   E0F0               LDI     R31, 0
   \   00000010   ....               RCALL   ?Subroutine25
   \                     ??CrossCallReturnLabel_101:
   \   00000012   5F0F               SUBI    R16, 255
   \   00000014   4F1F               SBCI    R17, 255
   \   00000016   ....               RCALL   ?Subroutine22
   \                     ??CrossCallReturnLabel_84:
   \   00000018   BF2F               OUT     0x3F, R18
   \   0000001A   9109               LD      R16, Y+
   \   0000001C   9119               LD      R17, Y+
   \   0000001E   9129               LD      R18, Y+
   \   00000020   91E9               LD      R30, Y+
   \   00000022   91F9               LD      R31, Y+
   \   00000024   9518               RETI
   \   00000026                      REQUIRE Tictime

   \                                 In  segment CODE, align 2, keep-with-next
   \                     ?Subroutine22:
   \   00000000   8300               ST      Z, R16
   \   00000002   8311               STD     Z+1, R17
   \   00000004   9508               RET

   \                                 In  segment CODE, align 2, keep-with-next
   \                     ?Subroutine25:
   \   00000000   8100               LD      R16, Z
   \   00000002   8111               LDD     R17, Z+1
   \   00000004   9508               RET
редактор
Не спец по AVR поэтому общие мысли
1. Бутлоадер и приложение один проект или два разных??
Если разные то прерывание и подсчет CRC должны быть описаны в одном проекте. иначе линкер может смешать области данных двыух проектов.
2. По описанию Адрес 0xA2 содержит указатель на CRC, а при вызове функции параметр как длина участка кода
addr = slow_crc32(addr,(Uint8 __flash *)0, ((Uint16)pchecksum)&0x013FF);
3. Второй вызов функции. Что из себя представляет переменная zero? может быть в этом проблема
addr = slow_crc32(addr,(Uint8 __flash *)&zero,4);
Поскольку два вызова функции, я бы попробовал после каждой из них посмотреть результат, какой вызов вносит ошибку.
SysRq
Быть может, дело вовсе не в crc, а в чем-то еще?
К примеру, эта самая Tictime - 16 бит, а МК - 8-битный. Если не запретить прерывания таймера на момент считывания Tictime для операции, к примеру, сравнения (if(Tictime == 1000)), возможна беда...
sergeeff
Цитата(SysRq @ Feb 27 2010, 20:52) *
Быть может, дело вовсе не в crc, а в чем-то еще?
К примеру, эта самая Tictime - 16 бит, а МК - 8-битный. Если не запретить прерывания таймера на момент считывания Tictime для операции, к примеру, сравнения (if(Tictime == 1000)), возможна беда...


Автор пишет, что прерывание всего одно - от Timer2. Посему никто не мешает процессору грузить новые данные в 16-разрядную переменную. То есть никакой беды нет.

И еще, пора бы уже поправить имя переменной Tictime -> Ticktime. Аж глаз режет.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.