разработка и программирование электронных устройств

Программирование STM32H747I-DISCO из командной строки Linux/MacOS

Для популярного семейства микроконтроллеров STM32 доступно большое количество разнообразных инструментальных средств. Не так давно компания STMicroelectronics приобрела компанию Atollic, известную своей средой разработки True Studio. С помощью наработок Atollic в арсенале STMicroelectronics появилась новая профессиональная среда разработки STM32Cube IDE на основе Eclipse.

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

Среди недостатков чаще всего упоминают сложность написания Makefile. Хотя под STM32 также возможно использование cmake для автоматической генерации Makefiles.
Отладка из командной строки также может отпугнуть программистов, привыкших к простоте разработки из интегрированной среды.
На самом деле разработка из командной строки очень простая и понятная. В этой статье я постараюсь доказать вам свое утверждение.

Редактор кода

В выборе редактора кода не получиться дать универсальный совет. Кто-то комфортно себя чувствует в vim или emacs. Другие предпочитают Visual Studio или Eclipse.
Я в основном пользуюсь редактором кода Sublime Text 3.
Выбирайте для себя тот редактор кода, в котором вам комфортно работать.

Компилятор

Выбор компилятора также не такой очевидный как может показаться на первый взгляд. Вы, наверное, думаете, что при работе из командной строки нет никакой альтернативы коллекции компиляторов GCC (ассемблер, С и С++ компилятор). На самом деле практически все компиляторы имеют режим командной строки. Но все же кроссплатформенность присуща только GCC. Этот компилятор одинаково хорошо работает под Linux, Windows и MacOS. Зато в тестах на производительность всегда побеждает компилятор от немецкой компании IAR, у которого также есть режим командной строки.

Все-же в данном руководстве я буду использовать бесплатную кросс-платформенную коллекцию компиляторов GCC.
Загрузить GNU ARM Toolchain можно из различных источников, например с ресурса компании ARM.

После загрузки распаковываем инструментарий и устанавливаем в домашнюю директорию:


$ tar -xvjf gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2


$ tar -xvjf gcc-arm-none-eabi-9-2019-q4-major-mac.tar.bz2

Копируем в домашний каталог:


$ cp -r gcc-arm-none-eabi-9-2019-q4-major ~/

Теперь копируем путь к инструментарию в скрипт инициализации командного интерпретатора:


$ vim ~/.bashrc


$ vim ~/.bash_profile

export PATH=$HOME/gcc-arm-none-eabi-9-2019-q4-major/bin:$PATH

Проверяем установленный компилятор arm-none-eabi-gcc :


$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Arm Embedded Toolchain 9-2020-q2-update) 9.3.1 20200408 (release)
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Отладочная плата

Компания STMicroelectronics выпускает большое количество отладочных плат по доступной цене.
Самые недорогие серии отладочных плат NUCLEO и DISCOVERY.
У меня в арсенале есть три различные отладочные платы, приобретенные в разное время.
Последнее мое приобретение — STM32H747I-DISCO с наиболее производительным на данный момент двухъядерным микроконтроллером от STMicroelectronics.
Для этой платы я написал make скрипты , с помощью которых можно собрать один из примеров от STMicroelectronics для STM32H747I-DISCO.
Чтобы воспользоваться этими сборочными скриптами вам необходимо клонировать проект с моего github репозитория :


$ git clone https://github.com/PetroShevchenko/STM32-CLI.git

Проект не содержит исходных файлов, поэтому для сборки необходимо также клонировать репозиторий STM32Cube H7 с исходниками от STMicroelectronics:


$ git clone https://github.com/STMicroelectronics/STM32CubeH7.git

Оба репозитория должны быть клонированы в ваш домашний каталог, иначе придется изменить настройки в файле STM32-CLI/CM7/config.make:


VERSION := Debug
#VERSION := Release

PROJECT_NAME := BSP_example
BOARD_NAME := STM32H747I-DISCO

MCU_CORE := CORE_CM7
MCU_SERIES := STM32H7xx
MCU_DEVICE := STM32H747xx

CUBE_PATH := $(HOME)/STM32CubeH7

TOOL_PATH := $(HOME)/gcc-arm-none-eabi-9-2019-q4-major

PROJECT_PATH := $(CUBE_PATH)/Projects/$(BOARD_NAME)/Examples/BSP

Переменная VERSION устанавливает отладочную или рабочую версию прошивки и библиотек . В версии Release включена оптимизация кода и убрана отладочная информация, поэтому для отладки кода в arm-none-eabi-gdb используйте значение переменной Debug.

Переменная CUBE_PATH содержит каталог установки STM32Cube H7, переменная TOOL_PATH — каталог установки ARM GNU Toolchain.
В переменной PROJECT_PATH хранится путь к компилируемому примеру.
Я решил собрать пример , содержащий тестирование различной периферии, расположенной на плате STM32H747I-DISCO, он так и называется — BSP (Board Support Package).

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

