Stm32cubeide как поменять микроконтроллер
Скачать версию STM32CubeIDE 1.9.0 без регистрации и смс для Windows или Linux можно в телеграм-канале:
При первом запуске программа предложит обозначить папку, где будут хранится проекты, указываем. Далее жмём Start new STM32 project либо через ( File -> New -> STM32 Project )

Выбираем необходимый микроконтроллер, у меня это всем известный STM32F103C8T6 и жмём Next :

Называем проект и жмём Finish

Включаю последовательную отладку (по SWD — Serial Wire Debug), чтоб использовать ST-LINK
SYS -> Debug -> Serial Wire

Тактирование от внешнего кварцевого резонатора
RCC -> HSE (High Speed Clock) -> Crystal/Ceramic Resonator

Во вкладке настройки тактовой системы вводим 72 МГц и жмём ввод, подтверждаем предложенное решение

Настраиваем вывод PC13 (к нему подключен зеленый светодиод) как двухтактный выход ПКМ на выводе -> GPIO_Output

Далее слева в дереве проекта в папке Src двойной щелчок по главному файлу main.c

Написан простейший код мигания светодиодом (он подключен в выводу PC13 ).
Значение в регистре ODR (Output Data Register) меняется каждый раз благодаря логической операции ИСКЛЮЧАЮЩЕЕ ИЛИ.
Ну, а со стандартной функцией задержки всё и так понятно.
GPIOC->ODR ^= GPIO_ODR_ODR13; // same: HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); HAL_Delay(500); // delay 0.5s
Собираем проект (Ctrl + B) либо щелчок по молоточку. Ошибок и предупреждений нет.

Запускаем отладку ( F11 либо Run -> Debug ). Переключаемся в пространство отладки.

Возможно придется обновить прошивку программатора-отладчика ST-LINK (делается это в два клика) и далее в настройках можно будет его лицезреть.

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

Теперь нажимая на кнопки продолжения/паузы смотрим за значениями в нужных регистрах.

В этой программе это регистр выходных данных ODR, бит ODR13, когда там нуль, то СИД светится, когда единица, то нет (т.к. светодиод подключен к плюсу на отладочной плате).

Ну а в железе это вот этот изменяющийся бит выглядит как мигание светодиода:
Переползая с AVR на STM32

В конце 90-х, фирма Atmel ворвалась на рынок микроконтроллеров со своей 8-битной архитектурой AVR с достаточно простой периферией, заманчивыми электрическими параметрами и выполнявшей большинство инструкций за такт. Чтобы переманить разработчиков с ставших уже популярными PIC и уже набившей оскомину 51 архитектуры (микроконтроллеры на которой выпускались и самой Atmel), Atmel немало вложилось, чтобы поддерживать сообщество разработчиков, делать документацию понятной и доступной и, самое главное, обеспечить разработчиков бесплатной доступной полноценной средой разработки. Так появились компилятор gcc для avr со всеми тулчейнами и причиндалами и AVR Studio, позже ставшая Atmel Studio – лицензированная Visual Studio от Microsoft и переделанная под нужды архитектуры. В итоге, любой любознательный разработчик с доступом в интернет мог за полчаса организовать себе среду разработки и с головой окунуться в документацию и сообщество AVR.
В середине нулевых, со своими достаточно мощными 32-битными микроконтроллерами с ядром популярной архитектуры ARM, на рынок ворвалась фирма STMicroelectronics. И хотя ARM ядра осваивали и другие производители, включая и Atmel, решения от STM отличались достаточно продуманной богатой периферией вкупе с вычислительной мощью 32-битного ядра ARM, и при этом сравнительно небольшой стоимостью.
Но! В сравнении с той же AVR, документация запутанная и невнятная, вкладываться в поддержку сообщества разработчиков они, видимо, не посчитали нужным. Поэтому, любопытный разработчик желающий начать изучать эти микроконтроллеры, сталкивался с кучей разнообразных вариантов среды разработки от сторонних производителей. Какие-то – платные и давали компилировать лишь маленький код, какие-то – построенные энтузиастами на чём-то бесплатном с помощью изоленты, и потому работающее через пень колоду. Всё это вкупе с кошмарной документацией, больше похожей на игру в «казачки-разбойнички», где чтобы найти нужную информацию по одному микроконтроллеру нужно пролистывать много разных отдельных файлов…
Нужно ли говорить, что любопытные разработчики, решившие освоить хоть что-нибудь, потыкавшись, всё-таки выбирали для начала AVR.
Таким любопытным разработчиком и был я где-то 5 лет назад, погрузившись в AVR.
Столкнувшись с необходимостью больших вычислительных способностей, я несколько раз пытался влиться в струю STM32, даже обзавёлся платой Discovery, но глючность бесплатных сред разработки и жуткое неудобство освоения архитектуры останавливали меня от этой затеи.

