Изучаем RISC-V с платой Sipeed M1S

в 8:05, , рубрики: bl808, bouffalo, buildroot, linux, m1s, m1s dock, risc-v, sipeed, timeweb_статьи, tutorial

Наконец-то появилось время и желание пощупать и опробовать в деле давно купленную отладку от Sipeed на базе RISC-V SoC BL808. Попутно я решил собрать материал по теме и поделиться с читателями своим опытом использования этого SoC в разных сценариях. Помимо обзора отладки и SoC я подробно расскажу, что предоставляет производитель для энтузиастов, состав SDK,  как собрать Linux-ядро, примеры ее использования. Всем кому интересна данная тема — добро пожаловать под кат! =)

Изучаем RISC-V с платой Sipeed M1S - 1

Важно! Перед началом повествования, хотелось бы заранее оговориться, что основная цель, которую я преследую при написании этой статьи — рассказать о своем опыте и с чего можно начать при изучении отладочных плат. Я не являюсь профессиональным разработчиком встраиваемых систем, не являюсь системным программистом под Linux и могу допускать какие-либо ошибки в использовании терминологии, а так же использовать не самые оптимальные пути решения задач, etc. Но отмечу, что любая конструктивная и аргументированная критика только приветствуется. Что ж, поехали…

❯ Обзор отладочной платы Sipeed M1S с процессором BL808

Начнем с обзора того, что предоставляет данная отладка. Пойдем по пунктам. 

Сердцем данной отладки является AIoT SoC от BouffaloLab BL808 с большим количеством интересных опций:

  • 32-битное RISC-V ядро E907 (M0) с частотой 320 MHz;

  • энергоэффективное 32-битное RISC-V E902 (LP) c максимальной частотой 160 MHz;

  • 64-битное RISC-V ядро С906 (D0) с максимальной частотой 480 MHz.

Рекомендую запомнить обозначения и назначение этих трёх ядер, которые встроены в BL808.

  • NPU BLAI-100 (Bouffalo Lab AI engine) для AI-приложений, с помощью которых можно  реализовать аудио/видео распознавание/детекцию разных паттернов, общей производительностью 100 GOPS;

  • оперативная память 768 KB SRAM и 64 MB UHS PSRAM;

  • хранилище SPI-NOR Flash 16MB (128Mbit);

  • Wireless Frontend в виде 2.4GHz PHY трансивера с встроенным balun, PA/LNA и поддержкой внешних PA/LNA для увеличения RF-performance

  • поддержка протоколов Wi-Fi 802.11 b/g/n, Bluetooth 5 Dual-mode (BR/EDR/BLE), Zigbee / 802.15.4 и механизмом Coexistence;

  • аудиокодек с поддержкой ADC (работает с 2 микрофонами или микрофоном и Line-In) и DAC для вывода аудио на динамик, с Sample Rate 8-192 KHz 24 bit;

  • кодеки MJPEG, h.264 (Baseline/Main) с разрешением 1920x1080@30fps + 640x480@30fps;

  • аппаратные ускорители Scaler, OSD, G2D;

  • до 8-ROI (region-of-interest);

  • поддержка интерфейса камеры DVP, MIPI-CSI;

  • поддержка дисплейных интерфейсов SPI, DBI, DPI (RGB), MIPI-DSI;

  • поддержка самой разнообразной периферии:

    • USB 2.0 HS OTG;

    • Ethernet RMII интерфейс;

    • SD-card интерфейс;

    • 4x UART;

    • 2x SPI;

    • 4x I2C;

    • 8x PWM каналов;

    • I2S интерфейс;

    • PDM интерфейс;

    • Аналоговый компаратор;

    • Периферия для работы с IR;

    • Поддержка Touch-сенсоров;

    • 40 GPIO.

  • поддержка энергосберегающего режима (~1uA);

  • паябельный QFN 88-пиновый корпус.

На мой взгляд весьма и весьма не дурно, при рекомендованной цене в $6. Давайте взглянем на пару изображений, на которых отражена архитектура данного SoC:

Изучаем RISC-V с платой Sipeed M1S - 2

И обратим внимание на структуру внутреннего интерконнекта:

Изучаем RISC-V с платой Sipeed M1S - 3

Как вы уже читали выше — Bouffalo Lab BL808 укомплектован тремя ассиметричными RISC-V ядрами.

Первое ядро D0 — 64-битное RISC-V ядро Alibaba T-Head С906 RV64GCV+ (RV64IMAFCV, 480 MHz), с доступом к мультимедиа-периферии и NPU. На данном ядре выполняется основная ОС, будь то Linux или FreeRTOS. У этого ядра имеется MMU Sv39 c 128 / 256 / 512 TLB, благодаря наличию которого возможен запуск Mainline Linux. 

Изучаем RISC-V с платой Sipeed M1S - 4

Второе ядро M0 — 32-битное RISC-V ядро Alibaba T-head E907 RV32GCP+ (RV32IMAFCP, 320 MHz) с поддержкой 32/16-битных инструкций. Используется для запуска OpenBouffalo Firmware и доступа к Wi-Fi, Bluetooth, Zigbee, Audio, USB, Ethernet и прочей. 

Изучаем RISC-V с платой Sipeed M1S - 5

Третье ядро LP — энергоэффективное 32-битное RISC-V ядро Alibaba T-Head E902 RV32EMC c максимальной частотой 160 MHz.

Изучаем RISC-V с платой Sipeed M1S - 6

Общую схему логических соединений между ядрами можно изобразить следующим образом:

Изучаем RISC-V с платой Sipeed M1S - 7

При поиске в Интернете нашлись даже исходные коды на Verilog: https://github.com/XUANTIE-RV.

Вот такой Pinout самого чипа на модуле, который распаян на отладке:

