Как разработать загрузчик для микроконтроллеров серии STM32?

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

Основной принцип работы BootLoader

Поскольку мы хотим реализовать программу BootLOader для STM32, сначала мы должны понять основные принципы работы программы BootLOader.

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

BootLoader and APP start independently
BootLoader and APP start independently

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

BootLoader and APP run at the same time (APP is stored in internal Flash)
BootLoader and APP run at the same time (APP is stored in internal Flash)

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

BootLoader and APP run at the same time (APP is stored in external Flash)
BootLoader and APP run at the same time (APP is stored in external Flash)

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

Проектирование загрузчика для STM32

Быстрое планирование

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

Flash Division of MCU - Bootloader and APP
Flash Division of MCU - Bootloader and APP

Мы позволили программе BootLoader занять 16 КБ памяти. Но она может работать со всем объемом флэш-памяти.

Структура BootLoader

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

BootLoader Program Functions
BootLoader Program Functions

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

Реализация BootLoader

Теперь мы определили разделение Flash и поняли основной рабочий процесс BootLoader. Далее я расскажу о том, как реализовать программу BootLoader.

Кодирование BootLoader

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

Flow Chart of IAP Mode in BootLoader Operation
Flow Chart of IAP Mode in BootLoader Operation

Что касается обработки 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. Подробности приведены ниже:

Linker configuration file editor - Vector Table
Linker configuration file editor - Vector Table
Linker configuration file editor - Memory Regions
Linker configuration file editor - Memory Regions

После завершения вышеуказанной настройки мы можем загрузить прикладную программу и программу BootLoader для реализации правильного перехода.

Резюме

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

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

Поделиться:

Прокрутить вверх

Instant Quote