Все микроконтроллеры программируются одинаково, если собирать код из 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

Глядя на оглавление флаера на микросхему, в первом приближении складывается такая мозаика.


Во флаере чип показан так:

 Device block diagram
Device block diagram

Каков план?

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

JRun.exe

Утилита для обновления прошивки по *.elf файлу

Колонка версия тут указана не случайно. Особенно для JFlash и Ozone. С другими версиями я не гарантирую, что инструкция будет совпадать с реальностью. Все программы добавляем в переменную PATH, чтобы можно было их вызывать просто по имени.

На самом деле, если вы до этого уже программировали другой микроконтроллер с ARM ядром компилятором GCC, то установка Eclipse, компилятора GCC и системы сборки Make абсолютно ничем не отличается от того, как это делалось в случае ARM-Coertex M4. Про это можно почитать тут:

#

Текст

URL

1

Настройка ToolChain(а) для Win10+GCC+С+Makefile+ARM Cortex-Mx+GDB

https://habr.com/ru/articles/673522/

2

Сборка firmware для CC2652 из Makefile

https://habr.com/ru/articles/726352/

5

ToolChain: Настройка сборки прошивок для микроконтроллеров Artery из Makefile

https://habr.com/ru/articles/792590/

В случае с YTM32x надо лишь акцентировать внимание на некоторых моментах.

Программная часть

Каждый нормальный вендор чипов бесплатно дает HAL для своего чипа. YunTu не исключение. Надо лишь зарегистрироваться на их сайте, придумать логин и пароль. После чего можно скачать спецификации на микроконтроллер, схемотехнику учебно-тренировочной электронной платы и тонны исходного кода HAL в SDK. Там же в личном кабинете можно получить наводку на сайты с GCC, Jlink, Ozone и прочее.

Исходники HAL можно взять с официального сайта. называется это SDK. Надо только зарегистрироваться и получишь много бесплатного Си-кода. Причем сам код HAL очень даже хорошо написан.

Утилита cloc показывает, что в официальном SDK порядка 80k строк Си-кода и 4k строк на ассемблере.

Анализ сорцов из SDK утилитой cloc
Анализ сорцов из SDK утилитой cloc

Среди всех сорцов надо обратить особое внимание на некоторые фундаментальные файлы:

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 можно посмотреть тут.

Подсказка по RAM и ROM памяти для MCU YTM32B1ME05G0MLQ
Подсказка по RAM и ROM памяти для MCU YTM32B1ME05G0MLQ

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) на одном единственном листочке. Получается вот такой конвейер метаморфоза файлов.

Схема ToolChain-a
Схема ToolChain-a

Для нас, как для программистов, исходниками тут являются файлы с расширениями *.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

Ссылка на флаер

https://ytmicro.com/product-2.php

8

J-Link LITE Cortex-M V9

https://kb.segger.com/J-Link_LITE_Cortex-M_V9

6

J-Link BASE Classic

https://www.chipdip.ru/product/j-link-usb-jtag-adapter

2

Чей-то репозитории для работы с MCU YTM32B1ME0

https://github.com/Franch-Toast/Vehicle-thermal-management-bench.git

3

Высокоскоростной эмулятор J-Link JLink V8 USB JTAG ARM

https://sl.aliexpress.ru/p?key=gleIGZ1

4

UM08003 JFlash

https://kb.segger.com/UM08003_JFlash#Command_line_options

5

Документация по MCU

https://account.ytmicro.com/#/download/dev

7

Отладочная плата NRF5340-DK в качестве программатора J-Link

https://habr.com/ru/articles/735422/

9

Ozone - The J-Link Debugger

https://www.segger.com/downloads/jlink/#Ozone