Изучаем RISC-V с платой Sipeed M1S - 8

Перейдем к описанию самой отладочной платы, на которой установлен модуль. Распиновка самого модуля с SoC выглядит следующим образом:

Изучаем RISC-V с платой Sipeed M1S - 9

Вот так выглядит модуль со снятым экраном:

Изучаем RISC-V с платой Sipeed M1S - 10

Производитель любезно предоставляет весь спектр необходимой документации для аппаратной разработки. 

На непосредственно модуль:

  • даташит и Reference Manual на SoC можно найти тут;

  • даташит на модуль можно найти тут;

  • схематик на сам модуль можно найти тут;

  • используемый BOM можно на данной странице: 

  • модели схемотехнических примитивов для KiCad можно взять тут;

  • dxf-файл с размерами можно взять тут;

  • 3D Step модель можно взять тут.

На отладочную плату:

  • даташит на отладочную плату можно взять тут;

  • схематик на плату можно найти тут;

  • используемый BOM и позиционные обозначения элементов на плате можно найти тут;

  • dxf-файл с размерами можно взять тут;

  • 3D Step модель можно взять тут;

  • дополнительные мануалы и даташиты можно найти тут

И есть так же официальный каталог документов от Bouffalo, можно найти тут.

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

  • полная поддержка FreeRTOS;

  • базовая поддержка Linux, т.к. у SoC есть MMU и не потребуется uClinux;

  • C SDK;

  • MaixHAL C;

  • PikaPython SDK;

  • поддержка механизма ускоренного логического вывода BLAI с помощью встроенного SDK;

  • поддержка TinyMaix inference.

Помимо этого, есть все необходимые для разработки тулзы и документация:

Теперь рассмотрим саму отладку. Выглядит она следующим образом:

Изучаем RISC-V с платой Sipeed M1S - 11

Общая распиновка выглядит вот так:

Изучаем RISC-V с платой Sipeed M1S - 12

Для работы с платой предоставляется набор простой базовой периферии:

  • Onboard USB to UART debugger BL702, который используется для загрузки firmware и реализации функций отладчика;

  • аналоговый микрофон;

  • 1 LED;

  • 2 пользовательских кнопки;

  • BOOT-кнопка и RST-кнопка;

  • 1 слот для microSD, в который можно подключать JTAG-отладчик;

  • 2x USB type-C разъемы для подключения устройств по USB и вывода UART;

  • интерфейс для подключения диплея с тач-скрином;

  • MIPI camera interface; 

  • 32 пина GPIO.

Помимо этого, можно докупить внешние модули:

  • TF2JTAG, отладчик который устанавливается в microSD слот;

  • 2MP MIPI OV2685 камера;

  • 1.69’’ 280x240 дисплей с тач-контроллером.

Все необходимое можно приобрести на Aliexpress.

❯ Начало работы с отладкой

Перед тем, как начать что-то делать с платой, необходимо подготовить:

  • два USB type-C кабеля;

  • компьютер с ОС Ubuntu/Linux.

На отладке имеется два порта type-C — первый (UART) предназначен для реализации консольного интерфейса между ПК и M1S. Второй порт (OTG) используется для записи firmware или для реализации USB-функциональности. Помимо этого, на плате есть кнопки S1_Button, S2_button для пользовательских задач и две кнопки BOOT и RST, которые нам пригодятся в дальнейшем. 

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

Изучаем RISC-V с платой Sipeed M1S - 13

Hello World для M1S Dock

Первым шагом давайте подготовим среду разработки. Сделать это все достаточно просто. Как обычно, процесс подготовки начинается с установки зависимостей:

sudo apt install git flex bison libncurses-dev device-tree-compiler
lz4 curl make openssl libssl-dev libelf-dev elfutils tree build-essential

Следующим шагом склонируем репозиторий с примерами для M1S BL808:

git clone https://github.com/Sipeed/M1s_BL808_example.git

Будут загружены следующие файлы:

megalloid@megalloid:~$ tree -L 1 M1s_BL808_example/
M1s_BL808_example/
├── assets
├── c906_app
├── e907_app
├── LICENSE
├── partition
└── readme.md

4 directories, 2 files

Далее клонируем SDK:

git clone https://github.com/sipeed/M1s_BL808_SDK.git

После этого необходимо в директорию M1s_BL808_SDK создать директорию toolchain и загрузить его в нее:

mkdir -p M1s_BL808_SDK/toolchain
cd M1s_BL808_SDK/toolchain
git clone https://github.com/wonderfullook/m1s_toolchain.git

Далее нужно переименовать директорию m1s_toolchain в Linux_x86_64:

mv m1s_toolchain Linux_x86_64

Потом необходимо добавить переменную окружения для указания расположения тулчейна. Можно добавить это в ~/.bashrc, чтобы переменная добавлялась при старте терминала или можно на один раз:

megalloid@megalloid:~$ cd ../../
megalloid@megalloid:~$ cd M1s_BL808_SDK
megalloid@megalloid:~/M1s_BL808_SDK$ pwd
/home/megalloid/M1s_BL808_SDK
megalloid@megalloid:~/M1s_BL808_SDK$ export BL_SDK_PATH=/home/megalloid/M1s_BL808_SDK

Главное — не добавлять конечный символ / в эту переменную для избегания ошибок в дальнешем. 

Переходим к компиляции примера. Переходим в директорию M1s_BL808_example/c906_app и через запуск build.sh c аргументом примера — запускаем компиляцию и получаем d0fw.bin, который можно будет загрузить в плату.

Выведем список примеров:

