Вставка файлов в прошивку — 2 часть

Я уже писал о методе добавления внешних файлов в прошивку микроконтроллера, даже написал для этой цели онлайн-конвертер бинарного файла в 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-редактор, в отличие от прошлого способа, где это можно сделать хоть Блокнотом.

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

Ссылка на основную публикацию