Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: CRC в IAR и определение конечного адреса
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
SasaVitebsk
Доброго времени суток.
Где-то по топикам видел (не записал к сожалению), что IAR может автоматически генерить и вставлять CRC в конец проги. Хочу свой BootLoader написать и там это мне обязательно понадобится. Отсюда вопросы.
1) Как и где эту опцию включить в IAR.
2) Как из проги обратится к этой CRC (видимо какая то глобальная переменная есть, которая LINKером генерится)
3) Какая формула CRC, а лучше таблица или п/п.

Заранее спасибо.
prottoss
Цитата(SasaVitebsk @ Sep 22 2007, 18:24) *
1) Как и где эту опцию включить в Заранее спасибо.
Project->Options->Linker->Processing->Generate Checksum...
zltigo
Цитата(SasaVitebsk @ Sep 22 2007, 13:24) *
Доброго....

В документации на линкер и дополнительно AN на IAR-овском сайте есть по нюансам алгоритмов.
То, что в проекте это для "галочки", посему в XCL файле прописывать удобнее.
prottoss
Processing

With the Processing options you can specify details about how the code is generated.

Use Fill unused code memory to fill all gaps between segment parts introduced by the with the value you enter. The lcan introduce gaps either because of alignment restriction, or at the end of ranges given in segment placement options.

Use Generate checksum to checksum all generated raw data bytes. This option can only be used if the Fill unused code memory option has been specified.

Size specifies the number of bytes in the checksum, which can be 1, 2, or 4.
One of the following algorithms can be used:

Arithmetic sum Simple arithmetic sum CRC16 , generating polynomial 0x11021 (default) CRC32 CRC32, generating polynomial 0x104C11DB7 Crc polynomial CRC with a generating polynomial of the value you enter

You can also specify that the one's complement or two's complement should be used.
By default it is the most significant 1, 2, or 4 bytes (MSB) of the result that will be output, in the natural byte order for the processor. Choose LSB from the Bit order drop-down list if you want the least significant bytes to be output.

The CRC checksum is calculated as if the following code was called for each bit in the input, starting with a CRC of 0:

unsigned long crc(int bit, unsigned long oldcrc)

{

unsigned long newcrc = (oldcrc << 1) ^ bit;

if (oldcrc & 0x80000000) newcrc ^= POLY;

return newcrc;

}

POLY is the generating polynomial. The checksum is the result of the final call to this routine. If the complement is specified, the checksum is the one's or two's complement of the result.

The will place the checksum byte(s) at the __checksum label in the CHECKSUM segment. This segment must be placed using the segment placement options like any other segment. [/quote]
SasaVitebsk
Вроде понял
получилось
-J2,crc16,1,(CODE)E4-E6

Но мне то в приложении только сгенерить надо, а читать из бута. Как прочитать CRC понятно. Привяжу к конкретному адресу. А как мне определить размер кода. То есть я хочу по результатам линковки в ячейках E6-EA разместить длину занятую кодом. Как это сделать.

Посмотрел по MAPу последним сегментом у меня идёт INITTAB. Я могу быть уверенным что он всегда в конце будет? И как конечный адрес разместить в (CODE)?
zltigo
Можете завести свой сегмент и всегда линковать его в конце. Ну а конкретное решение очень простое - заводите сегмент под переменную CRC, линкуете его в конце а по фиксированному адресу размещаете адрес CRC smile.gif.
SasaVitebsk
Цитата(zltigo @ Sep 22 2007, 18:16) *
Можете завести свой сегмент и всегда линковать его в конце. Ну а конкретное решение очень простое - заводите сегмент под переменную CRC, линкуете его в конце а по фиксированному адресу размещаете адрес CRC smile.gif.

Спасибо за совет. Я так и сделаю. Я так на Асме всё время делал. Только я не знаю как именно свой сегмент (или любой другой) в конце разместить. Так чтобы адреса не указывать, а просто - последним.
zltigo
Цитата(SasaVitebsk @ Sep 22 2007, 20:30) *
Так чтобы адреса не указывать, а просто - последним.

Порядок линковки в порядке перечисления:
Код
-Z(CODE)INTVEC=ROMSTART-ROMEND
......