megalloid@megalloid:~$ cd M1s_BL808_example
megalloid@megalloid:~/M1s_BL808_example$ tree -L 1 c906_app/
c906_app/
├── audio_recording
├── blai_mnist_demo
├── build.sh
├── camera_bypass_lcd
├── camera_dump
├── camera_streaming_through_wifi
├── cli_demo
├── flash_demo
├── gpio_demo
├── hello_world
├── i2c_touch
├── image_processing_demo
├── lfs_demo
├── lvgl_demo
├── Makefile
├── pikascript_demo
├── proj_config.mk
├── pwm_demo
├── spi_lcd
├── tinymaix_mnist_demo
├── tom_and_jerry_classification_demo
└── uvc_demo

Скомпилируем пример hello_world:

megalloid@megalloid:~/M1s_BL808_example$ cd c906_app/
megalloid@megalloid:~/M1s_BL808_example/c906_app$ ./build.sh gpio_demo

Далее, спустя небольшое время, появится первые необходимые бинари для загрузки в плату в директории build_out:

megalloid@megalloid:~/M1s_BL808_example/c906_app$ tree build_out/ -L 1
build_out/
├── bl808
├── bl808_c906_freertos
├── bl808_ring
├── bl808_std
├── bl808_xram
├── blai_nn
├── blai_npu_encoder
├── blfdt
├── bl_mm
├── blog
├── bl_os_adapter
├── cli
├── d0fw.bin
├── dsp2
├── dsp2_cli_demo
├── fatfs
├── freertos_posix
├── freetype
├── gpio_demo
├── gpio_demo.bin
├── gpio_demo.elf
├── gpio_demo.map
├── hello_world
├── hello_world.bin
├── hello_world.elf
├── hello_world.map
├── hosal
├── lfs
├── lvgl
├── lwip
├── m1s_c906_xram
├── m1s_common_xram
├── m1s_lfs_c906
├── m1s_model_runner
├── m1s_start
├── m1s_tools
├── mjpeg_sender_bl808
├── newlibc
├── romfs
├── rtsp_server
├── sdh_helper
├── sensor
├── utils
├── venc_device
├── venc_framework
├── vfs
└── yloop

40 directories, 7 files

Для этого необходимо дополнительно откомпилировать firmware для ядра E907:

megalloid@megalloid:~/M1s_BL808_example/c906_app$ cd ..
megalloid@megalloid:~/M1s_BL808_example$ cd e907_app/
megalloid@megalloid:~/M1s_BL808_example/e907_app$ ./build.sh firmware

После непродолжительной компиляции будет получен необходимый бинарный файл:

megalloid@megalloid-xubuntu:~/sources/M1s_BL808_example/e907_app$ tree build_out/ -L 1
build_out/
├── bl606p_phyrf
├── bl808_audio
├── bl808_e907_std
├── bl808_net
├── bl808_peri_e907
├── bl808_ring
├── bl808_user_xram
├── bl808_wlan_cli_demo
├── bl808_xram
├── blcrypto_suite
├── blfdt
├── blmtd
├── blog
├── bl_os_adapter
├── bugkiller_freertos
├── cli
├── coredump
├── dns_server
├── easyflash4
├── fatfs
├── firmware
├── firmware.bin
├── firmware.elf
├── firmware.map
├── freertos_e907
├── freertos_e907_helper
├── hosal
├── lfs
├── lwip
├── lwip_dhcpd
├── m1s_boot_d0
├── m1s_common_xram
├── m1s_e907_xram
├── m1s_lfs_e907
├── m1s_msc
├── mbedtls_lts
├── netutils
├── newlibc
├── remote_net_manager
├── romfs
├── sdh_helper
├── startup_bl808
├── usb_stack
├── utils
├── vfs
├── wifi
├── wifi_bt_coex
├── wifi_hosal
├── wifi_manager
├── wpa_supplicant
└── yloop

48 directories, 3 files

Теперь необходимо разобраться с тем, как загрузить полученный бинарник на плату и запустить его. Для этого необходимо скачать отсюда архив с программами для перепрошивки Bouffalo Lab Dev Cube. 

После скачивания извлекаем архив и в директории увидим множество файлов:

megalloid@megalloid:~/BouffaloLabDevCube-v1.9.0$ tree -L 1
.
├── bflb_iot_tool.exe
├── bflb_iot_tool-macos
├── bflb_iot_tool-ubuntu
├── BLDevCube.exe
├── BLDevCube-macos
├── BLDevCube-ubuntu
├── Changelog.txt
├── chips
├── clear.bat
├── clear.sh
├── config.toml
├── docs
├── log
├── ReleaseNote.txt
└── utils

4 directories, 11 files

Сделаем необходимые файлы исполняемыми:

megalloid@megalloid:~/BouffaloLabDevCube-v1.9.0$ chmod +x ./BLDevCube-ubuntu
megalloid@megalloid:~/BouffaloLabDevCube-v1.9.0$ chmod +x ./bflb_iot_tool-ubuntu

Рассмотрим несколько способов заливки прошивки на плату. Первый способ через приложение с GUI. Откроем программу BLDevCube-ubuntu:

megalloid@megalloid:~/BouffaloLabDevCube-v1.9.0$ sudo ./BLDevCube-ubuntu

Предлагается выбрать SoC, с которым будет осуществляться работа. Выбираем BL808:

Изучаем RISC-V с платой Sipeed M1S - 14

Далее необходимо скормить программе четыре файла:

  1. partition table — находится в M1s_BL808_example/partition/partition_cfg_16M_m1sdock.toml 

  2. boot2 — находится BouffaloLabDevCube-v1.9.0/chips/bl808/builtin_imgs/boot2_isp_bl808_v6.6.2/boot2_isp_debug.bin

  3. firmware — M1s_BL808_example/e907_app/build_out/firmware.bin

  4. d0fw — M1s_BL808_example/c906_app/build_out/hello_world.bin

Выглядит это следующим образом:

Изучаем RISC-V с платой Sipeed M1S - 15

