Развертывание среды разработки для STM32

Большая часть статьи — это текстовое описание видео: 

В статье показано, как с помощью бесплатных кроссплатформенных инструментов развернуть среду разработки для микроконтроллеров STM32.

Программы и библиотеки, о которых будет идти речь, уже объединены в готовые бесплатные среды разработки, например CooCox CoIDE или SW4STM32. Первая только для Windows, а вторая для множества операционных систем, но ссылки для скачивания появляются только после регистрации.

Мы соберем свою среду, чтобы лучше ее понимать и контролировать.

Eclipse

Грубо говоря, Eclipse — это продвинутый редактор кода. Eclipse никак не привязан к STM32 и с его помощью можно вести разработку на разных языках программирования и для разных целей.

Перейдем на страницу загрузки пакетов Eclipse и скачаем Eclipse IDE for C/C++ Developers.

Установка заключается в распаковке скаченного архива в удобное место. На Windows я устанавливаю Eclipse в папку Program Files, на Linux — в /opt, то же самое с любыми другими программами и библиотеками у которых нет установочного файла.

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

При первом запуске будет открыта вкладка Welcome, которую нужно просто закрыть.

GCC ARM

GCC ARM — это набор инструментов для сборки программы, таких как компилятор, линковщик, отладчик и много другое. GCC ARM имеет косвенное отношение к STM32 и позволяет разрабатывать программы под любые ARM-процессоры.

Идем на официальный сайт и выбираем версию для своей операционной системы.

Просто распаковываем архив в удобное место.

GNU ARM Eclipse

GNU ARM Eclipse — это дополнение для Eclipse, которое поможет связать его с GCC ARM.

Для его установки запустим Eclipse и выберем меню Help -> Install New Software:

eclipse-help-install-new-software

В появившемся окне нажмем кнопку Add, чтобы добавить источник дополнения.

В поле Name укажем имя источника «GNU ARM Eclipse Plug-ins», а в поле Location ссылку на источник: http://gnuarmeclipse.sourceforge.net/updates

eclipse-add-repository-gnu-arm-eclipse-plug-ins

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

Ставим галочку напротив GNU ARM C/C++ Cross Development Tools и нажимаем Next.

Затем проходим процедуру установки нажимая Next и соглашаясь с условиями лицензии.

Установка займет некоторое время. В какой-то момент в диалоговом окне появится вопрос, продолжить ли установку неподписанного содержимого, смело жмем OK.eclipse-security-warning

В конце установки будет предложено перезапустить Eclipse. Соглашаемся.

Создание проекта

Теперь есть все необходимое, чтобы создать проект.

Чтобы создать проект на языке C, выберем меню File -> New -> C Project.

eclipse-file-new-c-project

Можно создать проект на языке C++, но возникнет множество нюансов, которые усложнят разработку. О них я расскажу в другой статье.

В появившемся окне будет предложено задать имя проекта, его расположение, тип проекта и набор инструментов.

Проект я назову example. Тип — пустой проект (Empty Project). Набор инструментов — Cross ARM GCC, что соответствует ранее установленному GCC ARM.eclipse-c-project

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

eclipse-select-configurations

Далее будет предложено уточнить набор инструментов и указать путь к ним. По умолчанию выбран набор GCC ARM: «GNU Tools for ARM Embedded Processors (arm-none-eabi-gcc)«. В качестве пути нужно указать путь к папке GNU ARM.

eclipse-toolchain

После нажатия Finish проект будет создан. Его иерархическая структура отображается во вкладке Project Explorer. В этой же вкладе может отображаться множество проектов.

Сборка проекта

Чтобы собрать проект, необходимо создать хотя бы один файл с исходным кодом. Создадим файл main.c c функцией main().

Вызовем контекстное меню на имени проекта и выберем New -> Source File.eclipse-new-source-file

В поле Source File укажем имя файла main.c и нажмем Finish.eclipse-new-source-file

В файл добавим следующий код:


int main() {
	while(1);

	return 0;
}

Сохраним файл комбинацией Ctrl+S. И соберем проект комбинацией Ctrl+B или нажав на иконкуeclipse-%d0%b8%d0%ba%d0%be%d0%bd%d0%ba%d0%b0-build