-Z(CONST)INITTAB,DATA_ID,DATA_C=ROMSTART-ROMEND
// Segment for CheckSUM
-Z(CONST)CHECKSUM=ROMSTART-ROMEND     // To end of CODE block
//-Z(CONST)CHECKSUM#ROMSTART-ROMEND    // To end of ROM block
SasaVitebsk
Спасибо огромное. beer.gif
igorAT
Доброго времени суток.
SasaVitebsk, если Вы разобрались с CRC в IAR, то прошу помощи.
MEGA32
Строка в .xcl - -J2,crc16,1,=(CODE)0-1(для пробы считаю CRC для первых
двух байт прошивки)
Значения во FLASH 0x0000=0C, 0x0001=94
На месте CHECKSUM#7FFF - af 79
В .map:
Symbol Checksum Memory Start End Initial value
------ -------- ------ ----- --- -------------
__checksum 0x79af CODE 00000000 - 00000001 0x0
Вычисляю:
Код
void crc16_buf(u08 const __flash *buf,u16 buf_size)
{
  u32 oldcrc = 0;
  u32 newcrc;
  u16 bit;
  u08 byte,count;
  
  while(buf_size){
    byte = (*buf);
    count = 7;
    do{
      if(byte & 0x80)
    bit = 1;
      else
    bit = 0;
      newcrc = (oldcrc << 1) ^ bit;
//      if(oldcrc & 0x80000000) newcrc ^= 0xA0010000;
      if(oldcrc & 0x8000) newcrc ^= 0x1021;
      oldcrc = newcrc;
      byte <<= 1;
    }while(count--);
    buf++;
    buf_size--;
  }
  crc16mb_prev = oldcrc;
}

Не получается получить такой же результат.
Может увидите где ошибаюсь
Заранее спасибо.
[/quote]
vladimir_ad
Цитата(igorAT @ Sep 24 2007, 17:12) *
while(buf_size)
{
byte = (*buf);
...

А что, iar уже прямо так данные из flash берет?
Раньше для этого unsigned char __load_program_memory(unsigned char __flash *) использовали.
;-)
Сергей Борщ
Цитата(vladimir_ad @ Sep 26 2007, 16:40) *
А что, iar уже прямо так данные из flash берет?
Раньше для этого unsigned char __load_program_memory(unsigned char __flash *) использовали.
;-)
Даже и не сообразил сразу что ответить... Уже года 4 как.
Сергей Борщ
Цитата(igorAT @ Sep 24 2007, 16:12) *
Код
void crc16_buf(u08 const __flash *buf,u16 buf_size)
Ой, а что так страшно? Попробуйте что-то вроде такого:
Код
    uint16_t crc = 0;
    do
    {
        crc ^= ((uint16_t)*ptr++) << 8;
        uint8_t i = 8;
        do
        {
            if (crc & (1<<7))
            {
                crc <<= 1;
                crc ^= 0x1021;
            }
            else
                crc <<= 1;
        }
        while(--i);
    }
    while (--buf_size);

    crc16mb_prev =crc;
}
vladimir_ad
Цитата(Сергей Борщ @ Sep 27 2007, 00:29) *
Даже и не сообразил сразу что ответить... Уже года 4 как.
Ух, ты! Как я проспал! Всегда использовал свои функции для загрузки. Спасибо!

В коде примера Сергея есть:
Цитата
crc ^= ((uint16_t)*ptr++) << 8;
Имхо при сдвиге crc биты должны добавляться по одному, а не байтами.


Мои загрузчики считают crc всей памяти секции приложения. В конце секции лежит crc и другие данные записанные моей внешней программой.
+Нет разницы чем компилировать приложение и на каком языке написано.
Сергей Борщ
Цитата(vladimir_ad @ Sep 27 2007, 11:51) *
Имхо при сдвиге crc биты должны добавляться по одному, а не байтами.
Дальше вы видите цикл по восьми битам. Есть две схемы вычисления CRC, которые дают в итоге один и тот же численный результат. Нет разницы - добавлять по одному биту или сразу все. Более подробное объяснение с картинками мне попадалось у Б. Скляра в его "Цифровой связи".
Цитата(vladimir_ad @ Sep 27 2007, 11:51) *
Мои загрузчики считают crc всей памяти секции приложения. В конце секции лежит crc и другие данные записанные моей внешней программой.
+Нет разницы чем компилировать приложение и на каком языке написано.
Аналогично.
vladimir_ad
Цитата(Сергей Борщ @ Sep 27 2007, 13:10) *
Дальше вы видите цикл по восьми битам. ....
Вы не поняли. Пример не работает - crc всегда 0.
;-)
Waso
Почему линкер при линковке требует больше места чем ему требуется на самом деле?
Смотрю map-файл или готовый бинарник, сгенеренный когда линкеру дается весь флеш и затем задаю это (даже немного большее) значение как ROMEND.
Код
-DBOOTSIZE=00008000
//-DAPPMAXSIZE=00010000
-DAPPMAXSIZE=0000AB0F
-DROMSTART=(00100000+BOOTSIZE)
-DROMEND=(00100000+BOOTSIZE+APPMAXSIZE)