После этого я выбираю порт /dev/ttyACM1 и скорость 2.000.000 бод, и нажимаю Create & Download:

Изучаем RISC-V с платой Sipeed M1S - 16

Далее необходимо нажать на плате кнопку RST и будет запущено ПО. Во-первых появится съемный накопитель, на который можно будет скидывать свои прошивки для ядра D0. Во-вторых в порту /dev/ttyACM0 будет выводиться раз в секунду фраза Hello World:

megalloid@megalloid:~/BouffaloLabDevCube-v1.9.0$ minicom -D /dev/ttyACM0 -b2000000

Выглядит это так:

Изучаем RISC-V с платой Sipeed M1S - 17

Если открыть /dev/ttyACM1 с бодрейтом 2.000.000, то можно попасть в CLI-приложение, которое работает на втором ядре BL808:

megalloid@megalloid:~/BouffaloLabDevCube-v1.9.0$ minicom -D /dev/ttyACM1 -b2000000
Изучаем RISC-V с платой Sipeed M1S - 18

Прошивать плату можно также через CLI-приложение в два этапа:

megalloid@megalloid:~/BouffaloLabDevCube-v1.9.0$ ./bflb_iot_tool-ubuntu 
--chipname=bl808 
--port=/dev/ttyACM1 
--baudrate=2000000 
--firmware="/home/megalloid/sources/M1s_BL808_example/e907_app/build_out/firmware.bin"
--pt="/home/megalloid/sources/M1s_BL808_example/partition/partition_cfg_16M_m1sdock.toml"
--boot2="/home/megalloid/sources/BouffaloLabDevCube-v1.9.0/chips/bl808/builtin_imgs/boot2_isp_bl808_v6.6.2/boot2_isp_debug.bin"

megalloid@megalloid:~/BouffaloLabDevCube-v1.9.0$ ./bflb_iot_tool-ubuntu 
--chipname=bl808 
--port=/dev/ttyACM1 
--baudrate=2000000 
--firmware="/home/megalloid/sources/M1s_BL808_example/c906_app/build_out/hello_world.bin" 
--addr=0x101000 
--single

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

❯ Отладка программ с OpenOCD и JTAG

Для отладки по JTAG я купил предлагаемый Sipeed отладчик, который выглядит следующим образом:

Изучаем RISC-V с платой Sipeed M1S - 19

Подключать его следует вот так:

Изучаем RISC-V с платой Sipeed M1S - 20

Скачаем отладчик по этой ссылке, распакуем содержимое архива в удобную директорию и запустим его:

megalloid@megalloid:~$ tar xvf T-Head-DebugServer*
megalloid@megalloid:~$ chmod +x T-Head-DebugServer-linux-x86_64-V5.16.5-20221021.sh
megalloid@megalloid:~$ mkdir m1s_debugger/
megalloid@megalloid:~$ sudo ./T-Head-DebugServer-linux-x86_64-V5.16.5-20221021.sh -i
Do you agree to install the DebugServer? [yes/no]:yes
Set full installing path:/home/megalloid/m1s_debugger
This software will be installed to the path: (/home/megalloid/m1s_debugger)? [yes/no/cancel]:yes 
Installing ...
Done!
You can use command "DebugServerConsole" to start DebugServerConsole!
(NOTE: The full path of 'DebugServerConsole.elf' is: /home/megalloid/m1s_debugger/T-HEAD_DebugServer)

Проверим, что отладчик определился в системе:

megalloid@megalloid:~$ lsusb | grep -i bouffalo
Bus 001 Device 056: ID ffff:ffff Bouffalo Bouffalo Serial
Bus 001 Device 053: ID 42bf:b210 Bouffalo C-Sky CKLink-Lite

После этого обновим ПО отладчика:

megalloid@megalloid:~$ git clone https://github.com/cjacker/opensource-toolchain-bouffalo-lab
megalloid@megalloid:~$ sudo apt-get install python3-pip
megalloid@megalloid:~$ pip install bflb-mcu-tool
megalloid@megalloid:~$ cd opensource-toolchain-bouffalo-lab/sipeed_rv_debugger_plus_factory_firmware
megalloid@megalloid:~$ PATH="$HOME/.local/bin:$PATH"

Зажимаем клавишу Boot и подключаем отладчик. Запускаем обновление:

megalloid@megalloid:~/opensource-toolchain-bouffalo-lab/sipeed_rv_debugger_plus_factory_firmware$ bflb-mcu-tool --chipname=bl702 --interface=uart --port=/dev/ttyACM2 --baudrate=2000000 -firmware=bl702_cklink_whole_img_v2.2.bin

В консоли /dev/ttyACM1 необходимо включить JTAG-отладку:

# jtag_cpu0                                                                     
Enable CPU1 (D0/C906) on PIN0/PIN1/PIN2/PIN3(TCK/TDI/TMS/TDO)

После этого можно запустить сервер отладчика:

megalloid@megalloid:~$ DebugServerConsole -port 12345
+---                                                    ---+
|  T-Head Debugger Server (Build: Oct 21 2022)	           |
   User   Layer Version : 5.16.05 
   Target Layer version : 2.0
|  Copyright (C) 2022 T-HEAD Semiconductor Co.,Ltd.        |
+---                                                    ---+
T-HEAD: CKLink_Lite_V2, App_ver unknown, Bit_ver null, Clock 2526.316KHz,
       5-wire, With DDC, Cache Flush On, SN CKLink_Lite_Vendor-rog 17115D.
+--  Debug Arch is RVDM.  --+
+--  CPU 0  --+
RISCV CPU Info:
	WORD[0]: 0x0910090d
	WORD[1]: 0x12046000
	WORD[2]: 0x260c0001
	WORD[3]: 0x30030066
	WORD[4]: 0x42180000
	WORD[5]: 0x50000000
	WORD[6]: 0x60000753
	MISA   : 0x8000000000b4112d
