Перейти к содержимому

Инструменты разработки и первая прошивка … ↩

mod. Среда, 14 октября 2026 11:18 . См. 2

BeeFC · Урок S2 из 33 · Уровень «Старт»

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

После этого урока на учебной плате мигает светодиод под управлением собственной программы, а не готовой прошивки. Это версия BeeFC 0.1.

Содержание

1. Цели урока

Продолжительность урока — три часа: один час теории и два часа практики. После урока слушатель:

  • устанавливает комплект инструментов и собирает прошивку из командной строки;
  • определяет назначение выводов своей платы по выводу команды resource или по файлам описания платы в исходном коде прошивок;
  • пишет программу, которая управляет светодиодом через регистры микроконтроллера;
  • загружает прошивку двумя способами и останавливает программу в отладчике.
↑ К оглавлению

2. Термины и сокращения

ТерминОпределение
кросс-компилятор компилятор, который работает на компьютере, а создаёт код для другого процессора
загрузчик программа, записанная производителем в постоянную память микроконтроллера и умеющая принимать новую прошивку
обновление прошивки через USB (DFU) стандартный протокол загрузки прошивки по шине USB
последовательный отладочный интерфейс (SWD) двухпроводной интерфейс отладки ядер Arm Cortex-M
формат ELF файл программы с отладочной информацией и адресами секций
формат BIN образ памяти без служебной информации, побайтно записываемый во флеш-память
регистр периферии ячейка в адресном пространстве, через которую программа управляет блоком микроконтроллера
отладчик GDB программа для пошаговой отладки, работает совместно с OpenOCD
↑ К оглавлению

3. Комплект инструментов

Все программы курса бесплатны и работают в Linux, macOS и Windows. Версии зафиксированы, чтобы сборка у слушателя совпадала со сборкой на сервере автоматической проверки.

ПрограммаВерсияНазначение
Arm GNU Toolchain 13.3.rel1 компилятор arm-none-eabi-gcc, компоновщик, утилиты objcopy и size
gcc для компьютера любая современная сборка модульных тестов
GNU Make 4 и новее запуск сборки по правилам из файлов Makefile и target.mk
dfu-util 0.11 и новее загрузка прошивки через встроенный загрузчик по USB
OpenOCD 0.12 и новее связь компьютера с отладчиком ST-Link
Renode 1.15 и новее программная имитация микроконтроллера для автоматической проверки

Прошивка для платы собирается одной командой. Компилятор создаёт файл формата ELF, утилита objcopy превращает его в образ формата BIN, а утилита size выводит размеры секций.

make target
   text    data     bss     dec     hex filename
    664       0       0     664     298 build/target/blink.elf
Plain text

Столбец text показывает объём кода и констант во флеш-памяти, data — объём начальных значений переменных, bss — объём переменных, обнуляемых при запуске. Первая программа занимает меньше одного килобайта из одного мегабайта флеш-памяти STM32F405.

↑ К оглавлению

4. Описание платы

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

ПрошивкаГде описана платаПример строки для светодиода
Betaflight файл config.h в репозитории betaflight/config #define LED0_PIN PC15
INAV файл target.h в каталоге платы #define LED0 PB9
ArduPilot файл hwdef.dat PB9 LED_BLUE OUTPUT LOW GPIO(0)
PX4 файл board_config.h в каталоге boards GPIO_LED1 ... GPIO_PORTB GPIO_PIN5

Таблица содержит реальные строки из исходного кода. Плата Matek F405 описана в INAV и ArduPilot одинаково: светодиод подключён к выводу PB9. С платами Diatone Mamba F405 сложнее: в описании платы MAMBAF405_2022B для Betaflight светодиод указан на выводе PC15, а в описании платы mamba-f405-mk2 для PX4 — на выводе PB5. Это разные ревизии одной серии, поэтому описание всегда сверяется с конкретной платой.

Как узнать назначение выводов своей платы

Если на плате установлена прошивка Betaflight, назначение выводов выводит команда resource в консоли Betaflight. Консоль открывается во вкладке CLI конфигуратора Betaflight или в любой программе терминала последовательного порта.

# resource          (пример вывода, сокращён)
resource BEEPER 1 C13
resource MOTOR 1 B00
resource LED 1 B05
resource ADC_BATT 1 C01
resource GYRO_EXTI 1 C04
Plain text

Обозначение B05 соответствует выводу PB5. Полученные значения записываются в файл описания платы BeeFC.

Файл boards/board_example_f405.h

#define BOARD_HSE_HZ          8000000u   /* кварц: на большинстве плат F405 8 МГц */

#define BOARD_LED_PORT        GPIOB
#define BOARD_LED_PIN         5u         /* пример, уточнить по схеме */
#define BOARD_LED_ACTIVE_LOW  1

