Перейти к содержанию
    

Подсчет CRC средствами ИАР

Еще раз добрый день!

Столкнулся с такой проблемой - создаю CRC так:

-J2,crc=8005,,,,,=(CODE)0-1

 

получаю вот это:

Symbol      Checksum  Memory  Start      End       Initial value
------      --------  ------  -----      ---       -------------
__checksum    0xab7b   CODE   00000000 - 00000001  0x0000 (#0x0000)

 

В программе использую следующий код для подсчета CRC (задача сравнить его с CRC прошивки) (пробую пока на 2 байтах...)

 

#define POLY 0x8005
unsigned short slow_crc16(unsigned short sum, unsigned char __flash *p,
unsigned int len)
{
  while (len--)
  {
    int i;
    unsigned char byte = *(p++);
    for (i = 0; i < 8; ++i)
    {
      unsigned long osum = sum;
      sum <<= 1;
      if (byte & 0x80)
        sum |= 1;
      if (osum & 0x8000)
        sum ^= POLY;
      byte <<= 1;
    }
  }
  return sum;


unsigned short calc = 0;

/* Run the checksum algorithm */
calc = slow_crc16(calc, (unsigned char __flash*)0,(0x1));
}

 

внимание, вопрос... Не сходятся CRC...

Функция подсчета CRC взята из

IAR Linker and Library Tools

Reference Guide стр.36

 

В чем может быть дело???

Заранее благодарю...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Бутлодырь пишете?

Вам просто CRC Нужна или какая-то конкретная? Ибо если просто, то есть у меня отлаженный табличный алгоритм. Шустрый весьма.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Бутлодырь пишете?

Вам просто CRC Нужна или какая-то конкретная? Ибо если просто, то есть у меня отлаженный табличный алгоритм. Шустрый весьма.

Да. Именно бутлодырь.

Мне хотелось генерить crc средствами xlinc чтобы не заморачиваться со сторонними программами. Ну и соответственно, считать ее при заливке ПО. Вот потому и взял алгоритм и собственно код из документации по xlinc. Ан нет, не так все просто оказалось...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да. Именно бутлодырь.

Мне хотелось генерить crc средствами xlinc

 

Я работаю со старыми средами без xlink, и все работет.

Попробуйте стандартный полином. 0x1021

Проверьте диапазон памяти.

Проверьте заполнение памяти.

Проверьте расположение суммы.

На всякий случай кладу программу, но она отличается всего лишь полиномом.

 

unsigned short 
slow_crc16(unsigned short sum, unsigned char *p, unsigned short len)
{    while (len--)
    {
        int i;
        unsigned char byte = *p++;

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для бутлоадера на AVR ATMega128 я когда-то использовал CRC-32, табличный метод. По таблице у меня сначала проверялась CRC-32 самого бутлоадера, далее, если не были нажаты кнопки, то проверяется рабочая программа тоже по CRC-32. Контрольную сумму самого бутлоадера считает сам Xlink, и сам кладет ее в соответствующий сегмент "CHECKSUM" из 4х байт. Надо только указать его в xcl-файле:

 

 

//------ Code (FLASH) segments --------------------------

-Z(CODE)INTVEC=1E000-1E08B
-Z(CODE)CODE=1E000-1FFF9
-Z(CODE)TINY_F,TINY_ID,NEAR_F,NEAR_ID,INITTAB,DIFUNCT,SWITCH,HUGE_F=1E000-1FFF9
-Z(CODE)CHECKSUM=1FFFA-1FFFD
-Z(FARCODE)FAR_F=0-1FEF9

 

Способ подсмотрен в каком-то аппноте, от IAR (уже не помню, в каком, но точно не для AVR :)) Сама проверка очень проста:

 

unsigned long lCrc32Table [256] =
  {
  0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
  0x1a864db2, 0x1e475005, 0x2608edb8, ...,    ..., ...,                      0xb1f740b4
  };

//------------------------------------------------------------------------
// Проверить CRC-32 самого BootLoader'а
  {
  unsigned long ltemp = 0;
  unsigned int  ilenth = 0x1FFFA - 0x1E000;
  unsigned char __hugeflash* pcHFpoint = (unsigned char __hugeflash*)0x1E000;
  while (ilenth--)
    ltemp = lCrc32Table [(ltemp >> 24) ^ *pcHFpoint++] ^ (ltemp << 8);
  if (ltemp != *(unsigned long __hugeflash*)0x1FFFA)
    {
    MCUCR = (1<<SE)+(1<<SM1);   // если CRC-32 несовпадает,
    __sleep();                  // уснуть в полный PowerDown
    }
  }

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну и я до кучи положу модбасовскую CRC по полиному 0xA001.

 

// Method GetCRC
// Calculate CRC and save it
VOID CApollo_TesterDlg::GetCRC(BYTE *DataPtr, BYTE DataSize, BYTE *lpbFirstByte, BYTE *lpbSecondByte)
{
	WORD CRC = 0xFFFF;

	// calculating
	for(int i = 0; i < DataSize; i++)	   {
			CRC^= (unsigned int)DataPtr[i];

			for(int k = 0; k < 8; k++)	  {
					if (CRC & 0x01) {
							CRC>>=1;
							CRC^= 0xA001;
					}
					else	{
							CRC>>=1;
					}
			}
	}

	// save
	*lpbFirstByte = LOBYTE(CRC), *lpbSecondByte = HIBYTE(CRC);	  
}

 

И табличный метод для этих ваших AVR :)

 

/* Table of CRC values for high–order byte */
__flash unsigned char auchCRCHi[256] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40
};