Target Chip Info:
	CPU Type is C906FDV, Endian=Little, Vlen=128, Version is R2S1P6.
	DCache size is 32K, 4-Way Set Associative, Line Size is 64Bytes, with no ECC.
	ICache size is 32K, 2-Way Set Associative, Line Size is 64Bytes, with no ECC.
	Target is 1 core.
	MMU has 128 JTLB items.
	PMP zone num is 8.
	HWBKPT number is 4, HWWP number is 4.
	MISA: (RV64IMAFDCVX, Imp M-mode, S-mode, U-mode)

GDB connection command for CPUs(CPU0):
	target remote 127.0.0.1:12345
	target remote 192.168.2.2:12345

****************  DebuggerServer Commands List **************
help/h
	Show help informations.
*************************************************************
DebuggerServer$ 

Скачиваем T-Head Xuantie RISC-V embeded gcc:

megalloid@megalloid:~$ wget https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1663142243961/Xuantie-900-gcc-elf-newlib-x86_64-V2.6.1-20220906.tar.gz
megalloid@megalloid:~$ mkdir xuantie-riscv64-embed-toolchain
megalloid@megalloid:~$ tar xvf Xuantie-900-gcc-elf-newlib-x86_64-V2.6.1-20220906.tar.gz --strip-components=1 -C ./xuantie-riscv64-embed-toolchain
megalloid@megalloid:~$ export PATH=/home/megalloid/sources/xuantie-riscv64-embed-toolchain/bin/:$PATH

И подключаемся с использованием GDB к серверу:

megalloid@megalloid:~$ riscv64-unknown-elf-gdb
GNU gdb (Xuantie-900 elf newlib gcc Toolchain V2.6.1 B-20220906) 10.0.50.20200724-git
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=riscv64-unknown-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) target remote localhost:12345
Remote debugging using localhost:12345
warning: No executable has been specified and target does not support
determining executable automatically.  Try using the "file" command.
0x0000000050109ca4 in ?? ()
(gdb) file M1s_BL808_example/c906_app/build_out/hello_world.elf
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Reading symbols from M1s_BL808_example/c906_app/build_out/hello_world.elf...
(gdb) b main
Note: breakpoint 1 also set at pc 0x5010e1c0.
Breakpoint 2 at 0x5010e1c0: file /home/megalloid/sources/M1s_BL808_example/c906_app/hello_world/main.c, line 10.
(gdb) c
Continuing.

В общем, всё достаточно стандартно. Идём дальше.

❯ Запускаем Demo Linux на M1S Dock

Теперь попробуем запустить Linux на данной отладке. Самый простой способ — для проверки скачать файл предварительно откомпилированных бинарей и залить их на отладку.

megalloid@megalloid:~$ wget https://dl.sipeed.com/fileList/MAIX/M1s/M1s_Dock/7_Firmware/m1sdock_linux_20221116.zip
megalloid@megalloid:~$ mkdir m1sdock_linux
megalloid@megalloid:~$ unzip m1sdock_linux_20221116.zip -d m1sdock_linux/
Archive:  m1sdock_linux_20221116.zip
   creating: m1sdock_linux/.assets/
  inflating: m1sdock_linux/.assets/iot.png  
  inflating: m1sdock_linux/.assets/mcu.png  
  inflating: m1sdock_linux/low_load_bl808_d0@0x58000000.bin  
  inflating: m1sdock_linux/low_load_bl808_m0@0x58000000.bin  
  inflating: m1sdock_linux/steps.md  
  inflating: m1sdock_linux/whole_img_linux@0xD2000.bin  

Открываем программатор Bouffalo Lab Dev Cube и прошиваем первую часть образа следующим образом:

Изучаем RISC-V с платой Sipeed M1S - 21

Переходим на вкладку IOT и прошиваем вторую часть:

Изучаем RISC-V с платой Sipeed M1S - 22

Открываем в терминале /dev/ttyACM0 с baudrate 2.000.000 и нажимаем RST:

dynamic memory init success,heap size = 26 Kbyte 
C906 start...
mtimer clk:1000000
linux load start... 
len:0x00376c53
vm linux load done!
dtb load done!
opensbi load done!

load time: 606588 us 

OpenSBI v0.6
   ____                    _____ ____ _____
  / __                   / ____|  _ _   _|
 | |  | |_ __   ___ _ __ | (___ | |_) || |
 | |  | | '_  / _  '_  ___ |  _ < | |
 | |__| | |_) |  __/ | | |____) | |_) || |_
  ____/| .__/ ___|_| |_|_____/|____/_____|
        | |
        |_|

Platform Name          : T-HEAD Xuantie c910
Platform HART Features : RV64ACDFIMSUVX
Platform Max HARTs     : 1
Current Hart           : 0
Firmware Base          : 0x3eff0000
Firmware Size          : 56 KB
Runtime SBI Version    : 0.2

