- PVSM.RU - https://www.pvsm.ru -
Я всей душой люблю малоизвестных производителей. Зачастую их продукты имеют фичи, недоступные у их более именитых конкурентов, по очень интересной цене (однажды меня очень выручило наличие встроенной в SoC полуамперной зарядки для аккумулятора и нескольких LDO, способных запитать всю периферию). Кроме того, сроки и условия поставки какого-нибудь Nanjing Qinheng Microelectronics [1] могут приятно удивить разработчиков, привыкших за последние два ковидных года к конскому ценнику и 52+ неделям доставки на ST, TI, Nordic и прочие привычные вещи. Логистика становится особенно приятной, если массовое производство планируется в Китае и на площадке присутствует ваша китайская команда, способная разрулить возникающие проблемы. Да и доставка из Шеньчженя в Шеньчжень проще и предсказуемей, чем со склада глобального дистрибьютора и растаможка в России.

Незадолго до новогодних праздников мне в руки попал B91 Generic Starter Kit [2]. Отладка построена на базе TLSR9518A [3] - RISC-V SoC с поддержкой Bluetooth Classic, BLE, собственным AI-движком и кучей других плюшек, позволяющих сделать относительно сложное носимое устройство по достаточно низкой цене. На отладке распаян старший чип из линейки, ориентированный на задачи, связанные с аудио и одновременной поддержкой как классического Bluetooth, так и BLE, но в линейке есть и более простые устройства. В общем - идеальный кандидат на то, чтобы развеять тоску и отвлечь от тазика с оливье.
Telink раньше был известен в первую очередь благодаря сверхдешевым BLE-чипам, построенным на собственном ядре, но с недавнего времени в линейке появились и RISC-V.
На вики [4] вендора присутствуют ссылки на IDE, тулчейн и примеры кода. Если бы мы отлаживали что-то более распространенное в наших краях, то этого было бы достаточно, но здесь производитель приготовил несколько сюрпризов:
IDE только под винду, которой у меня нет (да и тысячи вендорских IDE на эклипсе уже набили оскомину. А после того, как WICED-Studio отказалась запускать отладку на CYW954907 пока я не уберу все брейкпойнты, я принял решение по возможности не использовать такие решения). Поэтому мы будем использовать связку CMake + VSCode.
Сервер, на котором хранятся IDE и тулчейн, находится где-то в тибетском монастыре, подключенном по dial-up'у, по крайней мере средняя скорость закачки в 10кб/с и более трех тысяч разрывов закачки намекают об этом.
Тулчейн неполный, мы можем собрать и зашить бинарь, но gdb-сервер не может стартовать из-за отсутствия одной из библиотек. Эти и другие проблемы мы попробуем решить.
Я использовал в процессе Ubuntu 21.10, так что если вы работаете с другой ОС, то возможно придется немного скорректировать команды.
sudo apt update && sudo apt upgrade && sudo apt autoremove
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386
sudo apt install -y make cmake wget unzip libncurses5
Его можно собрать самому по инструкции [5] или же скачать готовую сборку с гитхаба разработчиков ядра. У меня не получилось собрать его с ходу, а разбираться интереса не было. Поэтому, если кто укажет на причину - буду весьма благодарен.
По умолчанию предлагается вендором.
wget https://github.com/andestech/Andes-Development-Kit/releases/download/ast-v3_2_3-release-linux/nds32le-elf-mculib-v5f.txz
mkdir toolchain
tar -xvf nds32le-elf-mculib-v5f.txz -C toolchain
rm nds32le-elf-mculib-v5f.txz
https://github.com/andestech/Andes-Development-Kit/releases/download/ast-v3_2_3-release-linux/nds32le-elf-newlib-v5f.txz
mkdir toolchain
tar -xvf nds32le-elf-newlib-v5f.txz -C toolchain
rm nds32le-elf-newlib-v5f.txz
В комплекте с девбордой идет JTAG-отладчик от вендора, но в принципе не должно возникнуть особых проблем с использованием других аппаратных средств, поддерживающих OpenOCD. Единственный нюанс - TLSR9518A, установленный на плате, предназначен исключительно для оценки и единственный из всей линейки не имеет встроенной FLASH-памяти.
Для работы с вендорским отладчиком потребуется утилита для прошивки внешней флешки и отладчик ICE, модифицированный OpenOCD.
wget https://github.com/andestech/Andes-Development-Kit/releases/download/ast-v3_2_3-release-linux/flash.zip
wget https://github.com/andestech/Andes-Development-Kit/releases/download/ast-v3_2_3-release-linux/ice.zip
unzip flash.zip -d toolchain
unzip ice.zip -d toolchain
rm -rf flash.zip ice.zip
cd toolchain/ice/
chmod +x ICEman.sh
./ICEman.sh
Поддержка семейства TLSR9 также заявлена в JLink, но я писал статью по горячим следам и у меня не было его под рукой.
В том, что касается SDK, Telink придерживается подхода, похожего на тот, что использовали когда-то Nordic со свими SoftDevice - отдельный SDK под каждую задачу. Нужный вам можно найти на вики, а для примера я решил использовать Driver SDK, предназначенный для работы с периферией чипа. Стоит отметить, что Bluetooth SDK предполагает работу в суперцикле и не имеет ни малейшего намека на поддержку FreeRTOS, в отличие от Driver SDK. Представители вендора не дали прямого ответа, почему сделано именно так, но горячо уверили, что к осени SDK получит мощный апдейт. Заявлена поддержка Zephyr, но без BLE и, судя по треду [6], ситуация вряд ли улучшится в ближайшее время. Поэтому, если вы захотите начинать разработку следующего устройства на основе православного китайского чипа - имейте в виду такие особенности, они возникают достаточно часто.
wget http://wiki.telink-semi.cn/tools_and_sdk/Driver/B91_Driver_SDK.zip
mkdir driver_sdk
unzip B91_Driver_SDK.zip -d driver_sdk/
rm B91_Driver_SDK.zip
Единственное, чего нам не хватает сейчас - инструкции по сборке. За основу я взял UART_DEMO [7], немного подправив его, чтобы сделать возможной out-of-tree сборку и отладку.
cmake_minimum_required(VERSION 3.0)
project(apptest)
enable_language(C ASM)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS)
set(RISCV_TOOLCHAIN ${CMAKE_CURRENT_LIST_DIR}/../toolchain/nds32le-elf-mculib-v5f/bin)
set(DRIVER_SDK ${CMAKE_CURRENT_LIST_DIR}/../driver_sdk/B91_Driver_Demo)
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_C_COMPILER ${RISCV_TOOLCHAIN}/riscv32-elf-gcc)
set(CMAKE_CXX_COMPILER ${RISCV_TOOLCHAIN}/riscv32-elf-g++)
set(CMAKE_ASM_COMPILER ${RISCV_TOOLCHAIN}/riscv32-elf-gcc)
set(OBJCOPY ${RISCV_TOOLCHAIN}/riscv32-elf-objcopy)
set(OBJDUMP ${RISCV_TOOLCHAIN}/riscv32-elf-objdump)
set(NM ${RISCV_TOOLCHAIN}/riscv32-elf-nm)
set(READELF ${RISCV_TOOLCHAIN}/riscv32-elf-readelf)
set(SIZE ${RISCV_TOOLCHAIN}/riscv32-elf-size)
add_definitions(-DMCU_STARTUP_FLASH_B91=1)
add_compile_options(-Og -g3 -mcpu=d25f -mext-dsp -mabi=ilp32f -std=c99)
add_compile_options(-ffunction-sections -fdata-sections -fpack-struct -fshort-enums -flto)
add_compile_options(-fmessage-length=0 -fomit-frame-pointer -fno-strict-aliasing -fshort-wchar -fuse-ld=bfd)
add_compile_options(-Wall -Wno-nonnull-compare -Wextra -Wshadow -Werror -Wno-gnu-zero-variadic-macro-arguments)
set(CMAKE_EXE_LINKER_FLAGS "-Og -g3 -nostartfiles -static -T"${DRIVER_SDK}/link/flash_boot.link" -Wl,--gc-sections")
link_libraries(-lB91)
aux_source_directory(${DRIVER_SDK}/common SRCS_COMMON)
aux_source_directory(${DRIVER_SDK}/drivers/B91 SRCS_DRIVERS_B91)
aux_source_directory(${DRIVER_SDK}/vendor/common SRCS_VENDOR_COMMON)
aux_source_directory(${DRIVER_SDK}/vendor/UART_DEMO SRCS_APP)
set(SRCS
${SRCS_COMMON}
${SRCS_DRIVERS_B91}
${SRCS_VENDOR_COMMON}
${SRCS_APP}
${DRIVER_SDK}/boot/B91/cstartup_b91_flash.S)
include_directories(${CMAKE_CURRENT_LIST_DIR})
include_directories(${DRIVER_SDK})
include_directories(${DRIVER_SDK}/vendor/common)
include_directories(${DRIVER_SDK}/drivers/B91)
include_directories(${DRIVER_SDK}/common)
link_directories(${DRIVER_SDK}/drivers/B91)
add_executable(${PROJECT_NAME}.elf ${SRCS})
add_custom_target(BIN ALL
COMMAND ${OBJCOPY} -S -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin
COMMAND ${SIZE} ${PROJECT_NAME}.elf
COMMAND ${OBJDUMP} -x -d -C ${PROJECT_NAME}.elf > objdump.txt
COMMAND ${NM} -n -l -C ${PROJECT_NAME}.elf > symbol.txt
COMMAND ${READELF} -a ${PROJECT_NAME}.elf > readelf.txt
DEPENDS ${PROJECT_NAME}.elf
)
Я поместил этот файл в директорию app, в которой планирую хранить и остальные исходники. Теперь можно запустить сборку.
cd app && mkdir build && cd build
cmake ..
make
Для комфортной работы потребуется создать несколько файлов с настройками для VSCode: c_cpp_properties.json, launch.json, settings.json, tasks.json, каждый из которых отвечает за определенный функционал среды разработки. Для нас наиболее интересны настройки сборки и отладки.
Эти таски отвечают за сборку бинарника и его загрузку в чип. Задача ICEman отвечает за gdb-соединение и должна быть запущена в фоне всегда, когда идет отладка чипа или его прошивка. Здесь же можно настроить необходимые зависимости, например, собирать проект каждый раз перед прошивкой, если вы тоже иногда забываете это сделать.
{
"version": "2.0.0",
"tasks": [
{
"label": "Build",
"type": "shell",
"command": "cmake -Bbuild && cd build && make",
"group": {
"kind": "build",
"isDefault": true
},
"options": {
"cwd": "${workspaceRoot}/app/"
},
"problemMatcher": {
"owner": "cpp",
"fileLocation": ["relative", "${workspaceFolder}/build"],
"pattern": {
"regexp": "^(.*):(\d+):(\d+):\s+(warning|error):\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
}
},
{
"label": "ICEman",
"type": "shell",
"isBackground": true,
"options": {
"cwd": "${workspaceRoot}/toolchain/ice"
},
"command": "./ICEman -Z v5",
},
{
"label": "flash",
"type": "shell",
"options": {
"cwd": "${workspaceRoot}/toolchain/flash/bin"
},
"command": "./SPI_burn -i ./../../../app/build/apptest.bin -v",
"dependsOn":["Build"],
}
]
}
Для отладки потребуется один из двух плагинов, Cortex-Debug [8] привычный для тех, кто уже использовал VSCode для отладки ARM-микроконтроллеров или Native Debug [9]. Большой разницы между ними нет, но Cortex-Debug позволяет несколько удобнее работать с Zephyr, FreeRTOS и выводить RTT-сообщения во встроенный терминал VSCode, поэтому я предпочитаю его. Настройки для обоих решений приведены ниже:
{
"configurations": [
{
"type": "gdb",
"name": "Native Debug",
"request": "attach",
"cwd": "${workspaceRoot}",
"valuesFormatting": "parseText",
"executable": "${workspaceRoot}/app/build/apptest.elf",
"preLaunchTask": "ICEman",
"target": ":1111",
"remote": true,
"gdbpath": "${workspaceRoot}/toolchain/nds32le-elf-mculib-v5f/bin/riscv32-elf-gdb",
"autorun": [
"reset-and-hold",
"flushregs",
"break main"
]
},
{
"name": "Cortex-Debug",
"cwd": "${workspaceRoot}",
"executable": "./app/build/apptest.elf",
"request": "launch",
"type": "cortex-debug",
"servertype": "external",
"gdbTarget": "localhost:1111",
"gdbPath": "${workspaceRoot}/toolchain/nds32le-elf-mculib-v5f/bin/riscv32-elf-gdb",
"preLaunchTask": "ICEman",
"runToEntryPoint": "main",
}
]
}
Для использования Cortex-Debug потребуется добавить несколько строчек в настройки проекта settings.json
{
"cortex-debug.openocdPath": "${workspaceRoot}/toolchain/ice/openocd",
"cortex-debug.gdbPath": "${workspaceRoot}/toolchain/nds32le-elf-mculib-v5f/nds32le-elf-mculib-v5f/bin/riscv32-elf-gdb",
"cmake.sourceDirectory": "${workspaceFolder}/app",
"taskExplorer.enableMake": false,
"search.exclude": {
"**/build": true
}
}
И подсказать IntelliSense, где лежат наши исходники и какие объявления мы хотим сделать при сборке. Для этих целей служит c_cpp_properties.json
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/app/**",
"${workspaceFolder}/driver_sdk/**"
],
"defines": [
"MCU_STARTUP_FLASH_B91=1",
"DEBUG"
],
"browse": {
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"cStandard": "c11",
"cppStandard": "c++17",
"intelliSenseMode": "gcc-arm"
}
],
"version": 4
}
В целом этого достаточно для комфортной разработки и отладки. Настройка автосборки для GIthub Actions не сильно отличается от тех шагов, что были проделаны выше, но на всякий случай оставлю рабочий пример [10] для другого не очень распространенного микроконтроллера. Посмотреть на проект целиком можно на гитхабе [11].
Автор: Егор Марков
Источник [12]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie-mikrokontrollerov/372302
Ссылки в тексте:
[1] Nanjing Qinheng Microelectronics: http://www.wch.cn/
[2] B91 Generic Starter Kit: http://wiki.telink-semi.cn/wiki/Hardware/B91_Generic_Starter_Kit_Hardware_Guide/
[3] TLSR9518A: http://wiki.telink-semi.cn/doc/ds/PB_TLSR9_Series_Product_Brief.pdf
[4] вики: http://wiki.telink-semi.cn/wiki/IDE-and-Tools/Compiler_Linux/
[5] инструкции: https://github.com/andestech/nds-gnu-toolchain
[6] треду: https://github.com/zephyrproject-rtos/zephyr/issues/34282
[7] UART_DEMO: http://wiki.telink-semi.cn/telink-document-package/CMakeLists.txt
[8] Cortex-Debug: https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug
[9] Native Debug: https://marketplace.visualstudio.com/items?itemName=webfreak.debug
[10] пример: https://github.com/aectaan/da1469x-cmake/blob/master/.github/workflows/da1469x.yml
[11] гитхабе: https://github.com/aectaan/Telink-TLSR9-CMake
[12] Источник: https://habr.com/ru/post/652471/?utm_source=habrahabr&utm_medium=rss&utm_campaign=652471
Нажмите здесь для печати.