Тогда линковщик начинает ругаться:
Код
Error[e16]: Segment DATA_C (size: 0x2e3c align: 0x2) is too long for segment definition. At least 0xc24 more bytes needed. The problem occurred while processing the segment placement  
command "-Z(CONST)INITTAB,DATA_ID,DATA_C=ROMSTART-ROMEND", where at the moment of placement the available memory ranges were "CODE:1108f6-112b0f"
   Reserved ranges relevant to this placement:
   108000-1083a7        ICODE
   1083a8-1108a5        CODE
   1108a6-1108bf        INITTAB
   1108c0-112b0f        DATA_ID
Если дать ему эти нехватающие 0xC24 байта, то линкуется нормально, но это выделенное пространство заполняет как пустое неиспользованное место.
Почему? На всяк случай приложил map и xcl файлы.
Сергей Борщ
Цитата(Waso @ Nov 22 2007, 11:29) *
Почему линкер при линковке требует больше места чем ему требуется на самом деле?
Это баг. Примерно догадываюсь, откуда он идет. Судя по адресам речь об ARM. Безусловный переход в ARM может быть сделан одним из двух способов - B label и LDR PC,=label (аналоги RJMP и JMP у AVR). Во втором случае требуется еще одно слово для хранения абсолютного адреса (label) в виде константы. В коде место под константу зарезервировано. При линковке линкер смотрит, может ли он дотянуться до метки командой B label. Если может, вставляет эту команду и удаляет ставшую ненужной константу с адресом label. Предполагаю, что код может просматриваться в несколько проходов, ибо переходы, которые были слишком длинными на первой итерации, после удаления части констант тоже могут заменены на короткие. Таким образом размер кода уменьшается. Видимо подсчет размера кода и выдача сообщения об ошибке происходит перед операцией замены длинных переходов на короткие. Это мое мнение, просто предположение. Увы, обход только один - выделить чуть больше памяти и вручную смотреть, что получившийся код уместился в имеющуюся память.


Ой. только сейчас увидел:
Цитата(vladimir_ad @ Sep 27 2007, 12:51) *
Вы не поняли. Пример не работает - crc всегда 0.
Ага, ошибочка: if (crc & (1U<<15))
Сергей Борщ
Цитата(Сергей Борщ @ Nov 22 2007, 13:03) *
Видимо подсчет размера кода и выдача сообщения об ошибке происходит перед операцией замены длинных переходов на короткие.
Тема получила неожиданное продолжение на другом форуме, там же рецепт обхода проблемы. Еще не проверял.
Waso
Рецепт работает, благодарю!

Еще вопрос по CRC - хочу дописывать в конец файла число, которое давало бы нулевую CRC после прохода функции подсчета по файлу и этому числу вконце. Взял функцию crc16 из иаровских апнотов. Прогнал по прошивке. Результат сходится. В иаре менял настройку чтоб вставлял инверсионную сумму. И делал завершающий проход по этому числу. Результат ненулевой. Где я ошибся/как правильно??? Именно эту тонкость в гугле не нашол. sad.gif
Сергей Борщ
Цитата(Waso @ Nov 27 2007, 11:13) *
В иаре менял настройку чтоб вставлял инверсионную сумму. И делал завершающий проход по этому числу. Результат ненулевой.
Во-первых надо вставлять не инвертированный, а прямой результат. Во-вторых, если в коде встречаются "дыры", т.е. незаполненные участки, то линкер считает, что там нули, а на самом деле там единицы. Поэтому надо давать опцию заполнять свободное место константой 0xFFFFFFFF. Эту тему zltigo прорабатывал. Я ограничился написанием самописной утилиты, которая считает CRC как мне надо.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.