Eclipse может автоматически сохранять файлы перед сборкой, но для это нужно выбрать меню Windows -> Preferences, перейти в General -> Workspaces и поставить галочку напротив Save automatically before built.

При сборке проекта мы получим ошибку, потому что не хватает двух библиотек (CMSIS и STM32Cube), о которых далее пойдет речь.

CMSIS

CMSIS — это базовая библиотека для ARM-микроконтроллеров.

Ее можно скачать с сайта ARM после регистрации.

CMSIS распространяется в виде архива, который нужно распаковываем в удобное место.

Подключение библиотеки будет разобрано в соответствующем разделе далее.

В CMSIS есть папка

Device/ARM/ARMCMx/Source/GCC/

Есть несколько папок ARMCMx, которые соответствуют разным ядрам микроконтроллеров. Имя папки расшифровывается как ARM Cortex-M. Выбираем папку в соответствии с микроконтроллером.

Из этой папки в папку проекта требуется скопировать пару файлов:

  • gcc_arm.ld
  • startup_ARMCMx.c

Чтобы файлы появились в Eclipse, нажмите F5 в Project Explorer, либо в контекстном меню проекта выберете Refresh. Это обновит список файлов.

Оба файла придется отредактировать.

gcc_arm.ld

Это скрипт для линковки проекта. Он отвечает за распределение разных областей памяти в микроконтроллере.

В этом файле задается объем постоянной и оперативной памяти микроконтроллера, а также их начальные адреса. Эти параметры нужно отредактировать в соответствии с используемым микроконтроллером.

Параметры задаются в самом начале файла с помощью следующего кода:


/* Linker script to configure memory regions. */
MEMORY
{
  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x40000   /* 256k */
  RAM (rwx)  : ORIGIN = 0x20000000, LENGTH = 0x08000   /*  32k */
}

В переменной ORIGIN задается начальный адрес области памяти, а в LENGTH — ее объем в байтах. FLASH — это постоянная память, RAM — оперативная.

В STM32 начальный адрес постоянной памяти — 0x08000000, оперативной (как и указано) — 0x20000000.

startup_ARMCMx.c

Это файл с исходным кодом на языке C, который содержит базовый код программы и таблицу прерываний. Кроме того в файле задается объем стека и кучи. Код из этого файла выполняется до вызова функции main() и вызывает функцию main().

Таблица прерываний в этом файле скорее всего не соответствует таблице используемого микроконтроллера. Файл нужно отредактировать в соответствии с таблицей прерываний микроконтроллера. Об этом речь пойдет позже.

Размер кучи и стека должен соответствовать потребностям проекта и объему оперативной памяти микроконтроллера.

Размер кучи и стека задается следующим кодом:

...
  #define __STACK_SIZE 0x00000400
...
  #define __HEAP_SIZE 0x00000C00
...

__STACK_SIZE определяет объем стека. __HEAP_SIZE — объем кучи. В сумме оба значения не должны превышать объем оперативной памяти.

STM32Cube

STM32Cube — это библиотека с открытым исходным кодом для микроконтроллеров STM32, которую выпускает производитель микроконтроллеров. Библиотека пришла на смену STM32 Standard Peripheral Libraries (сокращенно SPL).

Для каждого семейства микроконтроллеров своя версия библиотеки STM32Cube, к названию которой прибавляется суффикс Fx или Lx, где x — число 0, 1, 2 и так далее. Например, STM32CubeF4.

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

В этой библиотеке уже содержится библиотека CMSIS в папке Drivers/CMSIS, но ее версия чаще всего не соответствует последней версии, которую предоставляет ARM.

Из STM32Cube нужно скопировать некоторые файла в свой проект:

  • Drivers/STM32xxxx_HAL_Driver/Inc/stm32xxxx_hal_conf_template.h
  • Drivers/CMSIS/Device/ST/STM32xxxx/Source/Templates/system_stm32xxxx.c

STM32xxxx и stm32xxxx разное для разных микроконтроллеров.

Обновим список файлов в Eclipse, как это писалось выше.

stm32xxxx_hal_conf_template.h