/* Table of CRC values for low–order byte */
__flash char auchCRCLo[256] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
0x40
};

unsigned int Get_CRC16(unsigned char *puchMsg, unsigned char usDataLen) {
 unsigned char uchCRCHi = 0xFF;  /* high byte of CRC initialized */
 unsigned char uchCRCLo = 0xFF;  /* low byte of CRC initialized */
 unsigned char uIndex;		   /* will index into CRC lookup table */

while ( usDataLen-- )   /* pass through message buffer */
{
 uIndex = uchCRCHi ^ *puchMsg++;  /* calculate the CRC */
 uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
 uchCRCLo = auchCRCLo[uIndex];
}
return ((uchCRCHi << 8) | uchCRCLo);
}

 

Оба метода по одному полиному. То есть в МК можно использовать табличный, а в ПК обычный способ.

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня сейчас CRC32 считается в IAR-е. Но в своё время много потратил времени чтобы разобраться как это правильно делать.

Проц - LPC17xx.

1. Область расчёта CRC не должна перекрываться с областью расчёта контрольной суммы первых векторов из таблицы ISR.

2. Место хранения CRC не должно перекрываться с областью расчёта CRC.

3. Размер области, заполняемой шаблоном, должен быть достаточным, чтобы перекрыть всю занимаемую прошивкой память.

Если эти условия не выполняются - будет неверная CRC.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. Область расчёта CRC не должна перекрываться с областью расчёта контрольной суммы первых векторов из таблицы ISR.

Может перекрываться, если туда заранее вписывать правильное значение. Тогда сборку надо делать в два прохода: первый - для вычисления значения КС векторов, второй - для вычисления правильной CRC.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как это сказать IAR-у? (что нужно два прохода, что только на 2-м считать CRC?)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как это сказать IAR-у? (что нужно два прохода, что только на 2-м считать CRC?)

Никак.

Запустить первый проход. CRC после первого прохода игнорировать. Подсчитать КС векторов. Вписать КС в нужное место. Запустить второй проход.

Можно и за один проход всё сделать если векторы (не все, а только те, которые участвуют в подсчёте КС) будут указывать на промежуточные вызовы, расположенные сразу за таблицей векторов по фиксированным адресам. В этом случае КС будет константной.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...