Так продолжалось до недавних пор.
Анатоллик и КубеИде
Видимо, особенно на фоне того что после покупки Atmel Microchip’ом, PIC и AVR теперь один и тот же конкурент, менеджеры из STM таки решили что негоже разбрасываться неокрепшими умами потенциальных разработчиков. Мало того, что вкладывается немало сил в причёсывание и структурирование документации (впрочем, «казачки-разбойнички» никуда не делись), так ещё в 2018 году STMicroelectronics разродилась покупкой одной из наиболее удачных платных сред разработки – Atollic TRUEStudio. А недавно на сайте появилась информация, что теперь официальной средой для разработки стала STM32CubeIDE, а Атоллик больше не поддерживается.
Обе среды разработки основаны на Eclipse, обе снабжены тулчейном и всеми необходимыми библиотеками, связанными с ARM и МК STM32, поддерживают дебаг через ST-Link, и позволяют создать шаблон проекта буквально в пару кликов мышкой, выбрав нужный МК из списка. Причём STM32CubeIDE позволяет в графическом интерфейсе задать начальные настройки портов и периферии, на основе которых сгенерируется код.
Любопытно, что когда я подключил свою плату STM32VLDiscovery, мне написали что мол, программатор ST-Link v1, который установлен на плате, не поддерживается. Нужна версия 2, не меньше. Ну а то ж! С её выпуска прошло аж 8 лет, кому нужно поддерживать такую древность.
Поэтому пришлось пользоваться отдельным STM32 ST-Link Utility
Та ещё ардуйня
Многие (да и я не в последнюю очередь) критикуют среду Arduino за то, что она приучает разработчиков вместо работы с регистрами процессора вызывать какие-то абстрагированные функции, которые медленно и печально за несколько десятков тактов приходят к тому же результату, которого можно было бы достичь за один такт. В результате получается неэффективное приложение, а разработчики лепят код, не желая разбираться в устройстве микроконтроллера.
Но тут приходят они! Библиотеки аппаратной абстракции для STM32. В Atollic Truestudio продвигалась библиотека SPL, в то время как STM32CubeIDE пропихивает «обновлённый» вариант, которая так и называется – HAL.
Для примера, допустим, я хочу помигать светодиодом на свежеприобретённой у китайцев плате с STM32F103C8 на борту:

Для этого создаём проект, выбираем микроконтроллер


Система генерирует нам проект с кучей файлов. Включаем сразу оптимизацию (потому что без нее совсем плохо и печально)

И компилируем проект…