Это заголовочный файл, который используется библиотекой STM32Cube для подключения заголовочных файлов периферии микроконтроллера. Кроме того он содержит некоторые настройки.

Файл нужно переименовать в stm32xxxx_hal_conf.h, то есть удалить суффикс template.

Его не требуется нигде подключать, об этом заботится сама библиотека.

Если микроконтроллер тактируется внешним источником (например, кварцевым резонатором или генератором), то нужно указать частоту этого источника в определении HSE_VALUE.

system_stm32xxxx.c

Код в этом файле содержит некоторые настройки и важную функцию SystemInit(), которая вызывается до вызова функции main().

Функция SystemInit() вызывается в файле startup_ARMCMx.c и предназначена для базовой настройки микроконтроллера. Можно изменить код этой функции, например, для настройки тактирования микроконтроллера.

Частоту внешнего тактирования в этом файле лучше не задавать.

Настройка проекта и подключение библиотек

После всего проделанного выше структура проекта должна выглядеть следующим образом:

eclipse-project-ecplorer-example-1

Если сейчас вы попробуете собрать проект (Ctrl+B), то получите сообщение об ошибке.

Откроем настройки проекта с помощью меню Project -> Properties. Появится окно настроек. В дереве слева выберем C/C++ Build -> Settings. В основной части окна нам нужна вкладка Tool Settings, здесь мы будем проводить большую часть времени.

Вкладка содержит дерево настроек, выберем первый пункт Target Processor, чтобы настроить ядро микроконтроллера. В поле ARM family выберем ядро, например cortex-m4 для микроконтроллера STM32F4xx. Остальные поля трогать не нужно.

eclipse-arm-family

Перейдем к пункту Cross ARM C Linker -> Genaral с основными настройками линковщика. В Script files нужно добавить скрипт линковки gcc_arm.ld. Нажмем на иконку на которой нарисован «+» и в диалоговом окне нажмем Workspace, чтобы выбрать файл из рабочей области, и выберем файл gcc_arm.ld.

eclipse-add-gcc_arm-ld

Перейдем к пункту Cross ARM C Compiler — Includes для настройки подключаемых файлов. В Include paths добавим пути для поиска заголовочных файлов. Нужно добавить следующие пути:

  • <Папка CMSIS>/CMSIS/Include
  • <Папка STM32Cube>/Drivers/STM32xxxx_HAL_Driver/Inc
  • <Папка STM32Cube>/Drivers/CMSIS/Device/ST/STM32xxxx/Include
  • ${workspace_loc:/${ProjName}}

eclipse-include-paths

Последняя папка указывает на папку нашего проекта в которой находится файл stm32xxxx_hal_conf.h и могут находится другие подключаемые файлы проекта.

Перейдем к пункту Cross ARM C Compiler — Preprocessor. В Defined symbols добавим определения:

  • USE_HAL_DRIVER
  • STM32xxxxxx

где STM32xxxxxx должен соответствовать используемому микроконтроллеру. Список значений можно посмотреть в файле

<Папка STM32Cube>/Drivers/CMSIS/Device/ST/STM32xxxx/Include/stm32xxxx.h

Например в файле stm32f4xx.h этот список выглядит так:

  /* #define STM32F405xx */   /*!< STM32F405RG, STM32F405VG and STM32F405ZG Devices */
  /* #define STM32F415xx */   /*!< STM32F415RG, STM32F415VG and STM32F415ZG Devices */
  /* #define STM32F407xx */   /*!< STM32F407VG, STM32F407VE, STM32F407ZG, STM32F407ZE, STM32F407IG  and STM32F407IE Devices */
  /* #define STM32F417xx */   /*!< STM32F417VG, STM32F417VE, STM32F417ZG, STM32F417ZE, STM32F417IG and STM32F417IE Devices */
  /* #define STM32F427xx */   /*!< STM32F427VG, STM32F427VI, STM32F427ZG, STM32F427ZI, STM32F427IG and STM32F427II Devices */
  /* #define STM32F437xx */   /*!< STM32F437VG, STM32F437VI, STM32F437ZG, STM32F437ZI, STM32F437IG and STM32F437II Devices */
  /* #define STM32F429xx */   /*!< STM32F429VG, STM32F429VI, STM32F429ZG, STM32F429ZI, STM32F429BG, STM32F429BI, STM32F429NG, 
                                   STM32F439NI, STM32F429IG  and STM32F429II Devices */
  /* #define STM32F439xx */   /*!< STM32F439VG, STM32F439VI, STM32F439ZG, STM32F439ZI, STM32F439BG, STM32F439BI, STM32F439NG, 
                                   STM32F439NI, STM32F439IG and STM32F439II Devices */
  /* #define STM32F401xC */   /*!< STM32F401CB, STM32F401CC, STM32F401RB, STM32F401RC, STM32F401VB and STM32F401VC Devices */
  /* #define STM32F401xE */   /*!< STM32F401CD, STM32F401RD, STM32F401VD, STM32F401CE, STM32F401RE and STM32F401VE Devices */
  /* #define STM32F411xE */   /*!< STM32F411CD, STM32F411RD, STM32F411VD, STM32F411CE, STM32F411RE and STM32F411VE Devices */     

