Настройка Toolchain(а) для сборки артефактов под STM32. x86-64, Win, Eclipse, GCC, Make, GDB, ST-LinkV2
В этом тексте я расскажу какой путь проходят исходники с момента написания до момента исполнения на микроконтроллере и как сварить прошивку. Также прокопаю тему как настроить ToolChain из бесплатных утилит. В этом тексте я покажу на что следует обратить внимание при запуске первого проекта на ARM Cortex-M чипах. Этот текст, в сущности, пояснение того, что происходит под капотом большинства IDE (IAR, Keil, CodeComposerStudio и пр.). Можете читать это как курс молодого боевика бойца.
Что же мне потребуется накатить на свой NetTop для разработки под STM32?
Вот список утилит с которыми скорее всего предстоит столкнуться при разработке прошивок для чипов STM32.
Программа/Утилита |
Назначение |
STM32 ST-LINK Utility.exе |
GUI прошивальщик по SWD/JTAG |
ST-LINK_CLI.exe |
CLI прошивальщик по SWD/JTAG |
Putty /TeraTerm/HTerm |
Терминалы Serial порта |
STM Studio |
Отрисовывать графики переменных из ячеек RAM памяти |
Cygwin |
Набор Unix утилит для Windows |
pdf reader |
браузер PDF файлов с документацией |
python |
интерпретатор языка Python |
Cppcheck |
Статический анализатор кода |
git-bash.exe |
Система управления версиями исходных кодов + удобны Unix CLI терминал |
WinMerge |
Сравнение текстовых файлов с подсветкой |
ST-LINK_gdbserver.exe |
Отладочный сервер |
WinRAR |
распаковка архивов с документацией от вендора |
GNU Tools ARM Embedded |
Компилятор для ARM |
Atollic TrueStudio |
Набор утилит |
Tor Browser |
Web Browser для скачивания утилит и документации из санкционных территорий |
Jenkins |
Сервер сборки артефактов |
hexdump /hexedit |
просмотрщик бинарных файлов |
grep |
поиск подстрок в кодовой базе |
find |
поиск файла в файловой системе по регулярному выражению для его имени |
STM32CubeMX |
Генератор базового кода с примерами |
clang format |
автоматические выравнивание отступов |
Notepad++ |
вспомогательный текстовый редактор специально для коммит сообщений |
Eclipse IDE for C/C++ Developers |
текстовый редактор |
Фаза 1. Установка текстового редактора
Так как любая программа это прежде всего текст, то надо установить какой-нибудь текстовый редактор.
Предлагаю Eclipse IDE for C/C++ Developers так как у него весьма удобные HotKeys.
Плюс в Eclipse приятное синее выделение.
Еще Eclipse мгновенно запускается. Как по мне качество текстового редактора определяется тем как часто вам приходится пользоваться мышкой. В хорошем текстовом редакторе мышка вообще не нужна. Eclipse один из таких текстовых редакторов.
Установить Eclipse IDE for C/C++ Developers можно отсюда
https://www.eclipse.org/downloads/packages/
Установка заключается в распаковке скаченного архива в удобное место. В ОС Windows можно устанавливать Eclipse в корень диска С.
Программа запускается с помощью исполняемого файла eclipse.exe, который находится в распакованной папке.
При первом запуске Eclipse надо выбрать рабочую папку (workspace). В этой папке Eclipse будет по умолчанию создавать проекты.
Настройка проекта в Eclipse
Настройки текстового редактора содержатся в файлах .project, .cproject. Важно снять галочку с пункта Makefile generation. В поле Build location прописать относительный путь к папке, которая содержит Makefile.
Настроить параллельную сборку чтобы ускорить цикл ToolChain(а). Это делается во вкладке Behavior
После этого инициировать сборки можно горячей клавишей Ctrl+B.
Фаза 2. Накатывание ToolChain(а) GCC под ARM для Cross компиляции на Win10
Нужен ToolChain: препроцессор (cpp), компилятор ASM(as), компилятор С (gcc),компилятор С++(g++), компоновщик(ld), отладчик(gdb). Нужны binutils(ы) для диагностики полученных артефактов(nm, size, readelf), архиватор статических библиотек(ar), и прочее. Это основные утилиты, которые и делают всю работу по превращению исходников (*.с, *.h) в артефакты (*.hex *.bin *.map *.elf *.out файлики).
ToolChain может находится примерно по такому адресу:
C:\Program Files (x86)\GNU Tools ARM Embedded\5.4 2016q3\bin\
Вот полный комплект GCC ARM. Всего 28 утилит.
Фаза 3. Установка Windows Build Tools binaries (Make, cp, rm, echo, sh...)
Самый классический способ сборки программ С(ях) это конечно же Make файлы. Не перестаю удивляться насколько элегантна сборка программ из make. В 1970е года когда появились утилита make программировали только настоящие ученые со степенями докторов наук. Тогда у школоты как сейчас банально не было персональных компьютеров из-за дороговизны DeskTop(ов). В 197x программировали по настоящему достойные люди. Поэтому и появились такие утилиты-шедевры как make, grep, find, sort и прочее. Благодаря Make файлам можно управлять модульностью сборок программных компонентов по-полной. Мгновенно, одной строчкой включать и исключать сотни файлов одновременно для сотен сборок. Это даже не снилось таким GUI(ням) как IAR с Keil, где приходится протирать дыры в коврике для мышки, чтобы сделать то, что в make делается одной строчкой в *.mk файлике.
Сейчас среди российских программистов микроконтроллеров make файлами умеет пользоваться в лучшем случае один из шести. Остальные не могут слезть с иглы GUI-IDE. Сборка прошивок из make это считается высшим пилотаже программирования на С(ях).
Вот минимальный набор утилит для процессинга Make файлов.
Утилита |
Назначение |
make |
build automation tool |
sh |
Unix shell interpreter |
busybox |
a software suite that provides several Unix utilities |
echo |
Echo the STRING(s) to standard output. |
cp |
Copy SOURCEs to DEST |
mkdir |
Create DIRECTORY |
rm |
Remove (unlink) FILEs |
Где же мне взять универсальный Makefile для сборки много-файловых проектов? Самое простое это воспользоваться код-генератором STM32CubeMX и сгенерировать MakeFile проект. Далее аккуратно раздербанить его под общую кодовую базу. Получается вот такой файл с правилами.
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
$(info Build $(mkfile_path) )
BUILD_DIR = build
#@echo $(error SOURCES_C= $(SOURCES_C))
INCDIR := $(subst /cygdrive/c/,C:/, $(INCDIR))
#@echo $(error INCDIR=$(INCDIR))
SOURCES_C := $(subst /cygdrive/c/,C:/, $(SOURCES_C))
#@echo $(error SOURCES_C=$(SOURCES_C))
SOURCES_ASM := $(subst /cygdrive/c/,C:/, $(SOURCES_ASM))
LDSCRIPT := $(subst /cygdrive/c/,C:/, $(LDSCRIPT))
#@echo $(error SOURCES_ASM=$(SOURCES_ASM))
# binaries
PREFIX = arm-none-eabi-
# The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx)
# either it can be added to the PATH environment variable.
ifdef GCC_PATH
CC = $(GCC_PATH)/$(PREFIX)gcc
AS = $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp
CP = $(GCC_PATH)/$(PREFIX)objcopy
SZ = $(GCC_PATH)/$(PREFIX)size
else
CC = $(PREFIX)gcc
AS = $(PREFIX)gcc -x assembler-with-cpp
CP = $(PREFIX)objcopy
SZ = $(PREFIX)size
endif
HEX = $(CP) -O ihex
BIN = $(CP) -O binary -S
# CFLAGS
#https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html
FPU =
FPU += -mfpu=fpv4-sp-d16
FLOAT-ABI = -mfloat-abi=hard
MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)
CSTANDARD = -std=c11
AS_DEFS =
AS_INCLUDES =
OPT += -Os
ifeq ($(DEBUG), Y)
#@echo $(error DEBUG=$(DEBUG))
CFLAGS += -g3 -gdwarf-2 -ggdb
endif
ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
CFLAGS += $(MCU) $(OPT) $(INCDIR) -Wall -fdata-sections -ffunction-sections $(CSTANDARD)
# Generate dependency information
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
# LDFLAGS
# libraries
LINKER_FLAGS += -Xlinker --gc-sections
ifeq ($(MBR), Y)
#@echo $(error MBR=$(MBR))
LIBS += -lnosys
else
LIBS += -lnosys
LINKER_FLAGS += -u _scanf_float
LINKER_FLAGS += -u _printf_float
endif
ifeq ($(LIBC), Y)
#@echo $(error LIBC=$(LIBC))
LIBS += -lc
endif
ifeq ($(MATH), Y)
#@echo $(error MATH=$(MATH))
LIBS += -lm
endif
#@echo $(error LDSCRIPT=$(LDSCRIPT))
LIBDIR =
LDFLAGS += $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections $(LINKER_FLAGS)
# default action: build all
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin
# build the application
# list of objects
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(SOURCES_C:.c=.o)))
vpath %.c $(sort $(dir $(SOURCES_C)))
# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(SOURCES_ASM:.S=.o)))
vpath %.S $(sort $(dir $(SOURCES_ASM)))
$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@
$(BUILD_DIR)/%.o: %.S Makefile | $(BUILD_DIR)
$(AS) -c $(CFLAGS) $< -o $@
$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
$(SZ) $@
$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
$(HEX) $< $@
$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
$(BIN) $< $@
$(BUILD_DIR):
mkdir $@
# clean up
clean:
-rm -fR $(BUILD_DIR)
# dependencies
-include $(wildcard $(BUILD_DIR)/*.d)
# *** EOF ***
Вот так выглядит пример make файла для компонента независимого сторожевого таймера
$(info IWDG_MK_INC=$(IWDG_MK_INC) )
ifneq ($(IWDG_MK_INC),Y)
IWDG_MK_INC=Y
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
$(info Build $(mkfile_path) )
IWDG_DIR = $(WORKSPACE_LOC)bsp/bsp_stm32f4/iwdg
#@echo $(error IWDG_DIR=$(IWDG_DIR))
IWDG=Y
INCDIR += -I$(IWDG_DIR)
OPT += -DHAS_IWDG
SOURCES_C += $(IWDG_DIR)/iwdg_drv.c
ifeq ($(CLI),Y)
ifeq ($(IWDG_COMMANDS),Y)
OPT += -DHAS_IWDG_COMMANDS
SOURCES_C += $(IWDG_DIR)/iwdg_commands.c
endif
endif
endif
А это MakeFile для конкретной сборки.
MK_PATH:=$(dir $(realpath $(lastword $(MAKEFILE_LIST))))
#@echo $(error MK_PATH=$(MK_PATH))
WORKSPACE_LOC:= $(MK_PATH)../../
INCDIR += -I$(MK_PATH)
INCDIR += -I$(WORKSPACE_LOC)
include $(MK_PATH)components.mk
include $(MK_PATH)cli_config.mk
include $(MK_PATH)diag_config.mk
include $(MK_PATH)test_config.mk
include $(WORKSPACE_LOC)code_base.mk
include $(WORKSPACE_LOC)rules.mk
В Makefile тоже можно делать Include guard подобно *.h файлам препроцессора.
$(info FILE_MK_INC=$(FILE_MK_INC))
ifneq ($(FILE_MK_INC),Y)
FILE_MK_INC=Y
endif
И так далее. Для каждой сборки один Makefile и множество общих *.mk файлов.
Windows Build Tools binaries можно скачать по ссылке.
Можно скопировать утилиты Windows Build Tools в папку:
C:\xpack-windows-build-tools-4.3.0-1\bin
Фаза 4. Подключить настройки компоновщика (Linker(а)). (*.ld файл)
После сборки *.с файлов образуются столько же *.o фалов. Их надо скомпоновать в один *.bin файл. Этим занимается утилита arm-none-eabi-ld.exe. Как и любой утилите нужен свой конфигурационный файл. Обычно это *.ld файл. Вот пример конфигурации компоновщика для сборки первичного загрузчика.
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x900; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 16K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(4);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(4);
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
libnosys.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
Фаза 5. Подключить инициализацию окружения. Ассемблерный код.
До запуска функции main() происходит множество инфраструктурных действий:
Проинициализировать регистр указателя SP на начало стека первым qWord(ом) бинаря.
Проинициализировать глобальные переменные в RAM данными из бинаря. (интервал rwdata).
Обнулить неинициализированные переменные в RAM (интервал bss).
Настроить ядро вычисление с плавающей точкой FPU.
Прописать в регистры процессора местонахождение адресов обработчиков прерываний.
Примонтировать, если нужно, внешнюю Off-Chip RAM память.
Всё это прописано в коде на Assembler в *.S файле. Который отрабатывает до запуска функции main(). Это например файл startup_stm32f413xx.S
Фаза 6. Нужны сорцы от Vendor(ов) чипа.
Чтобы можно было начать разрабатывать какое-то приложение и бизнес логику нужно целая куча системного софта. Это базовый софт или System Software. В его состав входит всяческая инициализация. Инициализация тактирования(TIM, RCC, RTC), интерфейсов (CAN, SPI, I2S, I2C, UART, USB, GPIO, SDIO, SAI, Ethernet), системных компонент (FLASH, SRAM, DMA, MPU, IWDG, RNG, FPU, NVIC), возможностей генерации (DAC, PWM). Это десятки тысяч строк кода. К счастью часть этого кода предоставляют нормальные вендоры чипов.
При разработке на STM32 у нас по сути два вендора: Компания ARM и Компания STMicroelectronic.
Компания ARM выпускает так называемый CMSIS(Common Microcontroller Software Interface Standard). Это С обертки для ASM команд под Cortex-M чипы. Так же *.ld файлики для компоновщика. Это скачивается с их сайта https://silver.arm.com/browse/CMSIS после регистрации
Компания STMicroelectonic выкатывает HAL Drivers - базовый системный софт для инициализации периферии микроконтроллера. Самое простое это установить их компанейский код генератор и STM32CubeMX по ссылке и сгенерировать проект.
STM32CubeMX сам скачает и сохранит сорцы базового кода в папку STM32F4xx_HAL_Driver. Только скачивать предстоит через Tor browser так как РФ у ST числится санкционной территорией. Вот список сорцов STM32F4xx_HAL_Driver от вендора:
Обратите внимание никаких статических библиотек (*.а) как у Texas Instruments. Чистые сорцы (*.c *.h файлики).
Фаза 7. Как скормить прошивку микроконтроллеру?
Накатить прошивку на чип можно при помощи программатора ST-Link через интерфейс SWD/JTAG и утилиты STM32 ST-LINK Utility.exe. Программатор может быть встроен в отладочную плату от ST, как например в семействе Nucleo_f4XXXxx:
Если вы записываете Generic *.bin артефакт(приложение), то надо указать адрес начала бинарная в On-Chip Nor Flash памяти. Запись *.hex файлов безопаснее так как вам не надо явно указывать адрес начала прошивки. Прошивка это просто бинарный массив в файле. Текстовым редактором его не проанализируешь. Анализировать содержимое бинарных файлов (*.bin) можно консольной утилитой-переходником hexdump.exe. Даешь *.bin получаешь *.txt
hexdump -C nucleo_f401re_gcc_m.bin > nucleo_f401re_gcc_m.txt
Стоит убедиться, что в первом qword всегда адрес из RAM (начало стека), а во втором qword всегда адрес из Flash (Reset_Handler). Тогда прошивка не зависнет до запуска main().
GUI окно утилиты STM32 ST-LINK Utility.exe. Можно прописать прошивку по любому отступу.
Классическая ситуация: накатили прошивку и плата зависла. Не мигает heartbeat LED. Как вариант может помочь пошаговая отладка.
Для пошаговой отладки потребуется обновление прошивки программатора ST-Link. Это можно выполнить прямо в утилите STM32 ST-LINK Utility.exe во вкладке ST-LINK:
С точки зрения DevOps(а) надо прошивать чипы из командной строки, Batch скриптом. Это легко автоматизировать. Вот скрипт автоматического обновления прошивки при помощи утилиты ST-LINK_CLI.exe
echo off
cls
set project_name=nucleo_f413zh_generic_gcc_d_m
set project_dir=%cd%
echo project_dir=%project_dir%
set artefact_hex=%project_dir%\build\%project_name%.hex
set FlashTool="C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ST-LINK_CLI.exe"
rem set Device= ID=0x463 SN=066CFF323535474B43013113
set Device=
set options= -c %Device% SWD freq=4000 HOTPLUG LPM -P %artefact_hex% -V "after_programming" -Log -TVolt
call %FlashTool% %options%
rem Reset System
call %FlashTool% -Rst
Вот лог результата работы
Easy!
Прошивка из ST-LINK_CLI.exe эффективнее, поскольку использует драгоценный интерфейс USB-SWD, только тогда, когда это реально нужно, а не всегда как в GUI версия (STM32 ST-LINK Utility.exe).
Фаза 8. Установка Debug Server
Для пошаговой отладки надо установить GDB Server. Это утилита-переходник, которая с одной стороны допрашивает чип по SWD или JTAG, а с другой стороны обслуживает TCP сокет к которому подключится отладчик arm-none-eabi-gdb.exe к порту с номером 61234.
Эту утилиту можно извлечь из набора утилит от Atollic TrueSTUDIO. Atollic TrueSTUDIO(R) for STM32 можно скачать с сайта ST.com.
Надо зарегистрироваться на сайте st.com. Скачивать дистрибутив en.TrueSTUDIO_V9.3.exe.exe получится при помощи Tor Browser так как РФ у ST числится, как санкционная территория.
ST-LINK_gdbserver установлен в
C:\Program Files (x86)\Atollic\TrueSTUDIO for STM32 9.3.0\Servers\ST-LINK_gdbserver\ST-LINK_gdbserver.exe
Нужно добавить в переменную Path путь к папке с утилитами binutils компилятора. В данном случае этот путь выглядит так:
C:\Program Files (x86)\GNU Tools ARM Embedded\5.4 2016q3\bin\
Опционально можно настроить конфигурацию отладчика в текстовом редакторе Eclipse во вкладке Run->External Tools->External Tools Configurations… или просто запустить GDB server (сервер отладки) вручную. Перейти в папку:
C:\Program Files (x86)\Atollic\TrueSTUDIO for STM32 9.3.0\Servers\ST-LINK_gdbserver
запустить скрипт ST-LINK_gdbserver.bat.
C:\Program Files (x86)\Atollic\TrueSTUDIO for STM32 9.3.0\Servers\ST-LINK_gdbserver\ST-LINK_gdbserver.bat
При работающем сервере отладки на ST-Link программаторе должен светиться зеленым светодиод. При не работающем - красным.
Фаза 9. Настройка Debug конфигурации для конкретной сборки
Неудобство Eclipse по сравнению с тем же IAR это то, что для каждой сборки приходится настраивать конфигурацию отладки. В Eclipse можно нажать Ctrl+3 появится окно быстрого поиска
и набрать там Debug Configuration. Надо прописать путь к *.elf файлу.
На вкладке Debugger надо прописать путь к отладчику от ARM GCC
C:\Program Files (x86)\GNU Tools ARM Embedded\5.4 2016q3\bin\arm-none-eabi-gdb.exe
и прописать порт от сервера отладки localhost:61234
На вкладке Startup надо прописать, что следует поставить точку останова на функции main(). Можно поставить точку останова также на более ранних функциях Reset_Handler или SystemInit().
Перед началом пошаговой отладки надо запустить отладочный сервер . Достаточно просто запустить на исполнение скрипт ST-LINK_gdbserver.bat в папке
C:\Program Files (x86)\Atollic\TrueSTUDIO for STM32 9.3.0\Servers\ST-LINK_gdbserver
Желательно из-под командной строки cmd, чтобы были видны логи отладочного сервера.
Для того чтобы выполнять пошаговую отладку нужно пересобрать артефакты с опциями компилятора
-g3 -gdwarf-2 -ggdb
Пошаговая отладка подсвечивается прямо в текстовом редакторе Eclipse зеленой строчкой. Это благодаря утилите arm-none-eabi-addr2line.exe. Текстовый редактор Eclipse сам парсит вывод addr2line и подсвечивает активный адрес в виде зелёной строчки в коде.
Во время пошаговой отладки светодиоды программатора ST-Link должны мигать зелено-красным цветом.
Блок-схема Toolchain(а)
Все вышесказанное можно представить в виде одной блок-схемы (Helicopter view) на одном единственном листочке. Такова общая канва.
Для нас исходниками являются файлы с расширениями *.ld, *.c, *.h, *.S, *.cproject, *.project, *.Makefile, *.mk их и надо подвергать версионному контролю в GIT. Автогенеренными для нас являются файлы с расширениями *.o, *.bin, *.hex, *.map, *.elf, *.out, *.d, *.a. Отгружать следует файлы *.bin, *.hex, *.map, *.elf. Это артефакты или конечный продукт работы программиста.
Также рекомендую пользоваться GIТ(ом) исключительно из-под командной строки. Так вы сможете обрабатывать вывод утилиты git легендарное утилитой grep. Можно делать вложенные grep поверх grep.
Если бы был аналог утилиты grep в материальном мире, то вы бы могли находить иголки в стоге сена, понимаете? Вам уже нравится утилита grep?
UART CLI Для отладки
Любая разработка начинается там, где есть возможность наблюдать за тем, что получилось после изменений. Поэтому вам понадобится интерфейс командной строки CLI для отладки софта и железа. Крайне желательно использовать раскраску логов, чтобы концентрировать внимание на ошибках (красный) и предупреждениях (желтый). Плюс появление цвета в консоли это признак того, что поток символов непрерывный так как коды цветов распарсились корректно. Своего рода контрольная сумма принятых данных. Да и вообще консольные логи должны выглядеть весело. Просматривать UART-CLI логи можно в утилите TeraTerm или PuTTY. Они точно понимают символы цветов.
Поэтому надо активировать свободный UART, написать в прошивке интерпретатор команд CLI для RunTime отладки по интерфейсу UART. CLI(шку) можно также инкапсулировать в любой полу или полнодуплексный интерфейс(LoRa, CAN, UART, RS485) или протокол (TCP/UDP). При наличии CLI для общения с гаджетом вам не нужно будет писать никакую GUI(ню) на QT, .Net или Python. Достаточно только общедоступных терминалов Serial порта как TeraTerm, PyTTY, Hercules. Это же успех!
Трюки для эффективной отладки прошивок
Всегда проверяйте адрес функции main(). Может случится, что техник записал Generiс в область памяти для Bootloader или наоборот. Прошивка должна проверять адрес функции main, что он лежит в нужном секторе On-Chip NorFlash(а).
Используйте файловую систему FlashFs. Это позволит уменьшить количество сборок, так как конфигурации будут в файловой системе.
Используйте HeartBeat LED. Так вы поймете, что прошивка зависла, если нет мигания.
Используйте GPIO+Oscilloscope+DMM для физической отладки быстрых процессов.
Разделяйте аппаратно-зависимый и аппаратно-независимый код. Аппаратно-независимый код тестируйте на LapTop(е).
Используйте серверы сборки (например Jenkins) для поддержания на плаву своих сборок. У вас всегда будет готовый артефакт для отгрузки. Плюс сразу будет видно какие сборки конфликтуют и оперативно принять меры по улучшению модульности.
Пишите свои загрузчики. Программатор может исчезнуть, сломаться. С загрузчиком вы обновите прошивку своего гаджета буквально по 3м проводам UART. Причем делайте первичный и вторичный загрузчик. Это позволит прописывать вторичный загрузчик по произвольному адресу.
Используйте интерфейс SWD/JTAG для пошаговой отладки и поиска причин зависаний.
Используйте утилиту STM Studio для построения графиков переменных по их адресу в ячейках RAM.
Покрывайте код модульными тестами (программные скрепы). Это лучший способ найти ошибку в коде, который затруднительно пройти пошаговой отладкой. Плюс тесты помогут безопасно делать рефакторинг. Сегодня российское общество испытывает явный дефицит программных скреп.
Вывод
Существуют и другие ToolChain(ы) (IAR, Keil). Тут же я написал про бесплатный способ полноценно вести разработку и отладку на STM32. Однако если разработчик научится собирать код из make, то он перестанете быть рабом IDE с их периодическими зависаниями. Плюс можно сэкономить 3500 EUR не покупая проприетарный компилятор, который еще и не продадут из-за санкций.
Ссылки на похожие посты:
ARM-ы для самых маленьких: тонкости компиляции и компоновщик
Отладка STM32 в среде Eclipse+GCC
ARM-ы для самых маленьких: компоновка-2, прерывания и hello world!
ARM-микроконтроллеры STM32F. Быстрый старт c STM32-Discovery
Развертывание среды разработки для STM32
STM32CubeMX — продвинутый генератор проектов для STM32
Eclipse для микроконтроллеров (STM32) + FreeRTOS Task Aware Debugge
Переход из online в offline IDE при программировании Nucleo-F401RE
Начинаем изучать Cortex-M на примере STM32
Комментарии (40)
RollerBob
27.06.2022 09:13+2Это точно не перевод какой-нибудь статьи пятилетней давности?
Брать голый эклипс и что-то там настраивать и при этом рекомендовать доставать сервер деббагера из Attolic true studio, который сам по себе был IDE для написания кода для STM32? Что вообще происходит? Есть же уже несколько лет STM32CubeIDE на базе того же эклипса, где уже всё настроено.
buldo
27.06.2022 09:46+2Более того, STM32CubeIDE - это и есть attolic True studio.
sami777
27.06.2022 12:55Это новый продукт на основе Atolic true studio. А если быть еще точнее, то на основе Eclips.
buldo
27.06.2022 13:02Странно называть это новым продуктом, если STM сказали "мы купили атолик и теперь он будет называться cubeIDE и поддерживать только наши контроллеры". То есть тут не на основе, а просто ребрендинг и продолжение развития.
Indemsys
27.06.2022 10:07+1Нынешние IDE это уже целые экосистемы. Они не сводятся к редактору или компилятору
Keil стоит попробовать хотя бы только для того чтобы увидеть сколько софта можно позаимствовать не изобретая велосипедов.STM32CubeMX в этом плане сильно отстаёт.
Те же add-on для RTOS в IAR или timeline на порядок повышают эффективность отладки.
Про подключение конфигурирование проектов для IAR тоже некорректно сказано. Проект IAR хранится в формате XML и также легко переделывается как и make файлы, даже легче.Не стоило автору противопоставлять тулсы, их надо применять все и из каждого брать лучшее.
aabzel Автор
27.06.2022 10:56-1Вот вам WarStory.
Вы программируете в IAR.
У вас 53 конфигурации. Все в одном файле workspace *.ewp в 55k строк кода.
И тут вам надо из всех сборок исключить 3 *.с файлика, а также макросы препроцессора и пути к заголовочным файлам для них.
В IDE у вас рука отвалится мышку водить. Да и переносить 150 строк в ноду <excluded> тоже задолбает уже на третей сборке. А останется еще 50 сборок обработать.
У вас на это уйдет весь день.
В make файле это делается одной строчкой или даже одним символом.Indemsys
27.06.2022 11:25+1Ваш сценарий описывает довольно неудобный воркфлоу (рабочий процесс).
Во первых, нельзя допускать у себя 53 конфигурации.
Я в таких случаях переношу выбор конфигураций в рунтайм.
Но никогда не допускаю больше нескольких конфигураций.
Тоже про макросы препроцессора. По своей воле стараюсь не создавать таких. Если они приходят из сторонних сорсов также рефакторю чтобы их стало меньше.А далее запускаю скрипт питона (у вас питон есть в списке необходимого, значит владеете им) и генерируется workspace по шаблону.
Тэг <excluded> не использую, чтобы не захламлять тот же воркспейс.Есть чистый код, но чистый и обозреваемый воркспейс тоже очень важен.
aabzel Автор
27.06.2022 11:31-3В make файлах удобнее. Там управление модульностью заложена разработчиками. IAR это для прототипирования единичных сборок или для обучения синтаксису программирования в ВУЗ(ах).
Для промышленного программирования надо пользоваться make.Indemsys
27.06.2022 11:55-1Тут вы смешиваете систему сборки и собственно управление сорсами.
В IAR более продвинутая чем make система сборки - Ninja
Она и с эклипсами идет, но только в IAR гораздо более мощный отладчик в паре с Segger Ultra адаптером.Странно что вы столько внимания уделяете сборке, когда наибольшее время занимает отладка. И эффективность отладки самый важный критерий выбора среды.
aabzel Автор
27.06.2022 12:03-2Для отладки достаточно интерфейса командной строки CLI поверх UART.
(см как в FlipperZero).
Куда важнее управление модульностью и сотнями сборок.
GDB нужен максимум для отладки UART. Далее в ход вступает UART-CLI(шка)Indemsys
27.06.2022 12:21+3CLI-са в принципе не поможет отладить алгоритмы фильтрации, детекции, PID и прочие алгоритмы в реальном времени. Тут нужны более мощные тулсы:
Т.е. CLI-са очень и очень ограниченный инструмент. Хотя да, на начальном этапе или в неполностью контролируемой среде (например во время реверса) вполне годный.
aabzel Автор
27.06.2022 12:49-1Просматривать переменные в карте памяти чипа можно и при помощи бесплатной утилиты от вендора STM Studio.
Spym
27.06.2022 12:05+1наибольшее время занимает отладка
Я бы сказал, что наибольшее время занимает написание тестов для верификации, но, возможно, это варьируется в зависимости от методологии.
aabzel Автор
29.06.2022 00:22Во первых, нельзя допускать у себя 53 конфигурации
Расскажите это Яндекс.Драйв(у).
sami777
27.06.2022 13:58+1В чем то отстает, в чем то опережает... Мне вот например в cubeIDE нравится количество инструментов для работы с SWV. KEIL во многих отношениях просто кардинально проще и обделен полезными инструментами, которые есть, что в кубе, что в атолике. Одно мне в кейле понравилось - есть поддержка "живых" переменных для ст-линка. А редактор текстовый в кейле - позапрошлый век.
JackKatch
27.06.2022 10:10+1Спасибо за статью! Достойной информации на русском не много. А по сути у меня впечатление что "хрен редьки не слаще". Производители всяких микроконтроллеров и сред разработки всё пытаются нам "помочь", упростить жизнь. Что бы легче программировать. А по факту получается всё хуже и сложнее.
segment
27.06.2022 12:08+2Сколько ни пытался перейти когда-то на eclipse, ни разу не выходило без глюков. Бывало, что ломалось что-то внутри самого eclipse и он просто переставал собирать, после переустановки все работало, что это было — не знаю. Он очень тяжелый, все медленно, даже на новых машинах. Настройка темной темы это было что-то с чем-то. Сейчас в целом нравится Segger Embedded Studio за быстроту и простоту, он для nRF52 бесплатный. Ну и пользуюсь Visual Studio для отладки платформо-независимого кода, для make проектов VS Code подходит, хотя отладка в нем все еще боль.
jaha33
27.06.2022 16:22+1В самом свежем SDK от нордика остался только VS Code, видать от Segger Embedded Studio отказались. Лично я срача Eclipse vs VS Code не понимаю, и там и там куча своих проблем. И у IAR своих куча. У Keil наверняка тоже своих заморочек полно
Есть еще интересный плагин для Visual Studio - VisualGDB, он под embedded, но платный. На всем известном ресурсе есть вылеченные версии
segment
27.06.2022 16:38+1Да как такового срача не вижу, я описал свои впечатления. К Segger я сначала относился подозрительно, но со временем они много чего доработали, это очень быстрая среда разработки и родной для него JLink. Интерфейс в целом достаточно простой, как минус это отсутствие нормального тёмного оформления. К своему удивлению я довольно быстро привык к Segger, пользоваться им удобно. VS Code как редактор хорош, сейчас он довольно шустрый. Но из-за этого медленного gdb отладка ужасна, тк бывают ошибки в самом плагине связывающий отладку и VS Code. Да и инструментов редактора для отладки мало пока что, все как-то через команды и где-то что-то обязательно не будет нормально работать.
Polaris99
27.06.2022 17:04+1Вот только про CodeVision не стоит, у него там под капотом ничего такого нет, все банально транслируется из совсем даже не ANSI-C в асм для AVR, на который натравливается AVR macro assembler от Atmel, которому уже чуть не 15 лет.
Spym
Очередной туториал по Eclipse с make в 2022? Остановите планету, я сойду.
Автору рекомендую открыть для себя человеческие инструменты и отправить наконец эклипс
в мусорное ведрона пенсию, где ему и место. Поиск замены можно начать с CLion или VSCode.Serge78rus
Может быть обоснуете второй абзац Вашего комментария?
Spym
Эклипс просто неюзабелен по современным меркам. Парсер C++ ломается на всем, что сложнее хеллоуворлда; интеграция отладчика с GDB ломается через раз сама по себе; интеграции с системами контроля версий практически отсутствуют; автодополнение ломается вместе с парсером языка, а если парсер и работает, предложенный функционал абсолютно минимален; нет языковых инъекций и встроенной поддержки других языков, используемых в проекте, вроде питона (только не начинайте про PyDev); нет нативной поддержки современными утилитами (как насчёт CoPilot?). Автоматические рефакторинги C++ там такие, что лучше бы их не было. Список не полный, конечно, я последний раз им пользовался лет пять назад и с тех пор не оглядывался ни разу.
Эклипс был хорош 10-15 лет назад на фоне отсутствия альтернатив. Сегодня его можно советовать для новых проектов только от незнания современных инструментов.
aabzel Автор
В профессии программист МК, как в деревне ничего не меняется десятилетиями. Постоянный консерватизм в наборе технологий. Что в 2011 в военном НИИ программировали Cortex-M3 в IAR на C с классами так и в 2021 в Яндекс.Драйв программируют Cortex-M3 в IAR на С c классами.
Spym
Чтож, ну давайте доедать кактус тогда, раз перемены запрещены.
aabzel Автор
Перемены ради перемен это бесмыcленно.
Есть классика Computer Science - это сборка многофайловых проектов С кода из make файлов.
Это должен уметь каждый разработчик микроконтроллеров, а не один из пяти как сейчас.
Spym
Моё возражение касалось выбора IDE, а не инструментов сборки. Насчёт актуальности make сегодня тоже можно дискутировать (нетривиальные проекты чаще используют высокоуровневые системы сборки вроде cmake или meson, и да, я говорю о глубокой встройке, как и вы), но тут действительно есть нюансы.
aabzel Автор
CLion стоит $238.80=12619,95 RUR.
В типичной российской организации нереально выпросить бюджет на покупку какого-то непонятного платного софта, если есть бесплатная и в обoем-то неплохая альтернатива.
aabzel Автор
В BackEnd Яндекс.Драйв вообще пользуются Vim и их это более чем устаивает.
wilcot
Не знаю откуда вы это взяли и от кого, но заявление странное. Наверняка кто-то и пользуется, но такое можно сказать практически про любой сервис в любой компании.
aabzel Автор
Пуговицы изобрели вообще в средневековье. Однако ими по сей день пользуются аж 2022году. Может пояcните почему?
aabzel Автор
VS code очень многих раздражает.
Вот что писал человек, который однажды пытался работать в VS code
"Ну, для начала мне не нравится, что VScode после установки почему-то отжирает почти полгига места на диске, при том что это, по сути, текстовый редактор. Не знаю как сейчас, но когда я последний раз его ставил, мне пришлось ещё накинуть в систему какую-то там версию .Net просто потому что она очень нужна была этой печатной машинке. Мне также не нравится, что этот текстовый редактор VScode независимо от того что я думаю на сей счет, со всех сил пытается быть IDE, даже там где это совершенно не нужно.
Но больше всего меня раздражает, что при всём желании этого текстонабирателя быть полноценной IDE, для того чтобы в нём были все необходимые IDE функции, в любом случае придётся ставить плагины, разумеется сторонние. А после установки плагинов оно начинает гораздо чаще глючить и медленно работать..."
У VS Code плохие отзывы, рецензии. Много рекламаций.
Spym
Посоветуйте вашему человеку дышать глубже и подбирать инструменты сообразно задаче. Если нужен текстонабиратель, есть nano/vi/notepad.exe. Если нужна IDE, придётся повозиться и пожертвовать парой гигабайт места на диске как минимум (почему это вообще проблема? у него место на диске платное?). Приведённая критика выглядит неадекватно и как-то эмоционально.
Вообще, пользуясь случаем, хочу бросить большой камень всем C++ IDE в принципе, и в этом поддержать вашего горячего знакомого конкретно в части "начинает гораздо чаще глючить и медленно работать". Даже топовые CLion и основанный на clang плагин C++ для VSCode регулярно ломаются в сложных проектах: то индекс слетит, то миспарсинг, то "Resolving symbol..." подвисает на минуту на ровном месте, то авторефакторинг калечит код так что приходится системой контроля версий его откатывать, и т.п. Знающие люди винят избыточность языка, что делает сложность разработки инструментария непомерно высокой (тем более с учётом постоянно развивающегося стандарта). Я сам давно бы завязал с C++ и перешёл на технологии поновее, но легаси всё не отпускает.
То ли дело эклипс, да?