2,64, мать его, килобайта! Пустой проект! В котором ничего ещё нет! Ладно, архитектура такая, большая таблица векторов прерываний, плюс основные обработчики на то на сё, пусть 400, ну ладно, пусть 500 байт, но почти три килобайта! Хорошо что у меня МК с флешем 64кБ, а не 16… Это всё не считая того что этот самый HAL на системный таймер тиков без спроса вешает прерывание, которое срабатывает 1000 раз в секунду.
Хорошо, добавляем в конец main простой код для ритмичного мигания светодиодом. Делаем всё с использованием функций HAL. Что-то типа такого
// Включаем такирование порта ввода-вывода
__HAL_RCC_GPIOC_CLK_ENABLE();
// Инициализируем ножку PC13
GPIO_InitTypeDef init_gpio;
init_gpio.Pin = GPIO_PIN_13; // здесь можно через | объединить несколько и настроить их одной командой
init_gpio.Mode = GPIO_MODE_OUTPUT_PP; // Вывод, push-pull
init_gpio.Pull = GPIO_NOPULL; // Подтягивающие резисторы не нужны
init_gpio.Speed = GPIO_SPEED_FREQ_LOW; // Низкая скорость работы
HAL_GPIO_Init(GPIOC, &init_gpio);
uint8_t flsh = 0;
for (;;) else
flsh++;
for (uint32_t i = 0 ; i < 200000 ; i++)
>
К слову, инициализацию порта можно оставить на откуп генератору кода, покликав мышкой в нужных местах при создании проекта.
Итак, компилируем. Та-дам! Код уже занимает 3,22 кБ! Распух более чем на полкило!
Почему так происходит? Да потому, что при использовании каждой драной функции HAL, линкер тянет огромную процедурину в память. К примеру, так выглядит HAL_GPIO_Init, настраивающая порт:

И это только начало! Там ещё ниже продолжение на 2 экрана.
Можно только представить, сколько времени выполнения отнимает то, что можно сделать записью в пару регистров. Я уж не говорю про отожранную флэш-память.
Причём такой подход, где сначала заполняется структура в памяти, потом указатель на неё предаётся в процедуру инициализации – там повсеместно. Этот подход сюда перекочевал из SPL – там всё примерно то же самое. Казалось бы, ну и ладно! Создадим несколько статичных структур, отметим их как const, компилятор поместит их во флэш – сэкономит немного времени? А вот фиг! В описаниях параметров этих функций слово const не указано – причины этому нет, просто не продуманно, а значит, где бы не находилась структура изначально, её нужно будет сначала скопировать в оперативную память. Эта глупость как была в SPL, так и перекочевала в HAL.
Вот так, например, скомпилировалось условие внутри цикла:
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET); // Низкий уровень — зажигает светодиод
8000b12: 4e0b ldr r6, [pc, #44] ; (8000b40 <main+0x68>)
8000b14: 4627 mov r7, r4
8000b16: f44f 5500 mov.w r5, #8192 ; 0x2000
if ((flsh & 5) != 0) else
flsh++;
for (uint32_t i = 0 ; i < 200000 ; i++)
>
Компилируем! Прошивка занимает 2,71кБ, то есть добавленный код увеличил её менее чем на 100 байт!
И теперь всё условие внутри цикла вместе с записью в порты выглядит вот так:
8000914: f44f 5100 mov.w r1, #8192 ; 0x2000
if ((flsh & 5) != 0) else
static inline void gpio_clear(GPIO_TypeDef * gpio, uint8_t pin)
Поскольку процедуры объявлены static inline, то вызов развернётся их кодом, и если на вход передаются константы, то все эти условия и формулы будут вычислены на этапе компиляции. В итоге код получается абсолютно идентичный тому, как если записывать напрямую в регистры, а вызовы этих функций выглядят так:
gpio_config_output(GPIOC, 13, GPIOOutputMode_GP_PP, GPIOOutputSpeed_Low);
gpio_clear(GPIOC, 13);
gpio_set(GPIOC, 13);
Читаемость кода? Такая же, как у библиотек абстракции. Переносимость? Если нужно переехать на новый МК, то достаточно переписать этот самый microhal.h, сохраняя сигнатуры функций и весь код снова заработает. Что если нужен экзотический режим работы? Боже ж мой! Это кусок собственного проекта, поэтому ничто не мешает дописать ещё пару функций в этот файлик.
Причём, разрабатывая под конкретную архитектуру, можно составить набор функций так, чтобы они давали максимально эффективный код.
Итак, кроме лени читать документации и разбираться в устройстве периферии микроконтроллера, какие остались причины использовать библиотеки абстракции?
Кто-то скажет что, дескать, HAL – она одна, каждый, кто с ней работал, поймёт и мой код. А то, что я там в своих функциях настрочил – это ещё разбираться надо. Поэтому если речь идёт про доработку чужого кода, то тут одни плюсы. На что я возражу – что и тут всё не так радужно. Помимо того, что кроме HAL есть ещё SPL, и чёрте что ещё, так даже HAL от версии к версии меняется до неузнаваемости, меняются названия функций, констант… Вон, в драйвере HAL есть раздел Legacy, как раз для переноса кода, написанного под старую версию.
Поэтому моё резюме таково: HAL – можно посмотреть, потыкаться, для чего-нибудь, что надо быстро слепить, лишь бы работало – сойдёт. Но для серьёзного изучения и для серьёзного применения МК – избавляться от этой пакости как можно скорее!
К слову, сейчас продвигается ещё одна версия аппаратной абстракции для STM32, называется LLL. Она и основана как раз на таких inline-функциях, в результате чего код компилируется достаточно компактно. Но, во-первых, это всё-таки усреднённая абстракция, не учитывающая особенности конкретной архитектуры. Пусть вместо одного действия будет делать не сто, а три, но всё же. Во-вторых, проблема остаётся та же самая: рано или поздно всё упирается в неспособность конкретной реализации обеспечить нужные режимы работы.
Документация
Те, кто работал с AVR, привыкли, что достаточно скачать один даташит и в нём будет всё: распиновка, список регистров, поддерживаемые инструкции, электрические характеристики, подробное описание периферийных блоков… Здесь же всё не так!
Ради примера: допустим, мы хотим запрограммировать STM32F103C8, типа того, что выше, на китайской плате. Нам понадобится:
— Production Data с распиновкой, кратким описанием периферии, электрическими параметрами.
— Reference Manual который опишет режимы работы периферии и соответствующие регистры. Но подождите! Для изюминки документ описывает сразу целый пучок микроконтроллеров, поэтому читая каждый раздел нужно внимательно следить – относится ли написанное к вашему экземпляру или нет. Вы ведь запомнили из Production Data какая периферия тут есть, а какой нет?
— Не забываем, что в этих микроконтроллерах ядро ARM Cortex относительно независимо от всей периферии. А значит, чтобы узнать как его программировать, где какие системные регистры и как управлять контроллером прерываний, нужен отдельный документ — Programming Manual.
— Разумеется, детальнее узнать о ядре Cortex-M3 поможет Technical Reference Manual непосредственно от ARM.
— Захотите, например, узнать, в какие регистры записывать, чтобы перезаписывать флэш? Тут нужен Flash Programming Manual
И так далее, в каждом документе ещё есть перечень related documents, который порекомендует к прочтению ещё пару недостающих кусков. Я же говорил, «казачки-разбойнички».
Чем STM32 лучше AVR?
— Разумеется, цена! Можно, как правило, получить STM32 куда большей вычислительной мощности, большего объёма памяти, с более богатой периферией и частотой работы, по сравнению с AVR за те же деньги.
— 32-бит! Вычисления, работа с регистрами, памятью и портами происходит в 32-битном режиме, что позволяет добиться большей вычислительной мощности при той же частоте.
— Мощное ядро. Очень продуманная архитектура позволяет динамично работать с данными. Продуманные режимы адресации, организация работы арифметики. Есть даже однотактовое умножение 32-битных чисел, а у МК на Cortex-M3 и старше – даже деление.
— Единое адресное пространство! Не нужно писать отдельные функции для работы с ОЗУ, отдельные – для флэша, доступ до всего организован единообразно. И, наоборот, чтобы поместить данные во флеш достаточно пометить их как const, компилятор сам сообразит.
— Частота! У AVR разве что в xmega встречаются частоты выше 20 МГц. А вот например, у того же STM32F103C8 – до 72 МГц.
— Развитая система тактирования. За счёт PLL, можно запустить на максимальной или почти максимальной частоте от внутреннего генератора, в отличие от AVR, где максимум от внутреннего – часто это 8 МГц.
— Калибровка генератора 1-2% с завода (в отличие от 5% на AVR), это значит, что запустив от внутреннего генератора микроконтроллер, можно смело настраивать USART – он будет работать в пределах допусков по скорости (я уж молчу про то что точность настройки частоты USART тут в 16 раз выше)
— Богатая и развитая периферия! Вспоминая, например, ATmega328, у которой два 8-битных и один 16-битный таймер, тут даже у самого простенького МК 4 таймера как минимум, причём таймеры 16-битные, те которые генерируют ШИМ, делают это в 4 канала. Более детальные настройки и более богатые режимы работы, в сравнении с AVR, у всей остальной периферии.
— DMA! Да, тут везде есть DMA, можно зарядить, например, передачу кучи байт в USART, без прерываний и вмешательства со стороны процессора.
— Мощный контроллер прерываний! Вообще, AVR хвалится тем, что вход в прерывание и выход занимают по 4 такта. Но кроме этого, обработчик прерываний должен сохранить флаги, регистры, в итоге вход и выход занимают минимум десятка полтора тактов. В STM вход в прерывание занимает 12 тактов, причём часть регистров уже оказываются сохранёнными. Мало того, можно настроить приоритеты прерываний, прерывания с большим приоритетом прервут работу обработчиков с меньшими. Есть хвостовое объединение прерываний: если, пока выполняется одно, происходит другое прерывание с тем же приоритетом, то по завершению первого не происходит восстановление регистров и новое сохранение, а сразу перескакивает на следующее. В итоге, можно очень гибко и эффективно работать с прерываниями.
— Толерантность к 5В! Многие входы МК могут работать с входными сигналами до 5В, несмотря на напряжение работы самого МК 2,0 – 3,6 В.
— 12-битный АЦП с частотой дискретизации до мегагерца.
— Встроенный загрузчик! В каждом STM32, в отдельной, не удаляемой области памяти, зашит загрузчик. Он запустится, если замкнуть нужные контакты и выполнить сброс, позволяя заливать прошивку через USART, а в некоторых случаях и через другую периферию.
Кстати вот вам ссылка на AN2606 о том, как запускать этот загрузчик в разных МК. А вот страница для загрузки прошивающего приложения.
— RTC! Почти у всех МК есть модуль реального времени, который работает от отдельной батареечки, сохраняет пару десятков байт данных и ведёт учёт времени, пока сам МК не работает.
— Продуманность структуры управляющих регистров! Они все более-менее консистентны, располагаются относительно друг друга одинаково, поэтому для работы с ними в исходном коде на C/C++ они объединены в удобные структуры.
И так далее, перечислять выгодные отличия можно бесконечно. Казалось бы, можно перейти на STM32 и забыть навсегда про AVR, но…
Чем STM32 хуже AVR?
Есть ряд существенных отличий, из-за которых, наверное, чуть ли не в половине своих проектов я бы отдал предпочтение AVR.
— Напряжение питания. Диапазон рабочих напряжений STM32 от 2,0 или 2,4 В до 3,6 В. 4,0 – указано как предельно допустимое. Против AVR, у которых рабочее от 1,8 до 5,5 В. Это значит, что, например, сделать схему с МК работающей от батареи куда сложнее. Напряжение на LiPo аккумуляторе, например, бывает до 4,2 вольт. А значит, для работы МК нужен преобразователь, который сам по себе будет разряжать батарею, или придумывать какие-то схематичные решения. Со многими датчиками, которые рассчитаны на 5 вольт, работать напрямую уже не получится – опять-таки, требуется схематическое усложнение.
— Ток. У AVR выходной ток на пине рабочий около 20мА, предельный – до 40мА. Здесь же 25мА уже предельный, а рабочий рекомендуют не более 8мА. На корпус в сумме здесь не более 150мА, (когда у AVR – 400мА). Значит часто управлять напрямую транзисторами и другим оборудованием может быть затруднительно.
— Ток в энергосберегающих режимах. Хотя STM и гарантирует ток порядка 2мкА, это всё равно значительно больше AVR-овских 0,1мкА.
— EEPROM. В STM32 он отсутствует напрочь! Для хранения настроечных параметров – либо использовать внешний EEPROM, либо встроенную память на батарейке (где она есть), либо перезаписывать страницы флэш-памяти.
— Корпуса. В линейке STM32 практически нет корпусов удобных для домашнего изготовления. Подавляющее большинство в корпусах у которых ноги с шагом 0,5мм. Я нашёл только 2 подходящих варианта: STM32F030F4P6 в корпусе tssop20 и ногами с шагом 0,65мм. И STM32F030K6T6 в корпусе lqfp32 с шагом ног 0,8мм (как у -AU корпусов AVR). Какие там DIP корпуса для макетных плат? Забудьте.
— Непредсказуемость времени выполнения. STM32 – это ядро ARM Cortex-M и куча независимой периферии, соединённые между собой многочисленными шинами данных. AVR – более менее монолитная архитектура, где периферия и ядро тесно интегрированы. В итоге на AVR всегда с точностью до такта можно сказать сколько времени займёт та или иная операция, когда на выходе МК появится сигнал, когда переключится периферия. Здесь же нельзя предсказать даже сколько тактов будет выполняться та или иная инструкция. Не опустошился ли буфер процессора? Не попали ли мы в цикл ожидания флэш памяти? Не занята ли оперативка сейчас контроллером DMA? И так далее. Запись в регистры портов отобразится изменением электрического уровня только через несколько тактов. То же самое с таймерами и ШИМ. То же самое с любой другой периферией. Как-то смеха ради на 20-мегагерцовом AVR я делал формирование VGA сигнала. Конечно, пиксели были в виде больших квадратов, но зато картинка была стабильная, поскольку время работы каждой инструкции строго определено архитектурой. На STM такой фокус уже не пройдёт.
Конечно, перечисленные выше пункты сложно назвать недостатками архитектуры. Скорее особенностями – платой за её большие возможности. Но и списывать со счетов их не стоит. STM32 не является «заменой» AVR, это просто другая архитектура, со своей сферой применения.
Разумеется, я рекомендую к изучению и использованию STM32, а если вы знакомы с программированием, но только хотите начать изучать микроконтроллеры, то STM32 будет отличной отправной точкой.
Как прошить китайский клон STM32
Мы живём в удивительное время, когда большая часть покупаемых DIY-энтузиастами микроконтроллеров STM32 — являются или откровенными подделками, или более или менее качественными клонами малоизвестных китайских брендов (пока малоизвестных).
В этой статье мы рассмотрим программирование клонов в среде SMT32CubeIDE. Так как данная среда развивается под строгим надзором ST Microelectronics, в ней не получится ни прошить клон, ни использовать отладчик без специальной магии. Во время загрузки программы, среда проверит аутентичность микроконтроллера и выдаст ошибку. Что делать?
Самый простой способ прошить клон — использовать для этого стороннюю программу, которая не проводит проверку подозрительных клонов. Мы будем работать с STM32CubeProgrammer, но подойдёт и любое другое подобное приложение.
В данном эксперименте мы прошивали два брендовых клона: APM32F103C8T6 и GD32F103C8T6.
ШАГ 1. Формирование .hex файла
Итак, предположим, мы создали программу в среде STM32CubeIDE и хотим её загрузить на микроконтроллер. Наша программа, в своём исходом виде, разумеется, совсем не годится для загрузки на МК. Сначала потребуется собрать весь проект, скомпилировать и превратить программу в бинарный файл с расширением .hex.
Для этого необходимо открыть настройки проекта в меню: Project/Properties. Затем раскрыть пункт C/C++ Build, далее Settings, открыть пункт MCU Post build outputs и отметить там Convert to Intel Hex file
После этих манипуляций, обязательно нажать внизу кнопку Apply and Close.

Далее собираем и компилируем проект командой Build Project в меню Project. Готовый HEX файл ищем в подпапке Debug вашего проекта. Сохраняем полный путь до этого файла.
ШАГ 2. Загрузка программы
Открываем приложение STM32CubeProgrammer. В нём много разных вкладок и куча разной информации, но нам потребуется совершить всего несколько телодвижений для достижения успеха.
Подключаем к USB порту компьютера программатор ST-Link, к которому присоединён подопытный микроконтроллер. Затем нажимаем кнопку Connect — она находится слева сверху.
Сразу после этого, в правой части экрана появится информация о программаторе ST-Link: серийный номер, режим порта, частота и прочее. Там же есть кнопка Firmware Upgrade для обновления прошивки именно программатора.
Вместе с этим, в таблице появится содержимое памяти контроллера в шестнадцатеричном виде.
Если программе не удалось прочитать память — проверяем правильность подключения МК.
Затем, в левой части экрана открываем вторую сверху вкладку Erasing & Programming. Это иконка со стрелочкой. Откроется форма для загрузки .hex файла на МК.
В поле File path указываем полный путь к .hex файлу, который мы сохранили ранее. Наконец, жмём кнопку Start Programm. Готово!
Stm32cubeide как поменять микроконтроллер
When developing, I am used to using my own set of function extension libraries and project templates, so every time I start a new project development, I will copy the previous project directly and develop it based on it. When the SCM model of the new project is different from that of the original project, it involves the issue of how to modify the SCM model in the project.
This article will take the MCU model in the project from STM32F103C8Tx to STM32F103VCTx as an example to explain the specific operation steps.
Steps
Modify the project file .cproject
Open the .cproject project file with a text editor (NotePad++) and useFind and replaceReplace the original single-chip microcomputer model "STM32F103C8" with "STM32F103VC" in the project file and save it. There is no content to be modified in the .project project file.
Replace startup file
Replace the boot file (XXX.s file) of the original model withstartup_stm32f103vctx.s, This startup file can be obtained by creating a project with MCU model STM32F103VCTx in STM32CubeIDE and automatically generating code.
Replace LinkerScript file
Replace the link file (XXX.ld file) of the original model withSTM32F103VCTX_FLASH.ld, This link file can be obtained by creating a project with MCU model STM32F103VCTx in STM32CubeIDE and automatically generating code. Of course, you can also directly modify the original link file:
The main changes are in the stack space allocation and the definition of RAM and Flash space.
Modify the Makefile
The main modification involves the MCU model, startup file, link file, etc.:
Since the startup file is an assembly file, just replace it:
Modifications to the Alwhales library
Need to be modifiedeeprom.hThe flash is divided into the address range of eeprom.
For the C8T6 model, the end address of the flash is "0x08010000";
For VCT6 model, the end address of the flash is "0x08040000";
Since the conditional compilation has been set up, it only needs to be in the appropriate position:
STM32 + CMSIS + STM32CubeIDE
Здесь я расскажу как создать минимальный проект на CMSIS с использованием «родной» IDE для микроконтроллеров STM – STM32CubeIDE.
Возможно STM32CubeIDE и обладает рядом недостатков, но у нее, на мой взгляд, есть несколько преимуществ – таких как проприетарность и бесплатность, ради которых, как минимум, стоит обратить внимание на эту среду разработки, если вы не сделали этого раньше.

Объектом прошивки выбран не очень распространенный микроконтроллер STM32F072 с ядром ARM Cortex-M0, для более привычных STM32F103 на ARM Cortex-M3, с поправкой на ядро, процесс идентичен.
Все необходимые ресурсы можно скачать с сайта st.com, и вот что понадобится:
-
, я использую Windows версию, но также доступны версии под Mac и Linux




Создание нового проекта — File/New/STM32Project. После некоторого раздумия появляется окно выбора микроконтроллера, в моем случае это STM32F072RB в корпусе LQFP64, выбираю нужную строку, жму далее. Далее предлагается выбрать имя проекта, расположение, язык программирования C/C++, исполняемый файл/статическая библиотека и будет-ли проект сгенерирован с помощью CubeMX или сами с усами. Генерация кубом, в данном случае не нужна, поэтому тип проекта Empty — финиш.



Слева, в окне Project Explorer, появилось дерево проекта, правда он не совсем Empty, как заказывали. Впринципе, если устраивает сгенерированная структура папок, можно добавить туда файлы из библиотеки CMSIS и работать дальше, но здесь я покажу как можно привести структуру проекта в гармонию со своим чувством прекрасного, поэтому удаляется всё, кроме скрипта линкера т.е. файла c расширением .ld — он еще пригодится.


Все манипуляции с папками и файлами можно проводить как в проводнике так и внутри 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

Теперь нужно перенести файлы библиотеки CMSIS в проект. Библиотека состоит из файлов ядра и файлов периферии. Файлы ядра начинаются с core_ или cmsis_ они общие для всех микроконтроллеров, использующих данное ядро. Файлы периферии содержат в названии наименование микроконтроллера stm32 и специфичны для конкретного производителя, в данном случае, компании STM.
В распакованном виде архив содержит папку STM32Cube_FW_F0_V1.11.0, все пути указаны относительно этой папки. Итого, нужно скопировать:
- 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
- Drivers\CMSIS\Device\ST\STM32F0xx\Source\Templates\system_stm32f0xx.c
- Drivers\CMSIS\Device\ST\STM32F0xx\Source\Templates\gcc\startup_stm32f072xb.s

Так как были проведены некоторые манипуляции с папками проекта, нужно отобразить это в настройках.
Правая кнопка по названию проекта -> Properties -> C/C++ Build -> Settings -> Tool Settings -> MCU GCC Linker -> General – здесь нужно указать новое расположение скрипта линкера с помощью кнопки Browse…

Также нужно указать пути к файлам проекта
Properties -> C/C++ General -> Includes
Properties -> C/C++General -> Source Location
В Includes пути к папкам inc, а в Source Location логично было-бы к папкам src, но если так сделать, то в дереве проекта будут отдельно добавлены эти папки. Чтобы не загромождать визуально дерево, в Source Location можно указать корневые папки Core, CMSIS и Startup.


Для того чтобы проект скомпилировался нужно раскомментировать в файле stm32f0xx.h строку с названием микроконтроллера ну и конечно же в main.c добавить функцию main.


Собственно всё. Безошибочная компиляция и сразу же куда-то подевалось целых полтора килобайта памяти ОЗУ она же RAM, и сразу же вспоминается стек и куча, в процессе создания проекта они нигде не упоминались. Величина стека и кучи указана в файле скрипта линкера, тот что с расширением .ld, их можно и нужно изменять в соответствии с требованиями проекта. Эти значения находятся в начале файла в виде меток _Min_Heap_Size/_Min_Stack_Size с указанием размера в шестнадцатеричном виде.

В качестве примера, приведу небольшой проект традиционного мигания светодиодом.
Светодиод будет мигать на отладочной плате STM32F072B-DISCO, тактирование осуществляться от внутреннего генератора HSI48 частотой 48 МГц, а в качестве источника задержки использоваться таймер SysTick, генерирующий прерывания с периодом в 1 мс, при помощи которых отсчитывается точное время задержки. Светодиод подключен к выводу 6 порта С, настроенного на выход push-pull.
Надеюсь, данная информация кому-то пригодится, т.к. в свое время, несмотря на обилие материалов по программированию STM32, мне пришлось перелопатить достаточно много мануалов, чтобы осознать вещи, кажущиеся сейчас очевидными.