Комментарии (18)


  1. checkpoint
    29.01.2025 22:37

    У вас всё так основательно - GCC, Makefile, а тут раз и какая-то проприетарная виндовая тулза для прошивки. Почему не OpenOCD или st-util/st-flash ?

    Я пока выбрал rdimon.

    А почему ? Я догадываюсь, что Вы хотите чтобы вывод printf() уходил в дебагер, но на сколько это удобно ? На мой взгляд слать вывод в UART0 - более основательное решение, позволяющее вести отладку дедовским методом без лишних устройств. :)


    1. aabzel Автор
      29.01.2025 22:37

      Почему не st-util/st-flash ?

      Почему проприетарныя? Это же утилиты из состава всеми признанного Segger J-link: Ozone, jflash, jflashLight.

      Всё, что связано с STM тут вообще работать не будет. Это же абсолютно другой MCU YTM32.

      Для OpenOCD у нас просто нет cfg файла под YTM32B1ME05G0MLQ. А так можно было бы отлаживаться и OpenOCD, как в случае с Artery (AT32F4x).  


      1. checkpoint
        29.01.2025 22:37

        Если не ошибаюсь Segger J-link это проприетарная фиговина, все тулы у них проприетарные и поддержки опенсорса у них нет. У меня лежит где-то в шкафчике этот Segger, но я ни разу им не пользовался именно потому, что он закрыт. Есть более человечные решения на базе FTDI.

        Это же абсолютно другой MCU YTM32

        Но протокол то Вы используете - SWD от STmicro ? Значит st-flash должен работать. Ну чисто гипотетически. :)

        Конфиг для OpenOCD можно составить самому если знать на каких пинах какие сигналы JTAG разведены.


        1. segment
          29.01.2025 22:37

          Segger J-link это проприетарная фиговина

          Эм, ну и что? Эта "фиговина" работает быстро и надежно.


          1. aabzel Автор
            29.01.2025 22:37

            Эта "фиговина" работает быстро и надежно.


            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.
            Это как?


            1. segment
              29.01.2025 22:37

              Не замечал особой разницы, возможно потому что не так часто пользовался именно их GUI. Например, работа с segger embedded studio всегда была шустрой и отладка была без каких-либо проблем на всех версиях драйверов. Работа через утилиты nordic semiconductor (через nrfutils) тоже была всегда безпроблемной.


              1. aabzel Автор
                29.01.2025 22:37

                При этой Segger ПО не видит J-link программаторов от того же nordic  .
                Поэтому nordic  выпустил свою консольную утилиту для обновления.
                C:\Program Files (x86)\Nordic Semiconductor\nrf-command-line-tools\bin\nrfjprog.exe
                Это как?

                sEGGER   это пример цинничного Vendor Locking-га.


                1. segment
                  29.01.2025 22:37

                  При этой Segger ПО не видит J-link программаторов от того же nordic

                  Можно тут подробнее?

                  Поэтому nordic  выпустил свою консольную утилиту для обновления.C:\Program Files (x86)\Nordic Semiconductor\nrf-command-line-tools\bin\nrfjprog.exe

                  Она имеет заточенный под nrf интерфейс, в чем вопрос? Она всё также работает на JLink.

                  Утилита J-Flash просто блочит неоригинальные китайские отладчики J-link V9 за 3к RUR и превращает их в кирпичи. Происходит это обновлением прошивки без предупреждения. У нас на этаже уже три таких кирпичика лежит.

                  В результате ничего не остается как покупать оригинальный sEGGER  V12 отладчик за 120kRUR.
                  Это как?

                  Эм, а что Вы хотели от неоригинальных копий? Вы же понимаете все риски с этим связанные. Вы говорите о покупке оригинального отладчика так, как будто это что-то плохое. Если у Вас работа связана с железом, и Вы его используете в своей работе постоянно, то покупка оригинального отладчика не выглядит дикой.


                  1. aabzel Автор
                    29.01.2025 22:37

                     Вы говорите о покупке оригинального отладчика так, как будто это что-то плохое. Если у Вас работа связана с железом, и Вы его используете в своей работе постоянно, то покупка оригинального отладчика не выглядит дикой.

                    Да, но надо ещё и для учёбы себе купить один отдельный программатор. А 120k это дорого.


                    1. segment
                      29.01.2025 22:37

                      Зависит конечно от учёбы, но на почти всех отладочных платах (например, от nordic и от stm) стоят встроенные отладчики, ничего дополнительно покупать не нужно.


                      1. aabzel Автор
                        29.01.2025 22:37

                        Забудьте про stm и nordic.
                        На дворе санкции!
                        Теперь надо работать только с китайскими микроконтроллерами: Artery, YunTu, GigaDev, Esp32, Nuvoton.
                        На отладке YTM32 отсутствует встроенный отладчик.


                      1. aabzel Автор
                        29.01.2025 22:37

                        del


                      1. segment
                        29.01.2025 22:37

                        Забудьте про stm и nordic.

                        Зачем про них забывать? Их новые чипы огонь, особенно у nordic.

                        На дворе санкции!

                        Новые китайские друзья не могут сделать свой отладчик? =)


                      1. Antares1991
                        29.01.2025 22:37

                        • STM - да, огонь, но у Nordic сами чипы, может, и огонь, но SDK сваливается в УГ. За 2 года 2 раза мигрировали на более новые версии, т.к. выявляли серьёзные баги в из SDK. К слову, техподдержка их в основном всегда на все найденные баги предлагает мигрировать на новые версии SDK с новыми багами. В итоге остановились на 2.6.0 с парочкой грязных воркэраундов, и молимся, чтобы заказчик не потребовал новых фич, которые бы потребовали миграции на другую версию SDK.

                        • "Нормальные" китайские подделки мимикрируют под урезанную EDU-версию J-Link и не огребают таких проблем с подлинностью, как более навороченные. Пиратство, к слову осуждаю, и китайские J-Link не использую, благо есть легальные решения для Nordic и ST, но считаю, что segger как-то слишком уж жадные.

                        • Как увидел, что речь пошла про отдельный J-Link сильно удивился и аж пролистал назад, чтобы увидеть, что китайцы на свою отладку встроенный дебаггер зажопили.


                      1. segment
                        29.01.2025 22:37

                        но SDK сваливается в УГ

                        Да, согласен. Я использовал их softdevice, и отладка в нем была боль. После того как они перешли на zephyr, который собирает прошивку через миллион скриптов, генераций (и еще очень долго) — перестал пользоваться их SDK, разве что смотрел их SDK просто как референс в некоторых моментах. На голое железо простой софт ложится очень хорошо, так как сам чип учитывает некоторые особенности разработки ПО. И когда я говорил про "огонь" — я имел ввиду только чипы, не SDK.


                      1. aabzel Автор
                        29.01.2025 22:37

                         но SDK сваливается в УГ

                        Что значит акроним УГ?


    1. aabzel Автор
      29.01.2025 22:37

      libc rdimon мне нужен только лишь для того, чтобы работала функция snprintf() для float чисел.

      Это надо для UART-CLI. Для сериализации структур.
      Если найду более компактную реализацию libc охотно перейду на нее.


      1. checkpoint
        29.01.2025 22:37

        rdimon это обертка для передачи обработки в дебаггер и выполнении её на стороне хоста. Используйте newlib-nano (-u _printf_float).

        Для инициализации LIBC потребуется сделать свой sbrk() для выделения памяти на куче, но это три строки кода. Хотя, возможно в Вашем тулчейне он уже есть.