Здесь я расскажу как создать минимальный проект на CMSIS с использованием «родной» IDE для микроконтроллеров STM – STM32CubeIDE.
Возможно STM32CubeIDE и обладает рядом недостатков, но у нее, на мой взгляд, есть несколько преимуществ – таких как проприетарность и бесплатность, ради которых, как минимум, стоит обратить внимание на эту среду разработки, если вы не сделали этого раньше.
![](https://habrastorage.org/r/w780q1/webt/dv/qc/r8/dvqcr8nj-bvc6u_45zida8xayd8.jpeg)
Объектом прошивки выбран не очень распространенный микроконтроллер STM32F072 с ядром ARM Cortex-M0, для более привычных STM32F103 на ARM Cortex-M3, с поправкой на ядро, процесс идентичен.
Все необходимые ресурсы можно скачать с сайта st.com, и вот что понадобится:
После установки, запуска и выбора папки Workspace можно начать создание проекта. На текущий момент STM32CubeIDE версии 1.1.0, так что по расположению различных настроек следует исходить из этого.
Создание нового проекта — File/New/STM32Project. После некоторого раздумия появляется окно выбора микроконтроллера, в моем случае это STM32F072RB в корпусе LQFP64, выбираю нужную строку, жму далее. Далее предлагается выбрать имя проекта, расположение, язык программирования C/C++, исполняемый файл/статическая библиотека и будет-ли проект сгенерирован с помощью CubeMX или сами с усами. Генерация кубом, в данном случае не нужна, поэтому тип проекта Empty — финиш.
![](https://habrastorage.org/r/w780q1/webt/gy/fp/3j/gyfp3j-mz4lkfbrdrelyxutxowe.jpeg)
![](https://habrastorage.org/r/w780q1/webt/n5/o7/wp/n5o7wpxecjf5zhppkvaxqgim5ru.jpeg)
![](https://habrastorage.org/r/w780q1/webt/6l/9h/xq/6l9hxqj1wewf29pmzhofurntiku.jpeg)
Слева, в окне Project Explorer, появилось дерево проекта, правда он не совсем Empty, как заказывали. Впринципе, если устраивает сгенерированная структура папок, можно добавить туда файлы из библиотеки CMSIS и работать дальше, но здесь я покажу как можно привести структуру проекта в гармонию со своим чувством прекрасного, поэтому удаляется всё, кроме скрипта линкера т.е. файла c расширением .ld — он еще пригодится.
![](https://habrastorage.org/r/w780q1/webt/8h/ny/-o/8hny-ox3erjy_uyxcdw7uehosco.jpeg)
![](https://habrastorage.org/r/w780q1/webt/wy/bd/l7/wybdl7b4d7nuunc8qpbaafov1pi.jpeg)
Все манипуляции с папками и файлами можно проводить как в проводнике так и внутри IDE, нажав правой кнопкой на название проекта, к примеру: правая кнопка –> new –> Folder. Если структура проекта изменялась вне IDE, то нужно просто обновить проект: правая кнопка –> Refresh.
Мой вариант структуры проекта выглядит так:
![](https://habrastorage.org/r/w780q1/webt/t4/nx/jw/t4nxjw8u631-l7su5nzua6wg_f0.jpeg)
Теперь нужно перенести файлы библиотеки CMSIS в проект. Библиотека состоит из файлов ядра и файлов периферии. Файлы ядра начинаются с core_ или cmsis_ они общие для всех микроконтроллеров, использующих данное ядро. Файлы периферии содержат в названии наименование микроконтроллера stm32 и специфичны для конкретного производителя, в данном случае, компании STM.
В распакованном виде архив содержит папку STM32Cube_FW_F0_V1.11.0, все пути указаны относительно этой папки. Итого, нужно скопировать:
В CMSIS\inc:
В CMSIS\src:
В Startup:
Так выглядит проект в заполненном виде.
![](https://habrastorage.org/r/w780q1/webt/l9/u5/kf/l9u5kfyx7xbvqsoouzqfyqofkdg.jpeg)
Так как были проведены некоторые манипуляции с папками проекта, нужно отобразить это в настройках.
Правая кнопка по названию проекта -> Properties -> C/C++ Build -> Settings -> Tool Settings -> MCU GCC Linker -> General – здесь нужно указать новое расположение скрипта линкера с помощью кнопки Browse…
![](https://habrastorage.org/r/w780q1/webt/va/6d/d5/va6dd5qv_-xohabg-hqzffunypu.jpeg)
Также нужно указать пути к файлам проекта
Properties -> C/C++ General -> Includes
Properties -> C/C++General -> Source Location
В Includes пути к папкам inc, а в Source Location логично было-бы к папкам src, но если так сделать, то в дереве проекта будут отдельно добавлены эти папки. Чтобы не загромождать визуально дерево, в Source Location можно указать корневые папки Core, CMSIS и Startup.
![](https://habrastorage.org/r/w780q1/webt/ba/r9/te/bar9temkumw_ffjxmjz0dc5ehcu.jpeg)
![](https://habrastorage.org/r/w780q1/webt/wt/_v/pa/wt_vpal_mdt3buqheo5ies8tyym.jpeg)
Для того чтобы проект скомпилировался нужно раскомментировать в файле stm32f0xx.h строку с названием микроконтроллера ну и конечно же в main.c добавить функцию main.
![](https://habrastorage.org/r/w780q1/webt/0m/3b/vq/0m3bvqzgvguepvzxghc3w66b4r8.jpeg)
![](https://habrastorage.org/r/w780q1/webt/8n/r2/tl/8nr2tlojommjirdqgc1poowjwq4.jpeg)
Собственно всё. Безошибочная компиляция и сразу же куда-то подевалось целых полтора килобайта памяти ОЗУ она же RAM, и сразу же вспоминается стек и куча, в процессе создания проекта они нигде не упоминались. Величина стека и кучи указана в файле скрипта линкера, тот что с расширением .ld, их можно и нужно изменять в соответствии с требованиями проекта. Эти значения находятся в начале файла в виде меток _Min_Heap_Size/_Min_Stack_Size с указанием размера в шестнадцатеричном виде.
![](https://habrastorage.org/r/w780q1/webt/cj/nt/l3/cjntl3rh8a3zjd7ng4vb-navi_g.jpeg)
В качестве примера, приведу небольшой проект традиционного мигания светодиодом.
Светодиод будет мигать на отладочной плате STM32F072B-DISCO, тактирование осуществляться от внутреннего генератора HSI48 частотой 48 МГц, а в качестве источника задержки использоваться таймер SysTick, генерирующий прерывания с периодом в 1 мс, при помощи которых отсчитывается точное время задержки. Светодиод подключен к выводу 6 порта С, настроенного на выход push-pull.
Надеюсь, данная информация кому-то пригодится, т.к. в свое время, несмотря на обилие материалов по программированию STM32, мне пришлось перелопатить достаточно много мануалов, чтобы осознать вещи, кажущиеся сейчас очевидными.
Возможно STM32CubeIDE и обладает рядом недостатков, но у нее, на мой взгляд, есть несколько преимуществ – таких как проприетарность и бесплатность, ради которых, как минимум, стоит обратить внимание на эту среду разработки, если вы не сделали этого раньше.
![](https://habrastorage.org/webt/dv/qc/r8/dvqcr8nj-bvc6u_45zida8xayd8.jpeg)
Объектом прошивки выбран не очень распространенный микроконтроллер STM32F072 с ядром ARM Cortex-M0, для более привычных STM32F103 на ARM Cortex-M3, с поправкой на ядро, процесс идентичен.
Все необходимые ресурсы можно скачать с сайта st.com, и вот что понадобится:
- Сама IDE, я использую Windows версию, но также доступны версии под Mac и Linux
- Библиотека CMSIS для ARM Cortex-M0, она находится в архиве STM32CubeFx, разбитом по версиям ядра. Сам архив, помимо CMSIS, содержит великое множество других ресурсов начиная от примеров работы с периферией до драйверов USB, собственно, именно этот архив используется, если создавать проект с помощью STM32Cube
- Не помешает Datasheet и Reference Manual
После установки, запуска и выбора папки Workspace можно начать создание проекта. На текущий момент STM32CubeIDE версии 1.1.0, так что по расположению различных настроек следует исходить из этого.
Создание нового проекта — File/New/STM32Project. После некоторого раздумия появляется окно выбора микроконтроллера, в моем случае это STM32F072RB в корпусе LQFP64, выбираю нужную строку, жму далее. Далее предлагается выбрать имя проекта, расположение, язык программирования C/C++, исполняемый файл/статическая библиотека и будет-ли проект сгенерирован с помощью CubeMX или сами с усами. Генерация кубом, в данном случае не нужна, поэтому тип проекта Empty — финиш.
![](https://habrastorage.org/webt/gy/fp/3j/gyfp3j-mz4lkfbrdrelyxutxowe.jpeg)
![](https://habrastorage.org/webt/n5/o7/wp/n5o7wpxecjf5zhppkvaxqgim5ru.jpeg)
![](https://habrastorage.org/webt/6l/9h/xq/6l9hxqj1wewf29pmzhofurntiku.jpeg)
Слева, в окне Project Explorer, появилось дерево проекта, правда он не совсем Empty, как заказывали. Впринципе, если устраивает сгенерированная структура папок, можно добавить туда файлы из библиотеки CMSIS и работать дальше, но здесь я покажу как можно привести структуру проекта в гармонию со своим чувством прекрасного, поэтому удаляется всё, кроме скрипта линкера т.е. файла c расширением .ld — он еще пригодится.
![](https://habrastorage.org/webt/8h/ny/-o/8hny-ox3erjy_uyxcdw7uehosco.jpeg)
![](https://habrastorage.org/webt/wy/bd/l7/wybdl7b4d7nuunc8qpbaafov1pi.jpeg)
Все манипуляции с папками и файлами можно проводить как в проводнике так и внутри IDE, нажав правой кнопкой на название проекта, к примеру: правая кнопка –> new –> Folder. Если структура проекта изменялась вне IDE, то нужно просто обновить проект: правая кнопка –> Refresh.
Мой вариант структуры проекта выглядит так:
- Startup – здесь будет храниться скрипт линкера, тот самый, оставшийся от сгенерированного проекта, а также startup файл взятый из CMSIS
- CMSIS\src и CMSIS\inc – здесь будут лежать исходники, файлы с расширением .c в папке scr и заголовочные файлы с расширением .h в папке inc соответственно, относящиеся к библиотеке CMSIS
- Core\src и Core\inc – здесь будет расположен собственно сам проект, для начала стоит положить туда main.c и main.h
![](https://habrastorage.org/webt/t4/nx/jw/t4nxjw8u631-l7su5nzua6wg_f0.jpeg)
Теперь нужно перенести файлы библиотеки CMSIS в проект. Библиотека состоит из файлов ядра и файлов периферии. Файлы ядра начинаются с core_ или cmsis_ они общие для всех микроконтроллеров, использующих данное ядро. Файлы периферии содержат в названии наименование микроконтроллера stm32 и специфичны для конкретного производителя, в данном случае, компании STM.
В распакованном виде архив содержит папку STM32Cube_FW_F0_V1.11.0, все пути указаны относительно этой папки. Итого, нужно скопировать:
В CMSIS\inc:
- Drivers\CMSIS\Include\cmsis_compiler.h
- Drivers\CMSIS\Include\cmsis_gcc.h
- Drivers\CMSIS\Include\cmsis_version.h
- Drivers\CMSIS\Include\core_cm0.h
- Drivers\CMSIS\Device\ST\STM32F0xx\Include\stmf0xx.h
- Drivers\CMSIS\Device\ST\STM32F0xx\Include\stm32f072xb.h
- Drivers\CMSIS\Device\ST\STM32F0xx\Include\system_stm32f0xx.h
В CMSIS\src:
- Drivers\CMSIS\Device\ST\STM32F0xx\Source\Templates\system_stm32f0xx.c
В Startup:
- Drivers\CMSIS\Device\ST\STM32F0xx\Source\Templates\gcc\startup_stm32f072xb.s
Так выглядит проект в заполненном виде.
![](https://habrastorage.org/webt/l9/u5/kf/l9u5kfyx7xbvqsoouzqfyqofkdg.jpeg)
Так как были проведены некоторые манипуляции с папками проекта, нужно отобразить это в настройках.
Правая кнопка по названию проекта -> Properties -> C/C++ Build -> Settings -> Tool Settings -> MCU GCC Linker -> General – здесь нужно указать новое расположение скрипта линкера с помощью кнопки Browse…
![](https://habrastorage.org/webt/va/6d/d5/va6dd5qv_-xohabg-hqzffunypu.jpeg)
Также нужно указать пути к файлам проекта
Properties -> C/C++ General -> Includes
Properties -> C/C++General -> Source Location
В Includes пути к папкам inc, а в Source Location логично было-бы к папкам src, но если так сделать, то в дереве проекта будут отдельно добавлены эти папки. Чтобы не загромождать визуально дерево, в Source Location можно указать корневые папки Core, CMSIS и Startup.
![](https://habrastorage.org/webt/ba/r9/te/bar9temkumw_ffjxmjz0dc5ehcu.jpeg)
![](https://habrastorage.org/webt/wt/_v/pa/wt_vpal_mdt3buqheo5ies8tyym.jpeg)
Для того чтобы проект скомпилировался нужно раскомментировать в файле stm32f0xx.h строку с названием микроконтроллера ну и конечно же в main.c добавить функцию main.
![](https://habrastorage.org/webt/0m/3b/vq/0m3bvqzgvguepvzxghc3w66b4r8.jpeg)
![](https://habrastorage.org/webt/8n/r2/tl/8nr2tlojommjirdqgc1poowjwq4.jpeg)
Собственно всё. Безошибочная компиляция и сразу же куда-то подевалось целых полтора килобайта памяти ОЗУ она же RAM, и сразу же вспоминается стек и куча, в процессе создания проекта они нигде не упоминались. Величина стека и кучи указана в файле скрипта линкера, тот что с расширением .ld, их можно и нужно изменять в соответствии с требованиями проекта. Эти значения находятся в начале файла в виде меток _Min_Heap_Size/_Min_Stack_Size с указанием размера в шестнадцатеричном виде.
![](https://habrastorage.org/webt/cj/nt/l3/cjntl3rh8a3zjd7ng4vb-navi_g.jpeg)
В качестве примера, приведу небольшой проект традиционного мигания светодиодом.
Светодиод будет мигать на отладочной плате STM32F072B-DISCO, тактирование осуществляться от внутреннего генератора HSI48 частотой 48 МГц, а в качестве источника задержки использоваться таймер SysTick, генерирующий прерывания с периодом в 1 мс, при помощи которых отсчитывается точное время задержки. Светодиод подключен к выводу 6 порта С, настроенного на выход push-pull.
Надеюсь, данная информация кому-то пригодится, т.к. в свое время, несмотря на обилие материалов по программированию STM32, мне пришлось перелопатить достаточно много мануалов, чтобы осознать вещи, кажущиеся сейчас очевидными.