Я уже писал о методе добавления внешних файлов в прошивку микроконтроллера, даже написал для этой цели онлайн-конвертер бинарного файла в c-хедер. Однако есть более простой и удобный способ, который предоставляет IAR, да и строго говоря, любой линкер обязан уметь так делать.

Конечно, вы уже поняли — мы полезем в параметры линкера.

Одна из самых частых моих задач за последнее время — это сборка прошивки основного девайса, в которую вкомпилена прошивка дочерней платы. Основной девайс при запуске проверяет версию прошивки дополнительной платы, и если она младше — обновляет её до свежей. Поэтому я должен включить в основную прошивку бинарный файл с дочерней прошивкой.

Открываем окно Options -> Linker -> Input:

Снимок экрана 2016-01-09 в 13.02.24

Внизу видим опции «Raw binary image». Это именно то, что нам нужно, указываем файл.

Что обозначают остальные опции?

  • Symbol — глобальный символ кода, это то имя, которое будет присвоено массиву с содержимым файла. Я написал здесь batp_fw, потому что это прошивка (firmware) платы BATP.
  • Section — секция линкера, в которой файл будет размещён. Напишем здесь «fw_section», только ещё надо будет создать и разместить эту секцию.
  • Align — выравнивание по границе байт, полуслов или слов. Обычно я ставлю здесь 4 (выровнять по границе слов).

Укажите имя символа в окошке «Keep symbols», иначе символ (и весь массив) будет выкинут линкером при сборке.

Снимок экрана 2016-01-09 в 13.14.46

Сохраните изменения, и пойдём править скрипт линкера. Он лежит в папке проекта, что-то вроде stm32f4xx_flash.icf.

/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__    = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__      = 0x081FFFFF;
define symbol __ICFEDIT_region_RAM_start__    = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__      = 0x2002FFFF;
define symbol __ICFEDIT_region_CCMRAM_start__ = 0x10000000;
define symbol __ICFEDIT_region_CCMRAM_end__   = 0x1000FFFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x400;
define symbol __ICFEDIT_size_heap__   = 0x200;
/**** End of ICF editor section. ###ICF###*/


define memory mem with size = 4G;
define region ROM_region      = mem:[from __ICFEDIT_region_ROM_start__   to __ICFEDIT_region_ROM_end__];
define region RAM_region      = mem:[from __ICFEDIT_region_RAM_start__   to __ICFEDIT_region_RAM_end__];
define region CCMRAM_region   = mem:[from __ICFEDIT_region_CCMRAM_start__   to __ICFEDIT_region_CCMRAM_end__];

define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };

initialize by copy { readwrite };
do not initialize  { section .noinit };

place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };

>>> place at address mem:0x08100000 { readonly section fw_section }; <<<

place in ROM_region   { readonly };
place in RAM_region   { readwrite,
                        block CSTACK, block HEAP };

Я добавил строчку

place at address mem:0x08001000 { readonly section fw_section };

практически в самом конце скрипта линкера. Это разместит тот файл во flash-памяти, начиная с адреса 0x08001000.

Файл batp_fw.bin в редакторе выглядит так:

Снимок экрана 2016-01-09 в 13.33.36

Компилируем, собираем проект и запускаем. Посмотрим редактор памяти (View -> Memory во время отладки):

Снимок экрана 2016-01-09 в 13.32.58

Как видим, файл действительно разместился по нужному нам адресу.

Ну и вишенка на торте, использование этого куска памяти, как массив в программе — это очень… нет, крайне просто!

extern uint32_t batp_fw[];

Конечно, тип данных может быть любой удобный вам. Хотите обращаться побайтово — используйте char или лучше uint8_t, хотите ускорить чтение — обращайтесь пословно с помощью unsigned int или лучше uint32_t.

Заключение.

Этот способ лучше, чем вклейка в код массива байт файла, как в прошлой статье. Но он, возможно, чуть сложнее. И если нужно что-то подправить в файле перед слияением — вам понадобится hex-редактор, в отличие от прошлого способа, где это можно сделать хоть Блокнотом.

Однако, этот способ даёт включить только один файл, если нужно включить несколько— потребуется ручная правка командной строки линкера.