#define BOARD_BEEPER_PORT     GPIOC
#define BOARD_BEEPER_PIN      13u        /* PC13 на Matek F405 и Mamba F405 */
#define BOARD_BEEPER_INVERTED 1

#define BOARD_GYRO_INT_PORT   GPIOC
#define BOARD_GYRO_INT_PIN    4u         /* линия готовности данных датчика */
Plain text
Сохранение заводской конфигурации: Загрузка BeeFC стирает прошивку Betaflight вместе с настройками. Перед первой загрузкой необходимо выполнить в консоли Betaflight команду diff all и сохранить её вывод в файл. Вернуть Betaflight можно в любой момент через конфигуратор Betaflight.
↑ К оглавлению

5. Первая программа на регистрах

Первая программа не использует ни библиотек производителя, ни уровня аппаратных абстракций BeeFC. Она обращается к регистрам напрямую, чтобы было видно, что происходит в микроконтроллере. Имена регистров и битов взяты из заголовочного файла CMSIS stm32f405xx.h, который публикует производитель.

Файл app/blink_regs.c

static void delay_cycles(volatile uint32_t n)
{
    while (n--) { }                 /* грубая задержка, только для первого запуска */
}

int main(void)
{
    /* 1. Включить тактирование порта: без этого запись в регистры порта не работает. */
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
    (void)RCC->AHB1ENR;             /* чтение после записи: пауза перед доступом к порту */

    /* 2. Режим вывода: два бита MODER на каждый вывод, значение 01 — выход. */
    BOARD_LED_PORT->MODER &= ~(3u << (BOARD_LED_PIN * 2u));
    BOARD_LED_PORT->MODER |=  (1u << (BOARD_LED_PIN * 2u));

    for (;;) {
        BOARD_LED_PORT->ODR ^= (1u << BOARD_LED_PIN);   /* переключить светодиод */
        delay_cycles(1600000u);     /* около 0,5 с на 16 МГц после сброса */
    }
}
Plain text

Почему сначала включается тактирование

После сброса тактирование почти всей периферии STM32 выключено для экономии энергии. Пока бит порта в регистре RCC->AHB1ENR равен нулю, запись в регистры порта не выполняется. Это самая частая причина, по которой первая программа не работает.

Регистры порта ввода-вывода

РегистрНазначениеБитов на вывод
MODER режим: вход, выход, альтернативная функция или аналоговый вход 2
ODR уровень на выходе 1
IDR уровень на входе 1
BSRR атомарная установка и сброс уровня 2
PUPDR подтягивающий резистор к питанию или к общему проводу 2

После сброса ядро работает от внутреннего генератора с частотой 16 МГц. Пустой цикл задержки на 1 600 000 проходов даёт полпериода порядка половины секунды, но точное значение зависит от того, как компилятор оптимизировал цикл. Точные интервалы времени появятся в уроке S6 вместе с таймером.

↑ К оглавлению

6. Загрузка прошивки

Встроенный загрузчик и протокол DFU

В постоянной памяти STM32F405 записан загрузчик производителя. Если при включении питания на выводе BOOT0 высокий уровень, микроконтроллер запускает загрузчик, а не прошивку. На полётных контроллерах для этого служит кнопка BOOT: её удерживают в момент подключения кабеля USB.

dfu-util -l                                    # плата видна как «Internal Flash»
dfu-util -a 0 -s 0x08000000:leave -D build/target/blink.bin
Plain text

Адрес 0x08000000 — начало флеш-памяти, суффикс :leave запускает прошивку сразу после записи.

Отладчик ST-Link и интерфейс SWD

Интерфейс SWD использует два сигнала: SWDIO и SWCLK. На большинстве полётных контроллеров они выведены на контактные площадки. Отладчик позволяет загружать прошивку без кнопки BOOT и, что важнее, останавливать программу.

openocd -f interface/stlink.cfg -f target/stm32f4x.cfg \
        -c "program build/target/blink.elf verify reset exit"
Plain text
Если площадок SWD нет: Весь уровень «Старт» можно пройти с загрузкой только через DFU. Отладчик значительно ускоряет поиск ошибок, поэтому рекомендуется припаять к площадкам SWD провода при первой возможности.
↑ К оглавлению

7. Отладка

OpenOCD запускается в одном окне терминала и ожидает подключения отладчика GDB на порту 3333.

openocd -f interface/stlink.cfg -f target/stm32f4x.cfg
arm-none-eabi-gdb build/target/blink.elf
(gdb) target extended-remote :3333
(gdb) monitor reset halt
(gdb) break main
(gdb) continue
(gdb) x/x 0x40020414        # регистр GPIOB->ODR: база порта 0x40020400, смещение 0x14
(gdb) set *(unsigned*)0x40020414 = 0x20   # включить вывод PB5 вручную
Plain text