К большому сожалению на плате STM32H747I-DISCO не вся периферия доступна одновременно. Например, невозможно одновременно использовать микрофон и контроллер Ethernet, поскольку они подключены к одним и тем-же выводам микроконтроллера.

Как я упоминал ранее отладочная плата построена на базе двухъядерного микроконтроллера, основное ядро — Cortex-M7, второе — Cortex-M4.
Я использовал только одно ядро Cortex-M7 в данном примере, второе ничего полезного не делает.

Сборка примера происходит очень просто :


$ make all

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


$ make clean
$ make clean-libs

Для загрузки прошивки в плату достаточно просто скопировать бинарный файл на диск, который автоматически монтируется при подключении платы к компьютеру.
Другой способ — использовать утилиту openocd, которую необходимо собрать из исходников. Дело в том, что на плате STM32H747I-DISCO установлен внутрисхемный программатор-отладчик ST-Link v3E, поддержка которого на данный момент существует только в девелоперской версии openocd, собираемой из исходников.

Внутрисхемный отладчик

Для целей внутрисхемной отладки вы можете использовать комбинацию GDB сервера с клиентом, соответственно openocd и arm-none-eabi-gdb.
Как я уже упоминал openocd должен быть собран из исходников:


$ git clone git://git.code.sf.net/p/openocd/code openocd


$ cd openocd
$ ./bootstrap
$ ./configure --enable-stlink
$ make && sudo make install


$ vim ~/.bashrc


$ vim ~/.bash_profile


export PATH=/usr/local/bin:$PATH

Проверяем версию openocd :


$ openocd --version
Open On-Chip Debugger 0.10.0+dev-01267-g4c364b45-dirty (2020-06-03-03:08)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html

Если вам не удалось собрать openocd из исходников, проверьте, все ли из перечисленного установлено в вашей UNIX подобной системе:

  • libtool
  • pkg-config >= 0.23
  • autoconf >= 2.64
  • automake >= 1.9
  • texinfo
  • libusb

Теперь, когда в системе установлена последняя версия openocd, подключаем плату и запускаем GDB сервер :


$ openocd -f interface/stlink.cfg -f target/stm32h7x.cfg
Open On-Chip Debugger 0.10.0+dev-01267-g4c364b45-dirty (2020-06-03-03:08)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select '.
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 1800 kHz
Info : STLINK V3J6M2 (API v3) VID:PID 0483:374E
Info : Target voltage: 3.207315
Info : stm32h7x.cpu0: hardware has 8 breakpoints, 4 watchpoints
Info : starting gdb server for stm32h7x.cpu0 on 3333
Info : Listening on port 3333 for gdb connections

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

Подключаемся вначале через telnet:


$ telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
>

Список поддерживаемых команд можно узнать , если ввести :


>help

Через telnet можно загрузить новую прошивку в плату или записать бинарный файл по определенному адресу. Например, для воспроизведения аудио в нашем примере STMicroelectronics предлагает загрузить бинарный файл audio_sample_tdm.bin по адресу 0x08080000, используя ST-Link Utilities.
Для этой же цели можно воспользоваться telnet соединением:


> pwd
/home/petro

Обратите внимание , что текущим каталогом будет тот , из которого был запущен openocd.


> cd /home/petro/STM32CubeH7/Projects/STM32H747I-DISCO/Examples/BSP/Binary

> pwd
/home/petro/STM32CubeH7/Projects/STM32H747I-DISCO/Examples/BSP/Binary


> reset halt
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08003ed4 msp: 0x24080000
> flash write_image erase audio_sample_tdm.bin 0x08080000
auto erase enabled
wrote 524288 bytes from file audio_sample_tdm.bin in 9.826867s (52.102 KiB/s)

>

Настало время запустить GDB клиент , с помощью которого можно выполнить те-же команды, что и через telnet, лишь с тем отличием , что вначале команды нужно набрать monitor . Кроме того становятся доступны команды GDB для отладки программы:


$ cd ~/STM32-CLI/build/CM7
$ arm-none-eabi-gdb BSP_example.elf
GNU gdb (GNU Arm Embedded Toolchain 9-2020-q2-update) 8.3.1.20191211-git
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-linux-gnu --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
.
Find the GDB manual and other documentation resources online at:
.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from BSP_example.elf...
(gdb)

(gdb) target remote localhost:3333
Remote debugging using localhost:3333
Reset_Handler () at /home/petro/STM32CubeH7/Projects/STM32H747I-DISCO/Examples/BSP/SW4STM32/startup_stm32h747xx.s:62
62 ldr sp, =_estack /* set stack pointer */
(gdb) monitor reset halt
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08003ed4 msp: 0x24080000
(gdb) load
Loading section .RAM_D3, size 0x200 lma 0x38000000
Loading section .isr_vector, size 0x298 lma 0x8000000
Loading section .text, size 0x22778 lma 0x80002a0
Loading section .rodata, size 0x745c lma 0x8022a18
Loading section .init_array, size 0x4 lma 0x8029e74
Loading section .fini_array, size 0x4 lma 0x8029e78
Loading section .data, size 0x9d4 lma 0x8029e7c
Start address 0x8003ed4, load size 174664
Transfer rate: 50 KB/sec, 10916 bytes/write.

