Все микроконтроллеры программируются одинаково, если собирать код из make скриптов.
Настало время освоить очередное семейство ARM-совместимых микроконтроллеров. За плечами уже AVR, MSP430x, LPC21x, STM8, STM32x, MDR32x, ESP32x, SPC58x, CC26x2, NRF53x, AT32Fx. Теперь вот и YTM32x от компании YUN TU (Suzhou YTM Semiconductor Co Ltd).
Итак у меня есть экзотический микроконтроллер YTM32B1ME05G0MLQ. Судя по маркировке это 32-х битный МК с ядром ARM Cortex-M33 c 1MByte Flash памяти.
Код маркировки |
переменная |
значение |
YTM |
Product Status |
Qualified |
32 |
MCU Type |
32-bit |
B |
Product Line |
General |
1 |
Generation |
1st generation product |
ME |
Level |
Middle end |
0 |
Major Revision |
1st revision |
5 |
Memory Size |
1M Byte |
G0 |
Reserved |
Reserved |
M |
Ambient Temperature |
-40 C ...125 C |
LQ |
Package |
144 pin |
Глядя на оглавление флаера на микросхему, в первом приближении складывается такая мозаика.
Во флаере чип показан так:
Каков план?
1--Научиться собирать прошивки для микроконтроллера YTM32B1ME05G0MLQ компилятором GCC. Причем собирать сорцы из make файлов.
2--Научиться прошивать *.hex файл с прошивкой во Flash память YTM32B1ME05G0MLQ
3--Научиться отлаживать *.elf прошивку по шагам через интерфейс SWD.
4--Написать первую базовую, полноценную, тестировочную NoRTOS прошивку в которой будет работать драйвер SysTick, Interrupt, GPIO, UART, HardBeat LED, парсер CSV, CLI и модульные тесты, чтобы можно было при помощи CLI и встроенных тестов отлаживать любой другой функционал. То есть довести прошивку до ортодоксально-канонической формы.
В принципе это универсальный план действий для освоения абсолютно любого другого микроконтроллера. Надо просто выполнить эти 4 шага. Остальное уже зависит от специфики конкретного приложения. А эти 4 пункта, как правило всегда присутствуют в любой сборке. Это база.
Аппаратная часть.
Что надо из оборудования?
№ |
Название |
Пояснение |
1 |
Учебно-тренировочная электронная плата YTM32B1M-EVB-0144 Rev.B |
Учебно-тренировочная электронная плата с микроконтроллером YTM32B1ME05G0MLQ 2245H на борту |
2 |
Кабель переходник с USB-A на USB Type-C |
Для соединения отладочной платы и PC |
3 |
Программатор отладчик J-link V9 (или V12) USB-JTAG для ARM |
Программатор для загрузки прошивки. Нужен именно V9. Так как поддержка ARM Cortex-M33 начинается именно с V9. Для загрузки прошивки в микроконтроллер |
4 |
шлейф 20 pin |
Для соединения MCU и программатора |
5 |
шлейф 10 pin |
Для соединения MCU и программатора |
6 |
Переходник с шлейфа 20 пин в шлейф 10 пин |
Для соединения MCU и программатора |
7 (opt) |
Перемычки вилка-гнездо. |
Для соединения программатора с платой. |
Вы узнаете электронную плату YTM32B1M-EVB-0144 Rev.B вот по этой фотографии
Вот так условно можно представить архитектуру схемотехники YTM32B1M-EVB-0144 Rev.B. CAN 4x, LIN 4x, LED 3x, BTN 2x, ADC 2x, FRAM, EEPROM, USB-UART.
Программатор выглядит так.
надпись на шильдике гласит
Что надо из документации?
№ |
Название документа |
колич. страниц |
Пояснение |
1 |
YTM32B1ME0x Data Sheet |
45 |
Флаер на продукт |
2 |
YTM32B1ME0x Reference Manual |
720 |
Спецификация на микроконтроллер. Разметка памяти. Список прерываний. |
5 |
GNU Make |
224 |
Спека на GNU make |
6 |
The GNU linker |
122 |
Спека на компоновщик |
4 |
Using the GNU Compiler Collection |
1006 |
Спека на компилятор GCC |
3 |
ARMv8-M Architecture Reference Manual |
1364 |
Спецификация ядра |
Что надо из ПО?
№ |
Программа |
Версия |
Пояснение |
1 |
Tera Term |
4.106 |
Терминал последовательного порта для полнодуплексного доступа к UART-CLI. |
2 |
arm-none-eabi-gcc.exe (GNU Arm Embedded Toolchain 10.3-2021.10) 10.3.1 20210824 (release) |
10.3.1 |
GCC компилятор языка программирования Си |
3 |
GNU Make |
4.4.1 |
Система сборки |
8 |
JRE |
? |
Виртуальная машина Java для запуска Eclipse. Можно скачать на сайте Oracle. |
4 |
Eclipse IDE for C/C++ Developers |
4.23.0 |
Текстовый редактор для написания кода |
6 |
Segger JFlash.exe версии 6.20 |
6.20 |
Утилита для загрузи и считывания файла с прошивкой |
5 |
Ozone - The J-Link Debugger C:\Program Files\SEGGER\Ozone |
3.26 |
Отладочный сервер с отладочным клиентом для встраиваемых систем. |
7 |
Утилита для обновления прошивки по *.elf файлу |
Колонка версия тут указана не случайно. Особенно для JFlash и Ozone. С другими версиями я не гарантирую, что инструкция будет совпадать с реальностью. Все программы добавляем в переменную PATH, чтобы можно было их вызывать просто по имени.
На самом деле, если вы до этого уже программировали другой микроконтроллер с ARM ядром компилятором GCC, то установка Eclipse, компилятора GCC и системы сборки Make абсолютно ничем не отличается от того, как это делалось в случае ARM-Coertex M4. Про это можно почитать тут:
# |
Текст |
URL |
1 |
Настройка ToolChain(а) для Win10+GCC+С+Makefile+ARM Cortex-Mx+GDB |
|
2 |
Сборка firmware для CC2652 из Makefile |
|
5 |
ToolChain: Настройка сборки прошивок для микроконтроллеров Artery из Makefile |
В случае с YTM32x надо лишь акцентировать внимание на некоторых моментах.
Программная часть
Каждый нормальный вендор чипов бесплатно дает HAL для своего чипа. YunTu не исключение. Надо лишь зарегистрироваться на их сайте, придумать логин и пароль. После чего можно скачать спецификации на микроконтроллер, схемотехнику учебно-тренировочной электронной платы и тонны исходного кода HAL в SDK. Там же в личном кабинете можно получить наводку на сайты с GCC, Jlink, Ozone и прочее.
Исходники HAL можно взять с официального сайта. называется это SDK. Надо только зарегистрироваться и получишь много бесплатного Си-кода. Причем сам код HAL очень даже хорошо написан.
Утилита cloc показывает, что в официальном SDK порядка 80k строк Си-кода и 4k строк на ассемблере.
Среди всех сорцов надо обратить особое внимание на некоторые фундаментальные файлы:
YTM32B1ME0_startup_gcc.S - это код процедуры Reset_Handler, который отрабатывает до вызова функции main(). Он написан на ассемблере. Тут происходит отключение прерываний, обнуление регистров процессора, инициализация глобальных переменных, инициализация регистра указывающего на начало стековой RAM памяти, вызов функции SystemInit и вызов функции main(). Тут же можно посмотреть как называются функции обработчики прерываний, например SysTick_Handler.
YTM32B1ME0_1_3_1/YTM32Bx_SDK/platform/devices/YTM32B1ME0/linker/gcc/flash.ld - это конфигурация для компоновщика. Тут указывается сколько у микроконтроллера RAM и ROM памяти, сколько стековой памяти, сколько памяти в куче. Указывается начало RAM памяти, начало ROM памяти. Указывается название массива isr_vector, который отвечает за таблицу векторов прерываний. Тут указано из каких секций состоит программа и в какой последовательности эти секции следуют. LD скрипт - это целый язык программирования со своими переменными, операторами, функциями и комментариями. Небольшой ликбез по LD можно посмотреть тут.
YTM32B1ME0_1_3_1\YTM32Bx_SDK\platform\devices\YTM32B1ME0\startup\system_YTM32B1ME0.c - в сорце system_YTM32B1ME0.c определена функция SystemInit(). Эта функция вызывается до функции main(). SystemInit включается сопроцессор для вычислений в плавающей точке, отключает сторожевой таймер, включает модуль защиты памяти MPU и прочее. Тут же лежит функция для программной перезагрузки микроконтроллера SystemSoftwareReset.
Особенность YTM32Bx_SDK в том, что разработчики на стороне YunTu решили, что таблица векторов прерываний будет по умолчанию хранится в RAM памяти. Поэтому такие драйверы, как UART при инициализации пополняют таблицу векторов прерываний прямо во время исполнения прошивки функцией INT_SYS_InstallHandler.
Далее исходный код добавляется по мере потребности учитывая специфику проекта. На GitHab тоже находятся множество образцовых проектов прошивок для микроконтроллера YTM32B1ME0x.
Система сборки.
В качестве системы сборки я по-прежнему пере использую make скрипты.
Корневой make файл с правилами сборки проекта
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
$(info mkfile_path:$(mkfile_path) )
MK_PATH := $(subst /cygdrive/c/,C:/, $(MK_PATH))
$(info MK_PATH=$(MK_PATH))
BUILD_DIR=build
EXTRA_TARGETS=
INCDIR := $(subst /cygdrive/c/,C:/, $(INCDIR))
SOURCES_TOTAL_C += $(SOURCES_C)
SOURCES_TOTAL_C += $(SOURCES_CONFIGURATION_C)
SOURCES_TOTAL_C += $(SOURCES_THIRD_PARTY_C)
SOURCES_TOTAL_C := $(subst /cygdrive/c/,C:/, $(SOURCES_TOTAL_C))
SOURCES_ASM := $(subst /cygdrive/c/,C:/, $(SOURCES_ASM))
LIBS := $(subst /cygdrive/c/,C:/, $(LIBS))
LDSCRIPT := $(subst /cygdrive/c/,C:/, $(LDSCRIPT))
#@echo $(error SOURCES_ASM=$(SOURCES_ASM))
include $(WORKSPACE_LOC)make_scripts/toolchain.mk
WORKSPACE_LOC := $(subst /cygdrive/c/,C:/, $(WORKSPACE_LOC))
FLOAT-ABI = -mfloat-abi=soft
MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)
CSTANDARD = -std=c99
AS_DEFS =
# AS includes
AS_INCLUDES =
ifeq ($(DEBUG), Y)
CFLAGS += -g3 -ggdb -gdwarf-2
COMPILE_OPT += -O0
else
COMPILE_OPT += -Os
endif
COMPILE_OPT += -fmessage-length=0
COMPILE_OPT += -fsigned-char
COMPILE_OPT += -fno-common
COMPILE_OPT += -fstack-usage
COMPILE_OPT += -fzero-initialized-in-bss
COMPILE_OPT += -finline-small-functions
COMPILE_OPT += -Werror=missing-prototypes
COMPILE_OPT += -Werror=address
COMPILE_OPT += -Werror=switch
COMPILE_OPT += -Werror=array-bounds=1
COMPILE_OPT += -Werror=comment
COMPILE_OPT += -Werror=div-by-zero
COMPILE_OPT += -Werror=duplicated-cond
COMPILE_OPT += -Werror=shift-negative-value
COMPILE_OPT += -Werror=duplicate-decl-specifier
COMPILE_OPT += -Werror=enum-compare
COMPILE_OPT += -Werror=uninitialized
COMPILE_OPT += -Werror=empty-body
COMPILE_OPT += -Werror=unused-but-set-parameter
COMPILE_OPT += -Werror=unused-but-set-variable
COMPILE_OPT += -Werror=float-equal
COMPILE_OPT += -Werror=logical-op
COMPILE_OPT += -Werror=implicit-int
COMPILE_OPT += -Werror=implicit-function-declaration
COMPILE_OPT += -Werror=incompatible-pointer-types
COMPILE_OPT += -Werror=int-conversion
COMPILE_OPT += -Werror=old-style-declaration
COMPILE_OPT += -Werror=maybe-uninitialized
COMPILE_OPT += -Werror=redundant-decls
COMPILE_OPT += -Werror=sizeof-pointer-div
COMPILE_OPT += -Werror=misleading-indentation
COMPILE_OPT += -Werror=missing-declarations
COMPILE_OPT += -Werror=missing-parameter-type
COMPILE_OPT += -Werror=overflow
COMPILE_OPT += -Werror=parentheses
COMPILE_OPT += -Werror=pointer-sign
COMPILE_OPT += -Werror=return-type
COMPILE_OPT += -Werror=shift-count-overflow
COMPILE_OPT += -Werror=strict-prototypes
COMPILE_OPT += -Werror=unused-but-set-variable
COMPILE_OPT += -Werror=unused-function
COMPILE_OPT += -Werror=unused-variable
COMPILE_OPT += -Werror=missing-field-initializers
COMPILE_OPT += -Wno-stringop-truncation
COMPILE_OPT += -Wno-format-truncation
COMPILE_OPT += -Wno-restrict
COMPILE_OPT += -Wno-format
COMPILE_OPT += -Wno-cpp #TODO temp
COMPILE_OPT += -Wno-discarded-qualifiers
COMPILE_OPT += -Wmissing-prototypes
#Perform dead code elimination
COMPILE_OPT += -fdce
#Perform dead store elimination
COMPILE_OPT += -fdse
ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) $(COMPILE_OPT) -Wall -fdata-sections -ffunction-sections
CFLAGS += $(CSTANDARD)
CFLAGS += -Wall
CFLAGS += $(MCU) $(OPT) $(COMPILE_OPT) -fdata-sections -ffunction-sections $(INCDIR)
# Generate dependency information
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
CPP_FLAGS += $(CSTANDARD) $(INCDIR) $(OPT) $(COMPILE_OPT)
LINKER_FLAGS += -Xlinker --gc-sections
LINKER_FLAGS += -lrdimon --specs=rdimon.specs
LINKER_FLAGS += -u _scanf_float
LINKER_FLAGS += -u _printf_float
ifeq ($(LIBC), Y)
LIBS += -lc
endif
ifeq ($(MATH_LIB), Y)
LIBS += -lm
endif
LIBDIR =
LDFLAGS += $(MCU)
LDFLAGS += -T$(LDSCRIPT)
LDFLAGS += $(LIBDIR)
LDFLAGS += $(LIBS)
LDFLAGS += -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections
LDFLAGS += $(LINKER_FLAGS)
ARTIFACTS += $(BUILD_DIR)/$(TARGET).bin
ARTIFACTS += $(BUILD_DIR)/$(TARGET).hex
ARTIFACTS += $(BUILD_DIR)/$(TARGET).elf
.PHONY: all
# default action: build all
all: $(EXTRA_TARGETS) $(ARTIFACTS)
.PHONY: generate_definitions
generate_definitions:
$(info GenerateDefinitions...)
$(PREPROCESSOR_TOOL) $(CPP_FLAGS) $(WORKSPACE_LOC)empty_source.c -dM -E> c_defines_generated.h
$(SORTER_TOOL) -u c_defines_generated.h -o c_defines_generated.h
# build the application
# list of objects
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(SOURCES_TOTAL_C:.c=.o)))
vpath %.c $(sort $(dir $(SOURCES_TOTAL_C)))
# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(SOURCES_ASM:.S=.o)))
vpath %.S $(sort $(dir $(SOURCES_ASM)))
TOTAL_FILES := $(words $(OBJECTS))
$(info TOTAL_FILES:$(TOTAL_FILES) )
$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
$(eval CURRENT_CNT=$(shell echo $$(($(CURRENT_CNT)+1))))
@echo Compiling $(CURRENT_CNT)/$(TOTAL_FILES) $@
@$(CC) -c -MD $(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 -p $@
# clean up
.PHONY: clean
clean:
-rm -fR $(BUILD_DIR)
# dependencies
-include $(wildcard $(BUILD_DIR)/*.d)
# *** EOF ***
Особенности компоновки. Какую выбрать libc?
При программировании на Си нужны стандартные функции, такие как printf() sprintf() и прочее. Они обычно распространяются в виде предварительно скомпилированных бинарных *.a файлов и лежат в папке с компилятором. В моём случае это папка
C:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2021.10
Называется эта библиотека libc. Их очень много реализаций: glibc, picolibc, nanolib, Newlib и прочее. От выбора той или иной libc зависит размер получившегося бинаря.
Собирая код внутри статической библиотеки libc.a у вас может возникнуть ошибка компоновщика про отсутствие определения тел функций для системных вызовов. Системные вызовы - это функции _sbrk, _write, _close, _fstat, _isatty, _lseek, _read, abort, _exit, _kill и _getpid. Именно эти функции вызываются внутри libc.
Вам надо решить какую Вы выберете реализацию libc. libc - это статическая библиотека с реализацией таких функций как printf(), scanf(), snprintf() и прочее.
Реализация libc |
ключ компоновщику |
Комментарий |
nosys |
--specs=nosys.specs |
Вставляет пустые функции для системных вызовов |
newlib-nano |
--specs=nano.specs |
Частичная реализация libc |
rdimon |
--specs=rdimon.specs |
no data |
Newlib |
no data |
Частичная реализация libc |
picolibc |
no data |
Частичная реализация libc |
nolibc |
-nolibc |
no data |
Я пока выбрал rdimon.
Как прошить микроконтроллер?
Тут надо снова вернуться к аппаратному обеспечению. Прежде всего надо соединить оборудование, как показано на схеме.
Такова расспиновка 10-ти пинового разъёма для программирования P1 по SWD.
При подключении программатора J-link в диспетчере устройств должно появиться ещё одно USB устройство: J-Link driver.
Формально есть 4 способа прошить микроконтроллер семейства YTM32х. Вот они перед вами.
# |
Утилита |
Артефакт на входе |
Примечание |
1 |
JFlash.exe* |
*.hex |
Можно прошить *.bat скриптом, если есть лицензия на отладчик j-link |
2 |
JFlashLight.exe |
*.hex |
Возможна только ручная пере прошивка курсором мышки в GUI клиенте |
3 |
JRun.exe* |
*.elf |
Появилась только в последних версиях |
4 |
Ozone.exe |
*.elf |
Прошивка перед пошаговой отладкой |
Патч к J-link
Чтобы Jlink понял как прошивать новое семейство микроконтроллеров надо попатчить программу SEGGER JLink V6.20. По сути патч сводится вот к такому добавлению в файл JLinkDevices.xml.
Также надо закинуть специальные бинарные файлы
Devices/YTMicro/YTM32B1ME0/YTM32B1ME0_Main.FLM
и
Devices/YTMicro/YTM32B1ME0/YTM32B1ME0_Dflash.FLM
Откуда берутся бинарные файлы с расширением *.FLM я пока сказать не могу. Будем считать, что файлы появились при помощи волшебной палочки.
Прошивка микроконтроллера утилитой JFlash.exe
Чтобы загрузить прошивку нужна утилита JFlash.exe. Эта утилита на вход получает два файла: *.hex файл с прошивкой и *.jflash файл с конфигурацией YTM32B1M4H0VLQT_SWD.jflash, который хранит такие метаданные как интерфейс, битовая скорость интерфейса, название микроконтроллера, начало памяти
YTM32B1M4H0VLQT_SWD.jflash
AppVersion = 62000
FileVersion = 2
[GENERAL]
ConnectMode = 0
CurrentFile = ""
DataFileSAddr = 0x00000000
GUIMode = 0
HostName = ""
TargetIF = 1
USBPort = 0
USBSerialNo = 0x00000000
[JTAG]
IRLen = 0
MultipleTargets = 0
NumDevices = 0
Speed0 = 4000
Speed1 = 4000
TAP_Number = 0
UseAdaptive0 = 0
UseAdaptive1 = 0
UseMaxSpeed0 = 0
UseMaxSpeed1 = 0
[CPU]
NumInitSteps = 1
InitStep0_Action = "Reset"
InitStep0_Value0 = 0x00000000
InitStep0_Value1 = 0x00000000
InitStep0_Comment = "Reset and halt target"
NumExitSteps = 0
UseScriptFile = 0
ScriptFile = ""
UseRAM = 1
RAMAddr = 0x20000000
RAMSize = 0x00010000
CheckCoreID = 0
CoreID = 0x00000000
CoreIDMask = 0x0F000FFF
UseAutoSpeed = 0x00000001
ClockSpeed = 0x00000000
EndianMode = 0
ChipName = "YTMicro YTM32B1ME05G0MLQT"
[FLASH]
NumBanks = 2
[FLASH0]
aRangeSel[1] = 0-511
BankName = "Internal Flash"
BankSelMode = 1
BaseAddr = 0x00000000
[FLASH1]
aRangeSel[1] = 0-255
BankName = "Internal Flash"
BankSelMode = 1
BaseAddr = 0x00100000
[PRODUCTION]
AutoPerformsErase = 1
AutoPerformsProgram = 1
AutoPerformsSecure = 0
AutoPerformsStartApp = 0
AutoPerformsUnsecure = 0
AutoPerformsVerify = 1
EnableTargetPower = 0
EraseType = 2
MonitorVTref = 0
MonitorVTrefMax = 0x0000157C
MonitorVTrefMin = 0x000003E8
OverrideTimeouts = 0
ProgramSN = 0
SerialFile = ""
SNAddr = 0x00000000
SNInc = 0x00000001
SNLen = 0x00000004
SNListFile = ""
SNValue = 0x00000001
StartAppType = 0
TargetPowerDelay = 0x00000014
TimeoutErase = 0x00003A98
TimeoutProgram = 0x00002710
TimeoutVerify = 0x00002710
VerifyType = 1
Вот так выглядит скрипт flash_Jlink.bat для пере прошивки по клику.
cls
set project_name=ytm32b1m_evb_0144_rev_b_mbr_gcc_m
set flash_tool=JFlash.exe
set mcu_config=YTM32B1M4H0VLQT_SWD_620.jflash
::set mcu_config=YTM32B1ME0_Main.FLM
set artefact_hex=build\%project_name%.hex
set option=
set option=%option% -openprj%mcu_config%
set option=%option% -open%artefact_hex%
set option=%option% -programverify
set option=%option% -startapp
set option=%option% -exit
%flash_tool% %option%
Надо прописать в переменную окружения PATH адрес к утилите JFlash.exe. В моём случае это C:\Program Files (x86)\SEGGER\JLink_V620\JFlash.exe
После успешной пере прошивки должен появиться вот такой расклад GUI.
После успешной пере прошивки должен появиться вот такой лог.
Лог успешной перепрошивки
Application log started
- J-Flash V6.20 (J-Flash compiled Sep 8 2017 18:04:56)
- JLinkARM.dll V6.20 (DLL compiled Sep 8 2017 18:04:35)
Opening project file [YTM32B1M4H0VLQT_SWD_620.jflash] ...
- Project opened successfully
Opening data file [build\ytm32b1m_evb_0144_rev_b_mbr_gcc_m.hex] ...
- Data file opened successfully (39612 bytes, 1 range, CRC of data = 0x55979B5C, CRC of file = 0x5B2D5825)
Checking if selected data fits into selected flash sectors.
Programming and verifying target (39612 bytes, 1 range) ...
- Connecting ...
- Connected successfully
- Start of determining flash info (Bank 0 @ 0x00000000)
- End of determining flash info
- Flash bank info:
- 512 * 2 KB @ 0x00000000
- Start of preparing flash programming
- End of preparing flash programming
- Start of determining dirty areas in flash cache
- End of determining dirty areas
- CPU speed could not be measured.
- Start of erasing sectors
- Erasing range 0x00000000 - 0x00003FFF (008 Sectors, 16 KB)
- Erasing range 0x00004000 - 0x00007FFF (008 Sectors, 16 KB)
- Erasing range 0x00008000 - 0x00009FFF (004 Sectors, 8 KB)
- End of erasing sectors
- Start of flash programming
- Programming range 0x00000000 - 0x00007FFF (016 Sectors, 32 KB)
- Programming range 0x00008000 - 0x00009FFF (004 Sectors, 8 KB)
- End of flash programming
- Flash programming performed for 1 range (40960 bytes)
- 0x0000 - 0x9FFF (020 Sectors, 40 KB)
- Start of verifying flash
- End of verifying flash
- Start of restoring
- End of restoring
- Target programmed and verified successfully (CRC = 0xE4E7952A) - Completed after 3.712 sec
Starting application ...
- Disconnecting ...
- Disconnected
- Connecting via USB to J-Link device 0
- Target application started
Обновление утилитой JFlashLight.exe
Прошивку можно загрузить при помощи утилиты JFlashLite.exe. Это клиентская утилита с GUI интерфейсом, чтобы прошивать микроконтроллеры программаторами j-link. При первом запуске следует выбрать название микроконтроллера YTM32B1ME05G0MLQ, интерфейс пере прошивки SWD и битовую скорость 1000 kbit/s пере прошивки.
Теперь остается только клюнуть на кнопку Program Device и прошивка будет прописана во Flash память микроконтроллера.
Во время загрузки появляется вот такой progress bar
В случае успеха появится вот такой лог
Лог успешной загрузки
Downloading C:\projects\workspace\board_name\source\projects\ytm32b1m_evb_0144_rev_b_mbr_gcc_m\build\ytm32b1m_evb_0144_rev_b_mbr_gcc_m.hex to YTM32B1ME05G0MLQT via SWD-Interface@1000kHz
Programming Thread started.
Device "YTM32B1ME05G0MLQT" selected.
Found SW-DP with ID 0x6BA02477
Scanning AP map to find all available APs
AP[2]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x84770001)
AP[1]: APB-AP (IDR: 0x54770002)
Iterating through AP map to find AHB-AP to use
AP[0]: Core found
AP[0]: AHB-AP ROM base: 0xE00FF000
CPUID register: 0x410FD214. Implementer code: 0x41 (ARM)
Found Cortex-M33 r0p4, Little endian.
FPUnit: 8 code (BP) slots and 0 literal slots
Security extension: not implemented
CoreSight components:
ROMTbl[0] @ E00FF000
ROMTbl[0][0]: E000E000, CID: B105900D, PID: 000BBD21 SCS
ROMTbl[0][1]: E0001000, CID: B105900D, PID: 000BBD21 DWT
ROMTbl[0][2]: E0002000, CID: B105900D, PID: 000BBD21 FPB
ROMTbl[0][3]: E0000000, CID: B105900D, PID: 000BBD21 ???
ROMTbl[0][5]: E0041000, CID: B105900D, PID: 002BBD21 ETM
ROMTbl[0][6]: E0042000, CID: B105900D, PID: 000BBD21 ETB
Debugger initialized successfully.
Reset: Halt core after reset via DEMCR.VC_CORERESET.
Reset: Reset device via AIRCR.SYSRESETREQ.
J-Link: Flash download: Bank 0 @ 0x00000000: 1 range affected (43008 bytes)
J-Link: Flash download: Total time needed: 3.411s (Prepare: 0.020s, Compare: 1.065s, Erase: 0.551s, Program: 1.217s, Verify: 0.545s, Restore: 0.009s)
Programming Thread exited
Programming done
Обновление прошивки утилитой JRun.exe
В поздних версиях J-link ПО ещё можно прошиваться утилитой JRun.exe. Даешь elf, название микроконтроллера и получаешь прошитый микроконтроллер.
Настройка пошаговой отладки.
Надо установить утилиту Ozone. Это отладочный сервер и одновременно отладочный клиент в одном приложении. Причем надо установить именно версии 3.26. После установки программа окажется в папке C:\Program Files\SEGGER\Ozone V3.26 . Как и любой другой отладочный клиент Ozone получает на вход *.elf файл.
При запуске Ozone надо первым делом выбрать целевой микроконтроллер
Далее следует явно указать путь к *.elf файлу.
Тут клюём next
Прошивка загрузится в боевую flash. Ozone весьма удобен в том плане, что он автоматически пере заливает прошивку, если *.elf файл изменился. Достаточно буквально пересобрать код и он тотчас же уже готов к пошаговой отладке.
И вот появится пошаговая отладка. Отрабатывает весьма четко. Без глюков.
А это минимальный набор горячих клавиш для работы с отладчиком Ozone
Hot key |
Значение |
Перевод |
F5 |
Continue |
отпустить программу на исполнение |
F10 |
Step Over |
перешагнуть через функцию |
F11 |
Step into |
зайти во внутрь функции |
Shift+F11 |
Step out |
??? |
Схема ToolChain-a
Все вышесказанное можно представить в виде одной блок-схемы (Helicopter view) на одном единственном листочке. Получается вот такой конвейер метаморфоза файлов.
Для нас, как для программистов, исходниками тут являются файлы с расширениями *.ld, *.c, *.h, *.S, *.cproject, *.project, *.Makefile, *.mk , *.bat. Вот их-то и надо подвергать версионному контролю в GIT.
Авто генеренными для нас являются файлы с расширениями *.o, *.bin, *.hex, *.map, *.elf, *.out, *.d, *.a.
Отгружать следует файлы *.bin, *.hex, *.map, *.elf. Это артефакты или конечный продукт работы программиста микроконтроллера.
UART-CLI Для Отладки
Также удалось достучаться до консоли по UART2. Это открывает прямую дорогу для полноценной отладки абсолютно любой остальной подсистемы микроконтроллера: CAN, LIN, PWM и проч.
Можно заметить, что в SDK от YunTo таблица векторов прерываний хранится в RAM памяти по адресу 0x1fff0000. Глядя на *.map файл там как раз переменная __VECTOR_RAM.
Также в UART-CLI можно попросить микроконтроллер прогнать модульные тесты
Итог
Удалось получить базовое представление о работе с очередным китайским микроконтроллером семейства YTM32. Теперь понятно, как собирать код, прошивать бинарь, как выполнять пошаговую отладку прошивке на target устройстве и как запустить UART-CLI. Всё это открывает прямую дорогу к полноценной разработке на китайских микроконтроллерах YTM32x от Yun Tu.
Этот текст в очередной раз подтверждает тот факт, что все микроконтроллеры программируются абсолютно одинаково, если собирать код из самостоятельно написанных GNU make файлов. Это и есть основное достоинство системы сборки GNU Make. Тотальная переносимость системы сборки и бесшовная миграция на любое новое железо.
Микроконтроллеры серии YTM32x подчинены воле российского человека.
Надеюсь, что этот текст поможет и другим программистам МК наладить Toolchain для сборки программ для микроконтроллеров YTM32x.
Словарь
Акроним |
Расшифровка |
ARM |
Advanced RISC Machines |
LED |
light-emitting diode |
JRE |
Java Runtime Environment |
UART |
universal asynchronous receiver-transmitter |
GPIO |
general-purpose input/output |
RISC |
Reduced instruction set computer |
CLI |
command-line interface |
GCC |
GNU Compiler Collection |
MCU |
microcontroller unit |
CSV |
Comma-separated values |
YTM32 |
YUN TU |
SWD |
Serial Wire Debug |
SDK |
software development kit |
Ссылки
№ |
Пояснение |
URL |
1 |
||
8 |
J-Link LITE Cortex-M V9 |
|
6 |
J-Link BASE Classic |
|
2 |
Чей-то репозитории для работы с MCU YTM32B1ME0 |
https://github.com/Franch-Toast/Vehicle-thermal-management-bench.git |
3 |
Высокоскоростной эмулятор J-Link JLink V8 USB JTAG ARM |
|
4 |
UM08003 JFlash |
|
5 |
Документация по MCU |
|
7 |
Отладочная плата NRF5340-DK в качестве программатора J-Link |
|
9 |
Ozone - The J-Link Debugger |
checkpoint
У вас всё так основательно - GCC, Makefile, а тут раз и какая-то проприетарная виндовая тулза для прошивки. Почему не OpenOCD или st-util/st-flash ?
А почему ? Я догадываюсь, что Вы хотите чтобы вывод printf() уходил в дебагер, но на сколько это удобно ? На мой взгляд слать вывод в UART0 - более основательное решение, позволяющее вести отладку дедовским методом без лишних устройств. :)
aabzel Автор
Почему проприетарныя? Это же утилиты из состава всеми признанного Segger J-link: Ozone, jflash, jflashLight.
Всё, что связано с STM тут вообще работать не будет. Это же абсолютно другой MCU YTM32.
Для OpenOCD у нас просто нет cfg файла под YTM32B1ME05G0MLQ. А так можно было бы отлаживаться и OpenOCD, как в случае с Artery (AT32F4x).
checkpoint
Если не ошибаюсь Segger J-link это проприетарная фиговина, все тулы у них проприетарные и поддержки опенсорса у них нет. У меня лежит где-то в шкафчике этот Segger, но я ни разу им не пользовался именно потому, что он закрыт. Есть более человечные решения на базе FTDI.
Но протокол то Вы используете - SWD от STmicro ? Значит st-flash должен работать. Ну чисто гипотетически. :)
Конфиг для OpenOCD можно составить самому если знать на каких пинах какие сигналы JTAG разведены.
segment
Эм, ну и что? Эта "фиговина" работает быстро и надежно.
aabzel Автор
sEGGER это, пожалуй, одна из немногих печально известных компаний у которых каждая новая версия клиентского софта J-link хуже предыдущей...
Да это так...
Все мои коллеги сидят на J-link версии не превышающей 6.20, хотя сейчас уже есть 7.66. В новых версиях GUI даже окно на весь экран сделать невозможно. Хотя раньше эта возможность была. И лог прошивки раньше был информативнее, чем сейчас.
А самые стабильные прошивки для J-link датируются аж 2014 годом! 11 летняя давность! Остальное просто не работает и постоянно сваливается в Hard Fault. Это как?
Утилита J-Flash просто блочит неоригинальные китайские отладчики J-link V9 за 3к RUR и превращает их в кирпичи. Происходит это обновлением прошивки без предупреждения. У нас на этаже уже три таких кирпичика лежит.
В результате ничего не остается как покупать оригинальный sEGGER V12 отладчик за 120kRUR.
Это как?
segment
Не замечал особой разницы, возможно потому что не так часто пользовался именно их GUI. Например, работа с segger embedded studio всегда была шустрой и отладка была без каких-либо проблем на всех версиях драйверов. Работа через утилиты nordic semiconductor (через nrfutils) тоже была всегда безпроблемной.
aabzel Автор
При этой Segger ПО не видит J-link программаторов от того же nordic .
Поэтому nordic выпустил свою консольную утилиту для обновления.
C:\Program Files (x86)\Nordic Semiconductor\nrf-command-line-tools\bin\nrfjprog.exe
Это как?
sEGGER это пример цинничного Vendor Locking-га.
segment
Можно тут подробнее?
Она имеет заточенный под nrf интерфейс, в чем вопрос? Она всё также работает на JLink.
Эм, а что Вы хотели от неоригинальных копий? Вы же понимаете все риски с этим связанные. Вы говорите о покупке оригинального отладчика так, как будто это что-то плохое. Если у Вас работа связана с железом, и Вы его используете в своей работе постоянно, то покупка оригинального отладчика не выглядит дикой.
aabzel Автор
Да, но надо ещё и для учёбы себе купить один отдельный программатор. А 120k это дорого.
segment
Зависит конечно от учёбы, но на почти всех отладочных платах (например, от nordic и от stm) стоят встроенные отладчики, ничего дополнительно покупать не нужно.
aabzel Автор
Забудьте про stm и nordic.
На дворе санкции!
Теперь надо работать только с китайскими микроконтроллерами: Artery, YunTu, GigaDev, Esp32, Nuvoton.
На отладке YTM32 отсутствует встроенный отладчик.
aabzel Автор
del
segment
Зачем про них забывать? Их новые чипы огонь, особенно у nordic.
Новые китайские друзья не могут сделать свой отладчик? =)
Antares1991
STM - да, огонь, но у Nordic сами чипы, может, и огонь, но SDK сваливается в УГ. За 2 года 2 раза мигрировали на более новые версии, т.к. выявляли серьёзные баги в из SDK. К слову, техподдержка их в основном всегда на все найденные баги предлагает мигрировать на новые версии SDK с новыми багами. В итоге остановились на 2.6.0 с парочкой грязных воркэраундов, и молимся, чтобы заказчик не потребовал новых фич, которые бы потребовали миграции на другую версию SDK.
"Нормальные" китайские подделки мимикрируют под урезанную EDU-версию J-Link и не огребают таких проблем с подлинностью, как более навороченные. Пиратство, к слову осуждаю, и китайские J-Link не использую, благо есть легальные решения для Nordic и ST, но считаю, что segger как-то слишком уж жадные.
Как увидел, что речь пошла про отдельный J-Link сильно удивился и аж пролистал назад, чтобы увидеть, что китайцы на свою отладку встроенный дебаггер зажопили.
segment
Да, согласен. Я использовал их softdevice, и отладка в нем была боль. После того как они перешли на zephyr, который собирает прошивку через миллион скриптов, генераций (и еще очень долго) — перестал пользоваться их SDK, разве что смотрел их SDK просто как референс в некоторых моментах. На голое железо простой софт ложится очень хорошо, так как сам чип учитывает некоторые особенности разработки ПО. И когда я говорил про "огонь" — я имел ввиду только чипы, не SDK.
aabzel Автор
Что значит акроним УГ?
aabzel Автор
libc rdimon мне нужен только лишь для того, чтобы работала функция snprintf() для float чисел.
Это надо для UART-CLI. Для сериализации структур.
Если найду более компактную реализацию libc охотно перейду на нее.
checkpoint
rdimon это обертка для передачи обработки в дебаггер и выполнении её на стороне хоста. Используйте newlib-nano (
-u _printf_float
).Для инициализации LIBC потребуется сделать свой sbrk() для выделения памяти на куче, но это три строки кода. Хотя, возможно в Вашем тулчейне он уже есть.