Запись в регистр из отладчика меняет состояние вывода сразу же. Так удобно проверять подключение светодиода и сигналы на логическом анализаторе ещё до того, как написан код.

↑ К оглавлению

8. Автоматическая проверка в Renode

Renode — программа, которая моделирует микроконтроллер STM32F4 вместе с периферией и выполняет настоящий образ прошивки. Сервер проверки загружает файл blink.elf в модель, выполняет пять секунд модельного времени и считает переключения вывода светодиода.

Ограничение модели: Модель Renode выполняет инструкции не с той скоростью, что настоящий микроконтроллер. Поэтому для пустого цикла задержки проверяется только сам факт переключений, а не период. Точный период проверяется в уроке S6, где время отсчитывает аппаратный таймер.
↑ К оглавлению

9. Практика

Задание S2.1. Описание своей платы

Продолжительность — 40 минут.

Определить назначение выводов своей учебной платы командой resource или по описанию платы в одной из прошивок. Создать файл boards/board_my.h по образцу boards/board_example_f405.h и заполнить выводы светодиода, звукового сигнализатора, линии готовности данных гироскопа и делителя напряжения батареи.

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

Задание S2.2. Первая прошивка

Продолжительность — 40 минут.

Изменить app/blink_regs.c под свою плату, собрать прошивку командой make target и загрузить её через DFU. Светодиод должен мигать.

Критерий автоматической проверки: сборка без предупреждений с флагом -Werror; размер секции text не больше двух килобайт; в модели Renode вывод светодиода переключается не менее восьми раз за пять секунд.

Задание S2.3. Остановка в отладчике

Продолжительность — 40 минут, требуется отладчик ST-Link.

Поставить точку останова на строку переключения светодиода, выполнить пять проходов цикла командой continue и после каждого прохода прочитать регистр ODR. Записать в отчёт docs/s2_report.md прочитанные значения и объяснить, почему меняется только один бит.

↑ К оглавлению

10. Как это сделано в больших прошивках

ПрошивкаВерсияФайл в исходном коде
Betaflight 2026.6.2 src/main/drivers/light_led.c
INAV 9.1.0 src/main/target/MATEKF405/target.h
ArduPilot Copter-4.7.2 libraries/AP_HAL_ChibiOS/hwdef/MatekF405/hwdef.dat
PX4 v1.17.0 boards/diatone/mamba-f405-mk2
  • Betaflight хранит описания плат в отдельном репозитории betaflight/config. Файл light_led.c не знает номера вывода: он получает его из конфигурации, которую можно изменить командой resource без перекомпиляции.
  • INAV описывает каждую плату файлом target.h в каталоге src/main/target; номер вывода задаётся при сборке и после неё не меняется.
  • В ArduPilot файл hwdef.dat при сборке обрабатывается сценарием chibios_hwdef.py, который создаёт заголовочный файл с настройкой всех выводов. Одна строка hwdef.dat описывает вывод, его назначение и начальный уровень.
  • В PX4 каждая плата — это каталог в boards с файлом board_config.h и настройками операционной системы NuttX.
↑ К оглавлению

11. Проверьте себя

  1. Почему запись в регистр MODER не действует, если не установлен бит в RCC->AHB1ENR?
  2. Чем файл формата ELF отличается от файла формата BIN?
  3. Как запустить встроенный загрузчик STM32F405 на полётном контроллере?
  4. Почему описание платы хранится отдельно от основного кода прошивки?
  5. Почему проверка в Renode не измеряет период мигания для пустого цикла задержки?
↑ К оглавлению

12. Чек-лист самопроверки

Результат: Все пункты выполнены. Версия BeeFC 0.1 готова, можно переходить к уроку S3.
↑ К оглавлению

13. Источники

  1. Справочное руководство RM0090 по микроконтроллерам STM32F405 и STM32F407, раздел 8, порты ввода-вывода общего назначения.
  2. Указания по применению AN2606: встроенный загрузчик STM32.
  3. Загрузка Arm GNU Toolchain.
  4. Утилита dfu-util.
  5. OpenOCD.
  6. Renode.
  7. Описания плат Betaflight.
  8. Заголовочные файлы CMSIS для STM32F4.
↑ К оглавлению

14. Что дальше

  • Следующий урок: S3. Устройство ядра Cortex-M4F: тактирование, память и запуск программы.
  • Полный перечень уроков приведён в статье «Курс BeeFC: содержание уровня „Старт“».

Проверено: 13.10.2026

↑ К оглавлению
  • мод. : Среда, 14 октября 2026