MIDELEG : 0x0000000000000222
MEDELEG : 0x000000000000b1ff
[    0.000000] Linux version 5.10.4 (taorye@tao-b660mstx) (riscv64-unknown-linux-gnu-gcc (Xuantie-900 linux-5.10.4 g2
[    0.000000] earlycon: sbi0 at I/O port 0x0 (options '')
[    0.000000] printk: bootconsole [sbi0] enabled
[    0.000000] Zone ranges:
[    0.000000]   DMA32    [mem 0x0000000050000000-0x0000000053ffffff]
[    0.000000]   Normal   empty
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000050000000-0x0000000053ffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000050000000-0x0000000053ffffff]
[    0.000000] On node 0 totalpages: 16384
[    0.000000]   DMA32 zone: 224 pages used for memmap
[    0.000000]   DMA32 zone: 0 pages reserved
[    0.000000]   DMA32 zone: 16384 pages, LIFO batch:3
[    0.000000] software IO TLB: Cannot allocate buffer
[    0.000000] SBI specification v0.2 detected
[    0.000000] SBI implementation ID=0x1 Version=0x6
[    0.000000] SBI v0.2 TIME extension detected
[    0.000000] SBI v0.2 IPI extension detected
[    0.000000] SBI v0.2 RFENCE extension detected
[    0.000000] riscv: ISA extensions acdfimsuv
[    0.000000] riscv: ELF capabilities acdfimv
[    0.000000] percpu: Embedded 17 pages/cpu s32600 r8192 d28840 u69632
[    0.000000] pcpu-alloc: s32600 r8192 d28840 u69632 alloc=17*4096
[    0.000000] pcpu-alloc: [0] 0 
[    0.000000] Built 1 zonelists, mobility grouping off.  Total pages: 16160
[    0.000000] Kernel command line: console=ttyS0,2000000 loglevel=8 earlyprintk earlycon=sbi root=/dev/mtdblock0 ros
[    0.000000] Dentry cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
[    0.000000] Inode-cache hash table entries: 4096 (order: 3, 32768 bytes, linear)
[    0.000000] Sorting __ex_table...
[    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[    0.000000] Memory: 53200K/65536K available (3960K kernel code, 2846K rwdata, 2048K rodata, 159K init, 288K bss, )
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] rcu: Hierarchical RCU implementation.
[    0.000000] rcu:     RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=1.
[    0.000000]  Tracing variant of Tasks RCU enabled.
[    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
[    0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=1
[    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.000000] riscv-intc: 64 local interrupts mapped
[    0.000000] plic: interrupt-controller@e0000000: mapped 64 interrupts with 1 handlers for 2 contexts.
[    0.000000] random: get_random_bytes called from start_kernel+0x298/0x3a6 with crng_init=0
[    0.000000] riscv_timer_init_dt: Registering clocksource cpuid [0] hartid [0]
[    0.000000] clocksource: riscv_clocksource: mask: 0xffffffffffffffff max_cycles: 0x1d854df40, max_idle_ns: 352636s
[    0.000019] sched_clock: 64 bits at 1000kHz, resolution 1000ns, wraps every 2199023255500ns
[    0.000818] Console: colour dummy device 80x25
[    0.001079] Calibrating delay loop (skipped), value calculated using timer frequency.. 2.00 BogoMIPS (lpj=4000)
[    0.001567] pid_max: default: 32768 minimum: 301
[    0.002186] Mount-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
[    0.002511] Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
[    0.007159] ASID allocator initialised with 65536 entries
[    0.007764] rcu: Hierarchical SRCU implementation.
[    0.009098] smp: Bringing up secondary CPUs ...
[    0.009260] smp: Brought up 1 node, 1 CPU
[    0.010352] devtmpfs: initialized
[    0.013169] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    0.013643] futex hash table entries: 256 (order: 2, 16384 bytes, linear)
[    0.015216] NET: Registered protocol family 16
[    0.016370] DMA: preallocated 128 KiB GFP_KERNEL pool for atomic allocations
[    0.017285] DMA: preallocated 128 KiB GFP_KERNEL|GFP_DMA32 pool for atomic allocations
[    0.018444] i2c-core: driver [dummy] registered
[    0.039289] SCSI subsystem initialized
[    0.041698] clocksource: Switched to clocksource riscv_clocksource
[    0.065232] NET: Registered protocol family 2
[    0.067195] tcp_listen_portaddr_hash hash table entries: 256 (order: 0, 4096 bytes, linear)
[    0.067615] TCP established hash table entries: 512 (order: 0, 4096 bytes, linear)
[    0.068045] TCP bind hash table entries: 512 (order: 1, 8192 bytes, linear)
[    0.068449] TCP: Hash tables configured (established 512 bind 512)
[    0.069161] UDP hash table entries: 256 (order: 1, 8192 bytes, linear)
[    0.069583] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes, linear)
[    0.070332] NET: Registered protocol family 1
[    0.072543] workingset: timestamp_bits=62 max_order=14 bucket_order=0
[    0.087342] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    0.088993] NET: Registered protocol family 38
[    0.089376] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 252)
[    0.089691] io scheduler mq-deadline registered
[    0.089950] io scheduler kyber registered
[    0.095498] 30002000.serial: ttyS0 at MMIO 0x30002000 (irq = 1, base_baud = 2000000) is a BFLB UART
[    0.095964] printk: console [ttyS0] enabled
[    0.095964] printk: console [ttyS0] enabled
[    0.096416] printk: bootconsole [sbi0] disabled
[    0.096416] printk: bootconsole [sbi0] disabled
[    0.126965] brd: module loaded
[    0.152962] loop: module loaded
[    0.154460] physmap-flash 58500000.xip_flash: physmap platform flash device: [mem 0x58500000-0x588fffff]
[    0.155926] 1 fixed-partitions partitions found on MTD device xip-flash.0
[    0.156358] Creating 1 MTD partitions on "xip-flash.0":
[    0.156697] 0x000000000000-0x000000280000 : "rootfs"
[    0.161604] mousedev: PS/2 mouse device common for all mice
[    0.162431] i2c /dev entries driver
[    0.162974] i2c-core: driver [i2c-slave-eeprom] registered
[    0.164325] [perf] T-HEAD C900 PMU probed
[    0.166987] NET: Registered protocol family 10
[    0.169430] Segment Routing with IPv6
[    0.169848] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
[    0.171722] NET: Registered protocol family 17
[    0.172081] Key type dns_resolver registered
[    0.172705] debug_vm_pgtable: [debug_vm_pgtable         ]: Validating architecture page table helpers
[    0.191511] VFS: Mounted root (squashfs filesystem) readonly on device 31:0.
[    0.202659] devtmpfs: mounted
[    0.203563] Freeing unused kernel memory: 156K
[    0.221228] Run /sbin/init as init process
[    0.221561]   with arguments:
[    0.221758]     /sbin/init
[    0.221936]     earlyprintk
[    0.222118]   with environment:
[    0.222320]     HOME=/
[    0.222478]     TERM=linux
********************************
 Exec rcS 