Ставим точку останова на функции MT25TL01G_GetFlashInfo и запускаем выполнение программы, жмем кнопку “Wakeup” для прохождения последовательности тестов аж до теста QSPI памяти, на котором должна сработать точка останова.


(gdb) b MT25TL01G_GetFlashInfo
Breakpoint 2 at 0x800d91e: file /home/petro/STM32CubeH7/Drivers/BSP/Components/mt25tl01g/mt25tl01g.c, line 45.
(gdb) continue
Continuing.

Breakpoint 2, MT25TL01G_GetFlashInfo (pInfo=0x2407ffa8) at /home/petro/STM32CubeH7/Drivers/BSP/Components/mt25tl01g/mt25tl01g.c:45
45 pInfo->FlashSize = MT25TL01G_FLASH_SIZE;

Теперь можно просмотреть стек вызовов . Очень удобная команда , особенно при попадании в обработчик HardFaultHandler. Просмотрев стек вызовов функций вы сможете сразу понять какой участок кода вызвал исключение:


(gdb) backtrace
#0 MT25TL01G_GetFlashInfo (pInfo=0x2407ffa8) at /home/petro/STM32CubeH7/Drivers/BSP/Components/mt25tl01g/mt25tl01g.c:45
#1 0x0800847a in BSP_QSPI_Init (Instance=0, Init=0x2407ffd4) at /home/petro/STM32CubeH7/Drivers/BSP/STM32H747I-DISCO/stm32h747i_discovery_qspi.c:171
#2 0x08002308 in QSPI_demo () at /home/petro/STM32CubeH7/Projects/STM32H747I-DISCO/Examples/BSP/CM7/Src/qspi.c:67
#3 0x08001fac in main () at /home/petro/STM32CubeH7/Projects/STM32H747I-DISCO/Examples/BSP/CM7/Src/main.c:138
(gdb)

Если отладка из командной строки вам кажется сложной или неудобной, то для gdb существует большое количество оболочек, так называемых front-end -ов.
Один из таких называется gdbgui и написан на языке Python.
Просмотр отладочной информации открывается в интернет браузере, вот как это выглядит :


$ gdbgui -g arm-none-eabi-gdb

Утилита STM32CubeMX

Работа в командной строке не означает отказ от удобных средств разработки с графическим интерфейсом. Для быстрой настройки проекта , генерации кода инициализации периферии вполне приемлемо воспользоваться очень полезной утилитой STM32CubeMX.

Установить STM32CubeMX в Linux системе можно с помощью установочного пакета SetupSTM32CubeMX-5.6.1.linux. На устройствах с Mac OS X для установки используется виртуальная машина Java :



$ sudo java -ar SetupSTM32CubeMX-4.14.0.exe

Подробную инструкцию по установке смотрите в файле Readme.html.

Отладка через консоль

Все мы в свое время написали свою первую программу. Понять, работает ли наша программа , нам помогло увиденное на экране компьютера сообщение “Hello World!”. Программируя для компьютера мы можем выводить на экран значения переменных, регистров процессора, массивов в памяти. При работе с отладочной платой все то же-самое можно вывести в отладочную консоль на основе интерфейса UART. Кроме того можно вести журнал работы устройства, выводя последовательно в консоль результаты работы вызываемых в программе функций.
Для этого можно написать простенькую систему логирования :

Встроенный в STM32H747I-DISCO отладчик ST-Link имеет также виртуальный COM порт, подключенный к интерфейсу USART1. Чтобы заставить программу выводить сообщения в USART1 , добавьте в проект следующий код:

Код инициализации USART1 можно сгенерировать в STM32CubeMX.
Обратите внимание на проверку аргумента file, это файловый дескриптор, значения которого от 0 до 2 зарезервированы за потоком ввода, вывода и ошибок соответственно. Остальные значения могут быть использованы , например, для работы с файловой системой.
В данном варианте используется только поток вывода, это означает, что стандартные функции потокового вывода языка С будут выводить значения в USART1:

То же касается перегруженного оператора << для вывода в поток в языке С++:

Не забудьте указать служебный символ ‘\r’ возврата каретки, иначе в терминальной программе сообщения могут разбежаться по всему экрану.

Для просмотра сообщений я использую утилиту minicom:


$ minicom -D /dev/ttyACM0 -b 115200

Welcome to minicom 2.7.1

OPTIONS: I18n
Compiled on Aug 13 2017, 15:25:34.
Port /dev/ttyACM0, 03:53:09

Press CTRL-A Z for help on special keys

[main:144] Test logging message
[main:144] Test logging message
[main:144] Test logging message

Также можно организовать в консоли командный интерфейс для ввода определенных команд. Пример реализации такого интерфейса предоставляется в качестве расширения для FreeRTOS и называется FreeRTOS+CLI.

Viewed 6905 times by 1049 viewers

Leave a Reply

You must be logged in to post a comment.