Напротив каждого определения представлен список соответствующих ему микроконтроллеров.

В Defined symbols для микроконтроллера STM32F405RG должно быть добавлено определение STM32F405xx.

eclipse-defined-symbols

Работа с этим окном завершена. Нажимаем OK.

Уже сейчас проект может быть успешно собран. Но перестанет собираться если мы начнем вызывать функции STM32Cube, например если мы добавим в main() вызов функции HAL_Init(), самой важной функции библиотеки.

Во первых, в main.c надо подключить основной заголовочный файл библиотеки stm32xxxx.h. Для STM32CubeF4 это файл stm32f4xx.h. Вообще, везде, где предполагается использование библиотеки надо подключать этот файл.

Во вторых, надо добавить в проект файлы исходного кода библиотеки. Для этого в контекстном меню проекта выбираем New -> Folder. В диалоговом окне нажимаем Advanced и выбираем Link to alternate location (Linked Folder) и с помощью Browse указываем папку

<Папка STM32Cube>/Drivers/STM32xxxx_HAL_Driver/Src

В поле Folder name задаем имя папки, например STM32Cube.

eclipse-new-folder-stm32cube

Жмем Finish.

Теперь соответствующая папка привязана к проекту и файлы в ней будут компилироваться как и другие файлы проекта.

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

Для исключения файла из сборки вызовем на файле контекстное меню и выберем Recource Configurations -> Exclude from Build.

eclipse-exclude-from-build

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

eclipse-exclude-from-build-configurations

Можно массово исключить множество файлов, если выбрать их с зажатыми клавишами Ctrl или Shift.

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

  • stm32f4xx_hal.c, так как это основной файл библиотеки, он содержит функцию HAL_Init().
  • stm32f4xx_hal_cortex.c
  • stm32f4xx_hal_rcc.c

Функции из последних двух вызываются в функции HAL_Init().

После всех манипуляций дерево проекта будет выглядеть следующим образом:

eclipse-project-explorer-example-2

Проект должен успешно собираться.

На вкладке Console будет следующий текст:

Building target: example.elf
Invoking: Cross ARM C Linker
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections  -g -T "/home/bravikov/workspace2/example/gcc_arm.ld" -Xlinker --gc-sections -Wl,-Map,"example.map" -o "example.elf"  ./STM32Cube/stm32f4xx_hal.o ./STM32Cube/stm32f4xx_hal_cortex.o ./STM32Cube/stm32f4xx_hal_rcc.o  ./main.o ./startup_ARMCM4.o ./system_stm32f4xx.o   
Finished building target: example.elf
 
Invoking: Cross ARM GNU Create Flash Image
arm-none-eabi-objcopy -O ihex "example.elf"  "example.hex"
Finished building: example.hex
 
Invoking: Cross ARM GNU Print Size
arm-none-eabi-size --format=berkeley "example.elf"
   text	   data	    bss	    dec	    hex	filename
   1752	   1088	     28	   2868	    b34	example.elf
Finished building: example.siz

Прерывания

SysTick

SysTick — это таймер, встроенный в ядро микроконтроллера. STM32Cube использует его для отсчета времени в миллисекундах. Об этой полезной особенности библиотеки у меня есть статья.