********************************
********mount all********
mount: according to /proc/mounts, porc is already mounted on /proc
mount: according to /proc/mounts, devtmpfs is already mounted on /dev
mount: mounting devpts on /dev/pts failed: No such file or directory
This may take some time ...
mount: mounting sysfs on /sys failed: Device or resource busy
--------Start Local Services--------
********************************
********************************

Linux login: root
login[40]: root login on 'ttyS0'
Processing /etc/profile ... 
Set search library path in /etc/profile
Set user path in /etc/profile
id: unknown ID 0
Welcome to Linux

[@Linux root]#cat /proc/cpuinfo 
processor       : 0
hart            : 0
isa             : rv64imafdcvsu
mmu             : sv39
model name      : T-HEAD C910
freq            : 1.2GHz
icache          : 64kB
dcache          : 64kB
l2cache         : 2MB
tlb             : 1024 4-ways
cache line      : 64Bytes
address sizes   : 40 bits physical, 39 bits virtual
vector version  : 0.7.1

❯ Компилируем и запускаем свой Linux на M1S Dock

Конечно предварительно заготовленные бинарники это хорошо, но давайте попробуем скомпилировать свою версию Linux из исходников:

megalloid@megalloid:~$ git clone https://github.com/sipeed/M1s_BL808_Linux_SDK
megalloid@megalloid:~$ cd M1s_BL808_Linux_SDK
megalloid@megalloid:~/M1s_BL808_Linux_SDK$ mkdir -p toolchain/cmake toolchain/elf_newlib_toolchain toolchain/linux_toolchain

megalloid@megalloid:~/M1s_BL808_Linux_SDK$ curl https://cmake.org/files/v3.19/cmake-3.19.3-Linux-x86_64.tar.gz | tar xz -C toolchain/cmake/ --strip-components=1

megalloid@megalloid:~/M1s_BL808_Linux_SDK$ curl https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1663142243961/Xuantie-900-gcc-elf-newlib-x86_64-V2.6.1-20220906.tar.gz | tar xz -C toolchain/elf_newlib_toolchain/ --strip-components=1

megalloid@megalloid:~/M1s_BL808_Linux_SDK$ curl https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1663142514282/Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.6.1-20220906.tar.gz | tar xz -C toolchain/linux_toolchain/ --strip-components=1

megalloid@megalloid:~/M1s_BL808_Linux_SDK$ ./build.sh opensbi
megalloid@megalloid:~/M1s_BL808_Linux_SDK$ ./build.sh kernel
megalloid@megalloid:~/M1s_BL808_Linux_SDK$ ./build.sh dtb
megalloid@megalloid:~/M1s_BL808_Linux_SDK$ ./build.sh low_load
megalloid@megalloid:~/M1s_BL808_Linux_SDK$ ./build.sh whole_bin

После этого в директории появятся необходимые нам файлы для перепрошивки:

megalloid@megalloid:~/M1s_BL808_Linux_SDK$ tree out/ -L 1
out/
├── fw_jump.bin
├── hw.dtb.5M
├── Image.lz4
├── low_load_bl808_d0.bin
├── low_load_bl808_m0.bin
├── merge_7_5Mbin.py
├── squashfs_test.img
└── whole_img_linux.bin

0 directories, 8 files

Далее таким же образом осуществляем прошивку, как в предыдущей главе. И получаем загруженный образ Linux:

[@Linux root]#uname -a
Linux Linux 5.10.4 #1 SMP Wed Oct 30 01:47:28 MSK 2024 riscv64 GNU/Linux

Выглядит просто. Идём ещё дальше.

❯ Buildroot для M1S Dock

Производитель также предоставляет систему сборки buildroot под данный SoC. Самое интересное, что данный образ будет иметь инструмент для работы с Wi-Fi и SoC можно будет соеденить с внешним миром. Давайте попробуем его собрать.

megalloid@megalloid:~$ git clone --recursive https://github.com/bouffalolab/buildroot_bouffalo.git
megalloid@megalloid:~$ cd buildroot_bouffalo
megalloid@megalloid:~$ export BR_BOUFFALO_OVERLAY_PATH=$(pwd)
megalloid@megalloid:~$ cd buildroot
megalloid@megalloid:~$ make BR2_EXTERNAL=$BR_BOUFFALO_OVERLAY_PATH bl808_nor_flash_defconfig -j4
megalloid@megalloid:~$ make -j4

Вот так просто можно собрать образ buildroot. Прошивается он так же как и Linux образ. В директории buildroot_bouffalo/buildroot/output/images будут находиться все необходимые файлы для перепрошивки:

  • m0_lowload_bl808_m0.bin —  грузится для group0 по адресу 0x58000000.

  • d0_lowload_bl808_d0.bin — грузится для group1 по адресу 0x58000000.

  • bl808_16M_whole_bin.bin — образ в 16Мбайт, который грузится на NOR Flash.

Есть одно изменение. Для прошивки образа на Flash-память необходимо указать адрес без смещения: 

Изучаем RISC-V с платой Sipeed M1S - 23

После этого можете открыть терминал на порту /dev/ttyACM0 и нажать RST. Сначала сработает первый загрузчик:

Изучаем RISC-V с платой Sipeed M1S - 24

После этого будет передано управление в OpenSBI:

Изучаем RISC-V с платой Sipeed M1S - 25

