BootLoader — это слово, знакомое многим людям и даже часто используемое. Например, оно необходимо при онлайн-обновлении системы, запуске программы во внешней памяти. В этой статье мы расскажем, как разработать программу BootLoader для микроконтроллеров серии STM32.
Основной принцип работы BootLoader
Поскольку мы хотим реализовать программу BootLOader для STM32, сначала мы должны понять основные принципы работы программы BootLOader.
Как мы знаем, программа BootLOader должна обеспечивать управление системой, что является ее основной функцией. Для микроконтроллеров серии STM32 программа будет выполняться с начального адреса внутренней флэш-памяти после запуска системы. Затем вводится прикладная программа и выполняется в соответствии с установленным порядком. В этот момент BootLoader и прикладная программа интегрированы, как показано на рисунке:

Но иногда мы не хотим, чтобы приложение запускалось напрямую, например, когда мы хотим реализовать IAP для системы; или мы не хотим, чтобы приложение запускалось из нашей внутренней флэш-памяти; или приложение запускается из внутренней флэш-памяти, но мы хотим, чтобы приложение запускалось с указанного нами адреса внутренней флэш-памяти и т. д. В таких случаях нам нужна отдельная программа BootLoader. Система сначала запускает программу BootLoader и переходит к выполнению прикладной программы после того, как система готова, как показано на рисунке:

На рисунке выше мы фактически храним приложение в указанном месте внутренней флэш-памяти, что, конечно же, необходимо для достижения некоторых наших целей, таких как системный IAP. Конечно, мы также можем хранить прикладную программу во внешней флэш-памяти, и тогда программа BootLoader переходит к внешней флэш-памяти для выполнения прикладной программы, но при условии, что внешняя флэш-память приобретает программу выполнения. Конкретный процесс выглядит следующим образом:

Конечно, это всего лишь пример, и нам нужно только изменить адрес для разных типов памяти. Что касается функций, которые будут реализованы в программе BootLoader, то это зависит от использования. В принципе, мы можем добавить любую функцию, которую захотим, например, обнаружение оборудования, обновление системы и т. д.
Проектирование загрузчика для STM32
Быстрое планирование
В качестве целевого микроконтроллера мы используем STM32F407IGT6, который имеет 1 Мб флэш-памяти и 192 Кб SRAM. Мы делим Flash на две части: одна — область загрузочной программы (0x0800 0000 — 0x0800 3FFF) размером 16 КБ, а остальная — область прикладной программы (0x0800 4000 — 0x080F FFFF). Конкретное распределение выглядит следующим образом:

Мы позволили программе BootLoader занять 16 КБ памяти. Но она может работать со всем объемом флэш-памяти.
Структура BootLoader
Рассмотрим структуру программы BootLoader. Основная цель нашей разработки программы BootLoader — обновление прикладной программы. Итак, какие основные функции необходимо реализовать в программе BootLoader? Необходимо учесть несколько аспектов. Один из них — это базовая конфигурация, такая как часы и т. д., которую мы реализуем в основной программе; другой — это работа Flash, и мы обязательно проверим и запишем Flash при обновлении прикладной программы; это программа управления переходом, нам нужно в конце выполнить прикладную программу, и функция перехода является необходимой. Конечно, в зависимости от различных потребностей могут быть и другие требования. Конкретно, как показано на рисунке ниже:

На рисунке выше, помимо трех основных реализаций подписи, мы также добавили функцию получения файлов IAP. Эта часть функции также необходима, но в разных режимах может быть большая разница. Потому что способ получения файлов может быть различным: Ethernet-порт, последовательный порт и т. д. Это также могут быть различные типы памяти, такие как SD-карта, U-диск и т. д. Поэтому, хотя эта функция является необходимой, способ ее реализации очень гибкий. В последующей реализации мы подробно проанализируем конкретные вопросы.
Реализация BootLoader
Теперь мы определили разделение Flash и поняли основной рабочий процесс BootLoader. Далее я расскажу о том, как реализовать программу BootLoader.
Кодирование BootLoader
Мы знаем, что при включении питания микросхема сначала запускает программу BootLoader, а затем переходит в область прикладной программы для ее выполнения. Поэтому, когда мы пишем программу BootLoader, мы сначала определяем, есть ли у системы требования IAP. Если есть запрос IAP, она переходит в режим IAP. После завершения она переходит к прикладной программе для выполнения. Если нет запроса IAP, она сразу переходит к прикладной программе для выполнения. Конкретный процесс выглядит следующим образом:

Что касается обработки IAP, в разных ситуациях будут применяться разные методы обработки. Здесь мы в основном рассмотрим программу управления переходом. Сначала определите первый адрес приложения и объявите тип указателя функции. Подробности приведены ниже:
#define ApplicationAddress 0x08004000 //Application first address definition
typedef void (*pFunction)(void); //Define the jump function pointer type
Некоторые могут спросить, что определяет такой тип указателя функции, ведь в конце концов мы переходим к функции Reset_Handler, поэтому у нас должен быть указатель функции, который может указывать на эту функцию. Далее мы можем реализовать программу перехода.
/*jump to application processing function*/
static void JumpToApplication(void)
{
uint32_tStackAddr; //Application stack address
uint32_tResetVector; //The address of the application interrupt vector table
pFunctionJumpToApp; //Define the jump function pointer
__set_PRIMASK(1); //Turn off global interrupt
StackAddr= *(__IO uint32_t*)ApplicationAddress; //0x08004000;
ResetVector = *(__IO uint32_t*)(ApplicationAddress + 4); //0x08004004;
if((StackAddr&0x2FFC0000)==0x20000000) //Check whether the stack top address is legal.
{
__set_MSP(StackAddr); //Initialize the application stack pointer
JumpToApp = (pFunction)ResetVector;
JumpToApp();
}
}
Обработка приложений
После реализации кодирования BootLoader, если мы хотим перейти к приложению для правильной работы, нам необходимо соответствующим образом изменить приложение. Есть 2 важных изменения. Если приложение является базовой программой, нам необходимо включить глобальный средний диапазон перед настройкой часов.
/*Enable global interrupt, closed in BootLoader*/
__set_PRIMASK(0);
В то же время необходимо изменить смещение адреса таблицы векторов среднего уровня. Для используемого нами STM32F07 его можно изменить непосредственно в файле system_stm32f4xx.c.
#define VECT_TAB_OFFSET 0x4000 /*!< Vector Table base offsetfield.
Затем необходимо внести необходимые изменения в среду разработки, взяв за пример используемый нами IAR EWARM V8.4. Измените настройки таблицы векторов прерываний и области хранения Flash в файле icf. Подробности приведены ниже:


После завершения вышеуказанной настройки мы можем загрузить прикладную программу и программу BootLoader для реализации правильного перехода.
Резюме
В этой статье мы реализовали простую программу BootLoader. После загрузки в целевой микроконтроллер осуществляется переход, и прикладная программа также работает нормально, что показывает, что наш проект правильный, и на его основе можно добавить различные функции для реализации соответствующего приложения IAP.
Следует отметить, что мы отключили глобальное прерывание в программе BootLoader, и не забудьте включить глобальное прерывание до того, как приложение инициализирует системные часы, иначе SystemTick не сможет работать и произойдет аппаратная ошибка (hardfault). Однако, если приложение работает на RTOS, включение прерывания может быть неправильным, что требует внимания.




