{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 41-M5Stamp-C3Uをデバッグする(暫定方法)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## M5Stamp-C3Uの魅力\n",
"ESP(240MHz, Dual Core)に比べるとオープンソースのRisc-Vの(160MHz, Single Core)と性能は少し低いですが、\n",
"待望のWiFi, Bluetooth搭載Risc-V(ESP32-C3)ということで、リリース情報を聞いてすぐに購入しました。\n",
"\n",
"さらに、M5Stamp-C3UはビルトインのUSB-CDCとJtagデバッガーが使えるので、購入してすぐにデバッガーが使えるます。\n",
"\n",
"\n",
"\n",
"## なぜデバッガーが必要なのか\n",
"新しいCPUのプラットフォームでの開発は、プラットフォームの情報(ドキュメント)も少なく、ソフトの障害も含まれているため、\n",
"アプリのデバッグは大変になります。\n",
"\n",
"そんな時こそ、デバッガーでアプリの動作を確認しながら、障害に対処するのが効率的です。\n",
"\n",
"## PlatformIOを使って簡単環境セットアップ\n",
"新しいボードで一番大変な作業は、開発環境の構築ですね。PlatformIOを使うことで面倒な環境開発がコマンド一発で完了します。\n",
"\n",
"ここからの開発はVisual Studio Code(以下VScodeと記す)を使用します。\n",
"最初に、新しくプロジェクトを作成するディレクトリをVScodeの「Open Folder...」で選択します。\n",
"次にVScodeのTerminalメニューからNew Terminalを選択すると画面下にターミナルウィンドウが開きます。\n",
"\n",
"ここでは、「ESPC3UTest」ディレクトリを作成し、プロジェクトを作成することにします。最初に「ESP32C3」をキーワードに既存の登録ボードを検索します。\n",
"\n",
"```bash\n",
"$ mkdir ESPC3UTest\n",
"$ cd ESPC3UTest\n",
"$ ~/.platformio/penv/bin/pio boards \"ESP32C3\"\n",
"\n",
"Platform: espressif32\n",
"======================================================================================================\n",
"ID MCU Frequency Flash RAM Name\n",
"------------------ ------- ----------- ------- ----- ----------------------------\n",
"esp32-c3-devkitm-1 ESP32C3 160MHz 4MB 320KB Espressif ESP32-C3-DevKitM-1\n",
"esp32-c3-devkitm-1 ESP32C3 160MHz 4MB 320KB Espressif ESP32-C3-DevKitM-1\n",
"```\n",
"\n",
"次に、Espressif ESP32-C3-DevKitM-1のID「esp32-c3-devkitm-1」を使ってプロジェクトを作成します。\n",
"\n",
"```bash\n",
"$ ~/.platformio/penv/bin/pio init --board esp32-c3-devkitm-1\n",
"```\n",
"\n",
"新しいプロジェクトが作成できたので、VScodeの「Open Folder...」で「ESPC3UTest」を選択します。\n",
"\n",
"platform.iniを見ると以下のようになっていると思います(最初のコメントは省略)。\n",
"```\n",
"[env:esp32-c3-devkitm-1]\n",
"platform = espressif32\n",
"board = esp32-c3-devkitm-1\n",
"framework = espidf\n",
"```\n",
"\n",
"私はespidfのフレームワークは馴染みがないので、Arduinoフレームワークを使えるように以下のように設定を変更します。\n",
"このフレームワークは暫定なので、PlatformIOの正式ページからは検索できません。\n",
"\n",
"```\n",
"[env:esp32-c3-devkitm-1]\n",
"board = esp32-c3-devkitm-1\n",
"framework = arduino\n",
"platform = https://github.com/Jason2866/platform-espressif32.git\n",
"platform_packages = framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git\n",
"\ttasmota/toolchain-riscv32\n",
"```\n",
"\n",
"### Lチカ\n",
"M5Stamp-C3Uには、LEDは搭載されておらず、代わりにNeoPixelが1個ついています。\n",
"\n",
"以下のサイトからNeoPixcelを使ったスケッチを参照しました。\n",
"- https://github.com/leCandas/M5Stamp-C3\n",
"\n",
"src/main.cをmain.cppに書き換えて\n",
"\n",
"```C++\n",
"#include \n",
"#include \n",
"\n",
"#define LED 2\n",
"#define NUMPIXELS 1\n",
"\n",
"int high = 255;\n",
"int low = 0;\n",
"Adafruit_NeoPixel pixels(NUMPIXELS, LED, NEO_GRB + NEO_KHZ800);\n",
"\n",
"void setup() {\n",
" pixels.begin();\n",
"}\n",
"\n",
"void loop() {\n",
" // オン\n",
" pixels.setPixelColor(0, pixels.Color(high, low, low)); \n",
" pixels.show();\n",
" delay(1000);\n",
" // オフ\n",
" pixels.setPixelColor(0, pixels.Color(low, low, low)); \n",
" pixels.show();\n",
" delay(1000);\n",
"}\n",
"```\n",
"\n",
"NeoPixelを使用するために、lib_deps項をplatformio.iniに追加します。\n",
"\n",
"```\n",
"lib_deps = adafruit/Adafruit NeoPixel@^1.10.3\n",
"```\n",
"\n",
"### ビルドと書き込み\n",
"最初に中央のボタンを押しながら、M5Stamp C3UにUSBケーブルを接続します。\n",
"\n",
"次にVScodeのViewメニューからCommand Palette...を選択し、「PlatformIO: Upload」を選択すると、\n",
"スケッチのビルドと書き込みを自動的にしてくれます。\n",
"\n",
"書き込みに成功したらM5Stamp C3Uのリセットボタンを押してください。中央ボタンの裏のNeoPixelが赤く点滅します。\n",
"\n",
"### ピン配置\n",
"M5Stamp C3Uのピン配置をM5Stackのサイトから引用します。\n",
"\n",
"\n",
"\n",
"SPI, I2Cのピン設定は、以下のURLのソースから取得しました。\n",
"- https://github.com/espressif/arduino-esp32/blob/master/variants/esp32c3/pins_arduino.h#L20-L23\n",
"\n",
"整理すると以下のようになります。\n",
"| IO番号 | ピン番号 | 機能 |\n",
"|---|---|---|\n",
"| GPIO0 | G0 | A0 |\n",
"| GPIO1 | G1 | A1 |\n",
"| GPIO2 | - | NeoPixel |\n",
"| GPIO3 | G3 | A3 |\n",
"| GPIO4 | G4 | A4, SCK |\n",
"| GPIO5 | G5 | A5, MISO |\n",
"| GPIO6 | G6 | MOSI |\n",
"| GPIO7 | G7 | SS |\n",
"| GPIO8 | G8 | SDA |\n",
"| GPIO9 | G9 | SCL, Button |\n",
"| GPIO10 | G10 | |\n",
"| GPIO18 | G18 | D- |\n",
"| GPIO19 | G19 | D+ |\n",
"| GPIO20 | G20 | Rx0 |\n",
"| GPIO21 | G21 | Tx0 |\n",
"| CHIP_EN | EN | |\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ビルトイン・デバッガーを使う\n",
"最初に、今回のデバッガーの実装は現状で何とかデバッガーを動かそうとした暫定処置だということをご理解ください。\n",
"\n",
"デバッガーを使用する上での1番の障害は、gdbのload機能が正常に機能しないことです。\n",
"そのため、プログラムを修正した後アップロードを実行してから、デバッグを開始しなくてはなりません。\n",
"\n",
"### OpenOCDの設定\n",
"esp32-c3-devkitm-1ボードのデバッガーとしてUSB-JTAG(ビルトイン・デバッガー)はまだサポートしていないので、\n",
"PlatformIOのPio Debugは使えません。\n",
"\n",
"そこで、カスタム・デバッグサーバとしてOpenOCDを使用します。platformio.iniに以下の3項目を追加します。\n",
"\n",
"- build_flags: ビルド時にデバッグ情報を付加するように-gオプションを追加\n",
"- debug_tool: customでカスタム設定(debug_serverでデバッグサーバを使用)を宣言\n",
"- debug_server: デバッグサーバとして、openocdと起動オプションを指定\n",
"\n",
"\n",
"```\n",
"build_flags = -g\n",
"debug_tool = custom\n",
"debug_server =\n",
" $PLATFORMIO_CORE_DIR/packages/tool-openocd-esp32/bin/openocd\n",
" -f openocd.cfg\n",
"```\n",
"\n",
"次にopneocd.cfgを以下のように作成します。\n",
"\n",
"```\n",
"# インタフェース設定\n",
"# esp32 USB biltin\n",
"set _RTOS auto\n",
"source [find interface/esp_usb_jtag.cfg]\n",
"\n",
"# CPUの設定\n",
"source [find target/esp32c3.cfg]\n",
"adapter_khz 5000\n",
"\n",
"# デバッガの初期化\n",
"gdb_target_description enable\n",
"init\n",
"reset init\n",
"```\n",
"\n",
"さらに、ESP32C3のrevisionミスマッチの発生を回避するため、gdbの開始時に以下のコマンドを実行するよう.initdbファイルを作成し、以下の設定を追加します。\n",
"- https://github.com/espressif/openocd-esp32/issues/144\n",
"\n",
"\n",
"```\n",
"set arch riscv:rv32\n",
"set mem inaccessible-by-default off\n",
"```\n",
"\n",
"### デバッガーの実行\n",
"デバッグの実行時には、デバッグ情報付きの実行形式を書き込んだ後にリセットボタンを押します。\n",
"続いてVScodeのデバッグでは、「Pio debug(without uploading)」を選択し、デバッガーを起動します。\n",
"\n",
"最初のブレークポイントとして、setup関数の最初の行にブレークポイントをセットしてください。\n",
"\n",
"デバッガー正常に起動したら、以下のようにsetup関数の先頭で実行が止まり、デバッグ画面が表示されます。\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Windows固有の設定\n",
"Windowsの場合、gitとZadigのインストールが必要です。以下のサイトからダウンロードしてインストールしてください。\n",
"git\n",
"- https://gitforwindows.org/\n",
"Zadig\n",
"- https://zadig.akeo.ie/\n",
"\n",
"Zadigを使って、jtagのドライバーをインストールします。\n",
"- optionsメニューからList All Devicesを選択\n",
"- Driverの右側をlibusb-win32(v1.2.6.0)を選択し、Replace Driverボタンを押下します。\n",
"\n",
"\n",
"\n",
"openocdを以下のサイトからダウンロードして、ユーザディレクトリの.platformio/packagesにopenocd-esp32をコピーし、「tool-openocd-esp32」に名前を変更します。\n",
"https://github.com/espressif/openocd-esp32/releases/download/v0.11.0-esp32-20211220/openocd-esp32-win32-0.11.0-esp32-20211220.zip\n",
"\n",
"\n",
"gdbが.initdbを見つけることができるように、PlatformIOフォルダは、Cドライブ直下に置きました。\n",
"\n",
"setup関数で停止するまでのDEBUG CONSOLEのログを追記しておきます(Macでのログ)。\n",
"```\n",
"Info : esp_usb_jtag: Device found. Base speed 40000KHz, div range 1 to 255\n",
"Info : clock speed 5000 kHz\n",
"Info : JTAG tap: esp32c3.cpu tap/device found: 0x00005c25 (mfg: 0x612 (Espressif Systems), part: 0x0005, ver: 0x0)\n",
"Info : datacount=2 progbufsize=16\n",
"Info : Examined RISC-V core; found 1 harts\n",
"Info : hart 0: XLEN=32, misa=0x40101104\n",
"Info : JTAG tap: esp32c3.cpu tap/device found: 0x00005c25 (mfg: 0x612 (Espressif Systems), part: 0x0005, ver: 0x0)\n",
"adapter speed: 5000 kHz\n",
"\n",
"Info : tcl server disabled\n",
"Info : telnet server disabled\n",
"Info : accepting 'gdb' connection from pipe\n",
"Warn : No symbols for FreeRTOS!\n",
"Info : Flash mapping 0: 0x10020 -> 0x3c020020, 35 KB\n",
"Info : Flash mapping 1: 0x20020 -> 0x42000020, 103 KB\n",
"Info : Auto-detected flash bank 'esp32c3.flash' size 4096 KB\n",
"Info : Using flash bank 'esp32c3.flash' size 4096 KB\n",
"Info : Flash mapping 0: 0x10020 -> 0x3c020020, 35 KB\n",
"Info : Flash mapping 1: 0x20020 -> 0x42000020, 103 KB\n",
"Info : Using flash bank 'esp32c3.irom' size 104 KB\n",
"Info : Flash mapping 0: 0x10020 -> 0x3c020020, 35 KB\n",
"Info : Flash mapping 1: 0x20020 -> 0x42000020, 103 KB\n",
"Info : Using flash bank 'esp32c3.drom' size 36 KB\n",
"0x40000000 in ?? ()\n",
"Info : JTAG tap: esp32c3.cpu tap/device found: 0x00005c25 (mfg: 0x612 (Espressif Systems), part: 0x0005, ver: 0x0)\n",
"JTAG tap: esp32c3.cpu tap/device found: 0x00005c25 (mfg: 0x612 (Espressif Systems), part: 0x0005, ver: 0x0)\n",
"Function \"main\" not defined.\n",
"Make breakpoint pending on future shared library load? (y or [n]) [answered N; input not from terminal]\n",
"PlatformIO: Initialization completed\n",
"PlatformIO: Resume the execution to `debug_init_break = tbreak main`\n",
"PlatformIO: More configuration options -> https://bit.ly/pio-debug\n",
"Note: automatically using hardware breakpoints for read-only addresses.\n",
"Info : [0] Found 8 triggers\n",
"[New Thread 1070137204]\n",
"[New Thread 1070132124]\n",
"[New Thread 1070136860]\n",
"[Switching to Thread 1070149344]\n",
"\n",
"Thread 1 hit Breakpoint 1, setup () at src/main.cpp:12\n",
"12\t pixels.begin();\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
}
],
"metadata": {
"language_info": {
"name": "python"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}