Далее загрузится U-Boot:

Изучаем RISC-V с платой Sipeed M1S - 26

Начнется загрузка Linux:

Изучаем RISC-V с платой Sipeed M1S - 27

Выведем версию ядра текущей сборки Linux:

# uname -a
Linux ox64 6.5.11 #1 Wed Oct 30 03:04:54 MSK 2024 riscv64 GNU/Linux

❯ Использование GPIO в Linux

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

Чтобы включить светодиод, нужно ввести команду:

# devmem 0x200008E4 32 0x00400b42

Чтобы выключить светодиод, нужно ввести другую команду:

# devmem 0x200008E4 32 0x01400b42

Чтобы использовать кнопки, которые расположены на плате, их необходимо сконфигурировать в режим Input с Pull-Up подтяжкой:

# devmem 0x2000091c 32 0x00400B13
# devmem 0x20000920 32 0x00400B13

Чтобы получить значение с кнопок, нужно произвести чтение области памяти:

# x=$(devmem 0x20000ac4); B1=$((1 - ($x>>22)&1)); B2=$((1 - ($x>>23)&1))
# echo $B1
0 или 1
# echo $B2
0 или 1

В составе buildroot-сборки имеется целая пачка утилит для работы с GPIO:

# ls /usr/bin | grep gpio
gpio-event-mon
gpio-hammer
gpio-watch
gpiodetect
gpiofind
gpioget
gpioinfo
gpiomon
gpioset
lsgpio

С ними, я думаю, вы сможете поиграться самостоятельно.

❯ Настройка Wi-Fi

Теперь давайте настроим клиентское подключение к Wi-Fi. Делается это максимально просто. Сначала проверим, что нужный модуль ядра подключен:

# lsmod
Module                  Size  Used by    Tainted: G  
blwnet                 28672  0 

Запускаем сканирование доступных сетей Wi-Fi в диапазоне 2.4 ГГц с поддержкой протоколов 802.11b/g/n:

# blctl wifi_scan

Выведем результаты сканирования:

# blctl wifi_scan_results
BSSID A0:22:4E:C7:0F:31, channel 3, rssi -41, auth WPA2-PSK/WPA3-SAE, cipher AES, SSID Wive-NG-HQ
BSSID E8:28:C1:E3:CE:2F, channel 11, rssi -53, auth WPA2-PSK, cipher AES, SSID move_2.4
BSSID E4:5A:D4:ED:33:50, channel 4, rssi -65, auth WPA2-PSK, cipher AES, SSID ELTX-2.4GHz_WiFi_3350
BSSID CC:9D:A2:D3:F4:80, channel 1, rssi -70, auth WPA2-PSK, cipher AES, SSID ELTX-2.4GHz_WiFi_F480
BSSID CC:9D:A2:D2:1A:D0, channel 2, rssi -73, auth WPA2-PSK, cipher AES, SSID ELTX-2.4GHz_WiFi_1AD0
BSSID CE:9D:A2:D2:1A:D1, channel 13, rssi -73, auth WPA2-PSK, cipher AES, SSID wlan0_Guest1
BSSID CE:9D:A2:D3:F4:81, channel 1, rssi -74, auth WPA2-PSK, cipher AES, SSID wlan0_Guest1
BSSID CE:9D:A2:D1:49:19, channel 8, rssi -78, auth WPA2-PSK, cipher AES, SSID wlan0_Guest1
BSSID CC:9D:A2:D1:49:18, channel 2, rssi -79, auth WPA2-PSK, cipher AES, SSID ELTX-2.4GHz_WiFi_4918
BSSID CE:9D:A2:D1:E6:69, channel 1, rssi -83, auth WPA2-PSK, cipher AES, SSID wlan0_Guest1
BSSID CE:9D:A2:D3:C3:41, channel 1, rssi -85, auth WPA2-PSK, cipher AES, SSID wlan0_Guest1
BSSID 9A:CD:AC:FC:D1:84, channel 6, rssi -87, auth WPA2-PSK/WPA-PSK, cipher TKIP/AES, SSID 98:CD:AC:FC:D1:84
BSSID 4C:BC:E9:88:F8:6C, channel 11, rssi -87, auth WPA2-PSK, cipher AES, SSID AT_401_RAC_056905_WW_f86c

Подключимся к домашней сети:

# blctl connect_ap <SSID> <Password>
[  578.193209] Connected to AP

Получим адрес на интерфейс по DHCP:

# udhcpc -i bleth0
udhcpc: started, v1.36.1
udhcpc: broadcasting discover
udhcpc: broadcasting select for 192.168.1.30, server 192.168.1.1
udhcpc: lease of 192.168.1.30 obtained from 192.168.1.1, lease time 3600
deleting routers
adding dns 192.168.1.1

Попингуем хосты внешнего мира:

# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=60 time=31.364 ms
64 bytes from 8.8.8.8: seq=1 ttl=60 time=27.346 ms
64 bytes from 8.8.8.8: seq=2 ttl=60 time=22.868 ms
^C
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 22.868/27.192/31.364 ms

Выглядит просто. Попробуйте и вы. Можно также использовать плату как Wi-Fi AP, подробнее можете почитать тут.

❯ Заключение

Сложилось устойчивое впечатление, что возможности платы можно раскрывать очень долго. Правда, не хватает готовых примеров для работы с Zigbee и Bluetooth, с NPU в Linux, вывода информации на дисплей из Linux и прочих.

Дальнейшие возможности в реализации потенциала данной отладки зависят лишь от уровня технических компетенций пользователя. Поэтому, если у меня появятся какие-либо новые материалы, например по разбору кода с помощью которого производится распознавание лиц или паттернов с помощью NPU — я с вами любезно поделюсь.

Спасибо за внимание! =)


📚 Читайте также:

Автор: megalloid

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js