Как добавить собственную секцию кода и разместить её по нужному адресу на примере flash-проекта на C, IAR Embedded Workbench for ARM, ver. 5.20.
Иногда бывает необходимо разместить нужные данные в строго заданном месте firmware, чтобы программа могла легко их найти (например, данные о версии программы положить по фиксированному адресу в код). В частности, у меня стояла задача разместить данные о версии программного обеспечения в коде программы. Требования к размещению:
1. Данные должны лежать в начале прошивки, по известному фиксированному адресу. 2. Формат должен быть основан на дате и времени. 3. Формат должен легко читаться человеком.
На ассемблере сохранить строку в коде flash довольно легко, достаточно - добавить в файл board_cstartup_iar.s строки: DCB 'V','E','R','S','I','O','N'
или так: DCB "VERSION"
Но чтобы эти данные лежали по нужному адресу, придется немного разобраться с файлом управления линкером ILINK (*.icf) - чтобы задать сегмент с данными версии по нужному адресу, а также разобраться с применением сегментов в коде программы. Вся необходимая информация по теме есть во встроенной документации IAR (Help -> ARM C/C++ Development Guide, файл EWARM_DevelopmentGuide.ENU.pdf, а также Help -> ARM Assembler Reference Guide, файл EWARM_AssemblerReference.ENU.pdf). В этой статье только практика, процесс по шагам. Итак, как положить информацию о версии по фиксированному адресу 0x100100 (резервируется блок размером в 32 байта), с помощью отдельного сегмента (в этом примере файлы проекта находятся в папке c:\asm\bootloader\ewp\, а файл линкера - c:\asm\bootloader\at91lib\board\at91sam7x512\flash.icf):
1. Возьмем на себя смелость отредактировать вручную файл *.icf конфигурации линкера (обычно он редактируется только редактором ICF editor, который можно вызвать в разделе конфигурации линкера в проекте). Итак, сначала редактируем файл flash.icf проекта (не забудьте сделать копию!). Это нужно для того, чтобы выделить место под данные версии (32 байта), разместить это место по нужному адресу (0x100100), и привязать к этому месту секцию кода, где будут лежать данные версии (в нашем примере это секция .versionsection). Вот полный текст получившегося файла flash.icf (изменения выделены жирным шрифтом):
/* Файл управления линкером flash.icf */
/*###ICF### Section handled by ICF editor, don't touch! ****/ /*-Editor annotation file-*/ /* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\a_v1_0.xml" */ /*-Memory Regions-*/ define symbol __ICFEDIT_region_ROM_start__ = 0x100000; define symbol __ICFEDIT_region_ROM_end__ = 0x17FFFF; define symbol __ICFEDIT_region_RAM_start__ = 0x200000; define symbol __ICFEDIT_region_RAM_end__ = 0x21FFFF; /*-Sizes-*/ define symbol __ICFEDIT_size_startup__ = 0x100; define symbol __ICFEDIT_size_version__ = 0x20; define symbol __ICFEDIT_size_vectors__ = 0x100; define symbol __ICFEDIT_size_cstack__ = 0x1000; define symbol __ICFEDIT_size_svcstack__ = 0x60; define symbol __ICFEDIT_size_irqstack__ = 0x60; define symbol __ICFEDIT_size_heap__ = 0x6000; /*-Exports-*/ export symbol __ICFEDIT_region_ROM_start__; export symbol __ICFEDIT_region_ROM_end__; export symbol __ICFEDIT_region_RAM_start__; export symbol __ICFEDIT_region_RAM_end__; export symbol __ICFEDIT_size_startup__; export symbol __ICFEDIT_size_version__; export symbol __ICFEDIT_size_vectors__; export symbol __ICFEDIT_size_cstack__; export symbol __ICFEDIT_size_svcstack__; export symbol __ICFEDIT_size_irqstack__; export symbol __ICFEDIT_size_heap__; /**** End of ICF editor section. ###ICF###*/
define memory mem with size = 4G; define region STA_region = mem:[from __ICFEDIT_region_ROM_start__ size __ICFEDIT_size_startup__]; define region VER_region = mem:[from __ICFEDIT_region_ROM_start__+__ICFEDIT_size_startup__ size __ICFEDIT_size_version__]; /* define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__+__ICFEDIT_size_startup__ to __ICFEDIT_region_ROM_end__]; */ define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__+__ICFEDIT_size_startup__+__ICFEDIT_size_version__ to __ICFEDIT_region_ROM_end__]; define region VEC_region = mem:[from __ICFEDIT_region_RAM_start__ size __ICFEDIT_size_vectors__]; define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__+__ICFEDIT_size_vectors__ to __ICFEDIT_region_RAM_end__];
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; define block SVC_STACK with alignment = 8, size = __ICFEDIT_size_svcstack__ { }; define block IRQ_STACK with alignment = 8, size = __ICFEDIT_size_irqstack__ { }; define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
initialize by copy { readwrite }; initialize by copy { section .vectors }; do not initialize { section .noinit };
place in STA_region { section .cstartup }; place in VER_region { section .versionsection }; place in ROM_region { readonly }; place in VEC_region { section .vectors }; place in RAM_region { readwrite, block IRQ_STACK, block SVC_STACK, block CSTACK, block HEAP };
Немного комментариев по коду примера. Код программы лежит в памяти микроконтроллера по абсолютному адресу 0x100000 (определяется символом __ICFEDIT_region_ROM_start__). Размер выделяемого под данные версии блока в 32 байта задается символом __ICFEDIT_size_version__. Адрес размещения 0x100100 нашего блока с версией определяется строчкой "define region VER_region = mem:[from __ICFEDIT_region_ROM_start__ + __ICFEDIT_size_startup__ size __ICFEDIT_size_version__];". Тот факт, что в блоке с данными будет лежать нужная нам секция .versionsection, определяется строчкой "place in VER_region { section .versionsection };".
2. Теперь осталось применить секцию .versionsection в коде для размещения нужных данных. На ассемблере это сделать проще всего. Например, добавляем в файл board_cstartup_iar.s строки: SECTION .versionsection:CODE DCB "VERSION"
Теперь в прошивке по адресу 0x100100 мы увидим слово VERSION.
3. Как добавить данные в секцию .versionsection из кода на C (текст, что мы добавили в board_cstartup_iar.s, закомментируем за ненадобностью): #pragma section = ".versionsection" const char version_full [] @ ".versionsection" = "VERSION 18.06.2010 15:25:40";
Теперь если открыть двоичный файл прошивки, то в коде увидим текст версии:
Информацию о версии удобно генерить автоматически из даты и времени, с помощью VBS-скрипта (см. Ссылки).
[Ссылки]
1. IAR EW ARM: автоматическая генерация версии прошивки. 2. IAR 4.0: размещение переменных и данных по заданному адресу. |
Комментарии
RSS лента комментариев этой записи