Чтобы отсчет времени работал, в проект надо добавить правильную реализацию функции SysTick_Handler(). Это функция обрабатывает прерывания от SysTick, и должна увеличивать счетчик времени на 1.

Добавим в файл main.c следующий код:

void SysTick_Handler(void) {
    HAL_IncTick();
}

Таблица прерываний

В файле startup_ARMCMx.c задается таблица прерываний. Изначально она не соответствует реальным микроконтроллерам. Таблицу надо сформировать самостоятельно.

Файл содержит объявление функций-обработчиков прерываний:

/*----------------------------------------------------------------------------
  Exception / Interrupt Handler
 *----------------------------------------------------------------------------*/
/* Cortex-M4 Processor Exceptions */
void NMI_Handler         (void) __attribute__ ((weak, alias("Default_Handler")));
void HardFault_Handler   (void) __attribute__ ((weak, alias("Default_Handler")));
void MemManage_Handler   (void) __attribute__ ((weak, alias("Default_Handler")));
void BusFault_Handler    (void) __attribute__ ((weak, alias("Default_Handler")));
void UsageFault_Handler  (void) __attribute__ ((weak, alias("Default_Handler")));
void SVC_Handler         (void) __attribute__ ((weak, alias("Default_Handler")));
void DebugMon_Handler    (void) __attribute__ ((weak, alias("Default_Handler")));
void PendSV_Handler      (void) __attribute__ ((weak, alias("Default_Handler")));
void SysTick_Handler     (void) __attribute__ ((weak, alias("Default_Handler")));

...

За объявлениями следует таблица прерываний:

/*----------------------------------------------------------------------------
  Exception / Interrupt Vector table
 *----------------------------------------------------------------------------*/
const pFunc __Vectors[] __attribute__ ((section(".vectors"))) = {
  /* Cortex-M4 Exceptions Handler */
  (pFunc)&__StackTop,                       /*      Initial Stack Pointer     */
  Reset_Handler,                            /*      Reset Handler             */
  NMI_Handler,                              /*      NMI Handler               */
  HardFault_Handler,                        /*      Hard Fault Handler        */
  MemManage_Handler,                        /*      MPU Fault Handler         */
  BusFault_Handler,                         /*      Bus Fault Handler         */
  UsageFault_Handler,                       /*      Usage Fault Handler       */
  0,                                        /*      Reserved                  */
  0,                                        /*      Reserved                  */
  0,                                        /*      Reserved                  */
  0,                                        /*      Reserved                  */
  SVC_Handler,                              /*      SVCall Handler            */
  DebugMon_Handler,                         /*      Debug Monitor Handler     */
  0,                                        /*      Reserved                  */
  PendSV_Handler,                           /*      PendSV Handler            */
  SysTick_Handler,                          /*      SysTick Handler           */

...

Массив __Vectors[] содержит имена функций-обработчиков прерываний.

Первая часть таблицы (до SysTick_Handler включительно) общая для всех микроконтроллеров. Остальное нужно дописать аналогичным образом на основании документации на микроконтроллер.

Заключение

Я описал только самое необходимое. Не коснулся темы программаторов, отладки и самого процесса разработки. Это необъятные темы, которые я буду раскрывать в будущем.

Ссылки

  1. Видео-скринкаст «Eclipse и GNU Tools для разработки под ARM-микроконтроллеры«.
  2. Eclipse IDE for C/C++ Developers.
  3. GNU Tools for ARM Embedded Processors.
  4. GNU ARM Eclipse Plug-ins.
  5. CMSIS.
  6. STM32Cube.
  7. Статья «Начало работы с STM32 в Keil MDK-ARM«.
  8. Статья «Приоритеты прерываний в Cortex-M и их настройка в STM32Cube«.
  9. Статья «Отсчет времени в STM32Cube«.
  10. Статья «ST-Link + MDK-ARM + Linux«.
Реклама

Автор

Дмитрий Бравиков

Инженер. Электронщик. Программист.

Развертывание среды разработки для STM32: Один комментарий

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход /  Изменить )

Google photo

Для комментария используется ваша учётная запись Google. Выход /  Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход /  Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход /  Изменить )

Connecting to %s