LoginSignup
4
3

More than 3 years have passed since last update.

micro:bitで本格的な組込みソフトウェア開発環境を構築し、サンプルプログラムをVSCodeからデバッグできるようにする

Posted at

micro:bitで本格的な組込みソフトウェア開発

micro:bitは、様々な方法で、組込みソフトウェア開発が可能です。
本記事では、リアルタイムオペレーティングシステムの実装であるApache Mynewt を使って、本格的な組込みソフトウェア開発環境を構築し、VSCodeでサンプルプログラムをデバッグ実行します。

Windows 10 (64bit版) 上での開発環境構築

次のドキュメントを参考にして、Windows 10 (64bit版) 上に開発環境を構築します。

Installing Newt on Windows
https://mynewt.apache.org/latest/newt/install/newt_windows.html
Installing the Cross Tools for ARM
https://mynewt.apache.org/latest/get_started/native_install/cross_tools.html

本記事では、具体的なダウンロード元やインストールフォルダを示していますので、将来、バージョンアップなどにより、動作しなくなる可能性があります(2020/07/04現在)。

MSYS2/MinGW のインストール

https://www.msys2.org/ からMSYS2のインストーラーをダウンロードし、インストールします。
msys2-x86_64-20200629.exe

MSYS2を最新化する為、スタートメニューからMSYS2 MSYSを起動し、次のコマンドを実行します。

pacman -Syuu

さらに、次のコマンドを実行し、tarツールをインストールします。

pacman -Su tar

Windows 10 のシステム環境変数で、変数名MSYS2_PATH_TYPEの変数値inheritを追加します。
image.png

さらに、Windows 10 のシステム環境変数の変数名Pathの先頭に変数値C:\msys64\usr\binを追加します。
C:\msys64\はMSYS2がデフォルトでインストールされるフォルダーです。

Mynewtのドキュメントやチュートリアルで指定されたコマンドを実行するには、MinGWターミナルを起動する必要がありますが、その際、スタートメニューからMSYS2 Mingw 64-bitを起動します。

Git のインストール

https://gitforwindows.org/ からgitのインストーラーをダウンロードし、インストールします。
Git-2.27.0-64-bit.exe

newt のインストール(バイナリ版 1.8.0)

バイナリ版のnewtをインストールします。
まず、MinGWターミナルを起動し、次のコマンドで、バイナリ版のnewtをダウンロードし、展開後、/usr/binへ移動します。

wget -P /tmp https://ftp.riken.jp/net/apache/mynewt/apache-mynewt-1.8.0/apache-mynewt-newt-bin-windows-1.8.0.tgz
tar -xzf /tmp/apache-mynewt-newt-bin-windows-1.8.0.tgz -C /tmp
mv /tmp/apache-mynewt-newt-bin-windows-1.8.0/newt.exe /usr/bin

次のコマンドで、newtのバージョンを確認できます。

newt version

ARM Toolchain のインストール

gcc-arm-none-eabi-7-2018-q2-update-win32.exeをダウンロードし、インストールします。
インストールの最後で、Add path to environment variableをチェックしてから、「完了」ボタンを押下してください。

MinGWターミナルを起動し、次のコマンドで、それぞれのツールのインストール先を確認することができます。

which arm-none-eabi-gcc
which arm-none-eabi-gdb

※ インストールするバージョンに関する注意事項
gcc-arm-none-eabi-7-2018-q2-update-win32.exeをダウンロードし、インストールしてください。

GNU Arm Embedded Toolchain: 8-2018-q4-major December 20, 2018 (gcc-arm-none-eabi-8-2018-q4-major-win32.exe) では開発中に次のエラーでビルドに失敗します。

When extracting code from .elf, objcopy reports "64-bit address 0x4b4fa300000000 out of range for Intel Hex file".

不具合情報:https://bugs.launchpad.net/gcc-arm-embedded/+bug/1810274

openocd のインストール

openocd-0.10.0.zipをダウンロードします。
C:\openocd-0.10.0\フォルダへ展開します。
C:\openocd-0.10.0\bin をシステム環境変数のPathの先頭に追加します。

SEGGER J-Link デバッガ のインストール

「J-Link Software and Documentation pack for Windows」をダウンロードし、インストールします。
JLink_Windows_V680d.exe

micro:bitのファームウェア最新化(DAPLink)

次の手順で、micro:bitのフォームウェアを最新化します。
https://microbit.org/get-started/user-guide/firmware/

  1. 0253_kl26z_microbit_0x8000.hexファイルをダウンロードします。
  2. micro:bit本体のリセットスイッチを押しながら、USB通信ケーブルで、パソコンに接続します。
  3. micro:bitのストレージをMAINTENANCEドライブとしてパソコンが認識していることを確認します。
  4. ダウンロードしたHEXファイルをMAINTENANCEドライブへコピーします。

サンプルプログラム

開発環境が構築できたかどうかを確認する為、Lチカのサンプルプログラムを作成し、micro:bit本体で実行してみます。
https://mynewt.apache.org/latest/tutorials/blinky/nRF52.html

プロジェクトの作成とリポジトリの取得

MinGWターミナルを起動し、次の一連のコマンドを実行し、プロジェクトを作成(newt new myproj)とリポジトリの取得(newt upgrade)を行います。

mkdir ~/dev
cd ~/dev

newt new myproj

cd myproj
newt upgrade

ターゲットの作成

次のコマンドで、ブートプログラム(ubit_boot)とLチカ本体(ubit_blinky)のターゲットを作成し、設定します。

newt target create ubit_boot
newt target set ubit_boot app=@mcuboot/boot/mynewt
newt target set ubit_boot bsp=@apache-mynewt-core/hw/bsp/bbc_microbit
newt target set ubit_boot build_profile=optimized

newt target create ubit_blinky
newt target set ubit_blinky app=apps/blinky
newt target set ubit_blinky bsp=@apache-mynewt-core/hw/bsp/bbc_microbit
newt target set ubit_blinky build_profile=debug

newt target show

サンプルソースコードの差し替え(micro:bit LED)

Lチカ本体のソースコードは、~/dev/myproj/apps/blinky/src/main.cです。
Windows10からは、C:\msys64\home\<アカウント名>\dev\myproj\apps\blinky\src\main.cとしてアクセスできます(<アカウント名>はログオンユーザーアカウント)。
micro:bitのLEDマトリックスは、少し特殊な回路となっていますので、LEDマトリックスを点滅させるため、メモ帳などのテキストディタでmain.cを開き、次のサンプルソースコードで上書き保存します。

main.c
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include <assert.h>
#include <string.h>

#include "sysinit/sysinit.h"
#include "os/os.h"
#include "bsp/bsp.h"
#include "hal/hal_gpio.h"

// LED pin Column
#define PIN_LED_COL1  4
#define PIN_LED_COL2  5
#define PIN_LED_COL3  6
#define PIN_LED_COL4  7
#define PIN_LED_COL5  8
#define PIN_LED_COL6  9
#define PIN_LED_COL7  10
#define PIN_LED_COL8  11
#define PIN_LED_COL9  12
// LED pin Row for LED toggling
#define PIN_LED_ROW_0  13
#define PIN_LED_ROW_1  14
#define PIN_LED_ROW_2  15

static volatile int g_task1_loops;

/**
 * main
 *
 * The main task for the project. This function initializes packages,
 * and then blinks the BSP LED in a loop.
 *
 * @return int NOTE: this function should never return!
 */
int
main(int argc, char **argv)
{
    int rc;

    sysinit();

    // because the LEDs are multiplexed, we must ground the opposite side of the LED
    hal_gpio_init_out(PIN_LED_COL1, 0);
    hal_gpio_init_out(PIN_LED_COL2, 0);
    hal_gpio_init_out(PIN_LED_COL3, 0);
    hal_gpio_init_out(PIN_LED_COL4, 0);
    hal_gpio_init_out(PIN_LED_COL5, 0);
    hal_gpio_init_out(PIN_LED_COL6, 0);
    hal_gpio_init_out(PIN_LED_COL7, 0);
    hal_gpio_init_out(PIN_LED_COL8, 0);
    hal_gpio_init_out(PIN_LED_COL9, 0);

    // set LED pin to output mode
    hal_gpio_init_out(PIN_LED_ROW_0, 1);
    hal_gpio_init_out(PIN_LED_ROW_1, 1);
    hal_gpio_init_out(PIN_LED_ROW_2, 1);

    while (1) {
        ++g_task1_loops;

        /* Wait one second */
        os_time_delay(OS_TICKS_PER_SEC);

        /* Toggle the LED */
        hal_gpio_toggle(PIN_LED_ROW_0);
        hal_gpio_toggle(PIN_LED_ROW_1);
        hal_gpio_toggle(PIN_LED_ROW_2);
    }
    assert(0);

    return rc;
}

ターゲットのビルドとアプリケーションイメージの生成
次のコマンドで、作成した2つのターゲットをビルドし、アプリケーションイメージを生成します。

newt build ubit_boot
newt build ubit_blinky
newt create-image ubit_blinky 1.0.0

micro:bit本体へのロード

次のコマンドで、micro:bit本体へ、実行に必要なイメージをロードします。

newt load ubit_boot
newt load ubit_blinky

image.png

VSCodeを用いた開発環境の構築

次のドキュメントを参考にして、Visual Studio Code (VSCode)を用いたに開発環境を構築します。
https://mynewt.apache.org/latest/misc/ide.html

VSCodeのインストール

https://code.visualstudio.com/Download のページから、Windows版のVSCodeをダウンロードし、インストールします。

VSCode拡張機能のインストール

VSCodeを起動し、次の2つの拡張機能をインストールします。

  1. C/C++ 拡張機能(Microsoft)
  2. Native Debug 拡張機能(webfreak)

C/C++ 拡張機能 のインストール

  1. Ctrl-Pを押下し、VSCodeの検索ボックスを開きます。
  2. 検索ボックスにext install cpptoolsと入力し、Enterキーを押下します。
  3. リストのトップに拡張機能のC/C++が表示されますので、インストールボタンでインストールします。

Native Debugger 拡張機能 のインストール

  1. Ctrl-Pを押下し、VSCodeの検索ボックスを開きます。
  2. 検索ボックスにext install webfreak.debugと入力し、Enterキーを押下します。
  3. リストのトップに拡張機能のNative Debugが表示されますので、インストールボタンでインストールします。

VSCode上でのワークスペースとタスクの関連付け

VSCodeには、次のような概念があります。

  1. ワークスペース - 開いているフォルダがワークスペースです。
  2. タスク - タスクを使用すると、プロジェクトのビルドやデバッグに使用される外部ツールとの操作をVisual Studio Codeに統合できます。

ワークスペースの関連付け

Lチカのサンプルプログラム(プロジェクト)をVSCodeのワークスペースとして関連付けます。
エクスプローラーを開き、~/dev/myproj/であるC:\msys64\home\<アカウント名>\dev\myprojフォルダを開きます。ファイル名やフォルダ名以外の空白の部分で、右クリックし、`Code で開く'で、VSCodeで開きます。

ワークスペース内でのタスクの定義

myprojのワークスペースを開いた状態で、開発に必要なタスクを定義します。

tasks.jsonの追加

次の手順で、tasks.jsonファイルを追加します。
1. Ctrl-Shift-Pキーを押下し、表示された検索ボックスで、tasksと入力すると候補が絞り込まれますので、タスク: タスクの構成 / Tasks:Configure Taskを選択します。
1. テンプレートからtasks.jsonを作成をクリックし、リスト末尾のOthersをクリックします。
1. tasks.jsonファイルが追加され、エディタに表示されます。

task.jsonの定義

tasks.jsonの内容を次の定義内容で上書き保存します。

tasks.json
{
    "version": "0.1.0",
    "command": "newt",
    "echoCommand": true,
    "isShellCommand": true,

    "tasks":[
        {
            "taskName": "build_ubit_boot",
            "args": ["build", "ubit_boot"],
            "suppressTaskName": true
        },
        {
            "taskName": "build_ubit_blinky",
            "args": ["build", "ubit_blinky"],
            "isBuildCommand": true,
            "suppressTaskName": true
        },
        {
            "taskName": "create_ubit_blinky",
            "args": ["create-image", "ubit_blinky", "1.0.0"],
            "suppressTaskName":true
        },
        {
            "taskName": "load_ubit_boot",
            "args": ["load", "ubit_boot"],
            "suppressTaskName":true
        },
        {
            "taskName": "load_ubit_blinky",
            "args": ["load", "ubit_blinky"],
            "suppressTaskName":true
        },
        {
            "taskName": "debug_ubit_blinky",
            "args": ["debug", "ubit_blinky", "-n"],
            "suppressTaskName": true
        },
    ]
}

タスクの実行方法

例えば、build_ubit_blinkyタスクを実行するには、次の手順で操作します(他のタスクも同様)。

  1. Ctrl-Shift-Pキーを押下し、検索ボックスを開きます。
  2. tasksと入力すると、候補が絞り込まれますので、タスク: タスクの実行 / Tasks: Run Taskをクリックします。
  3. build_ubit_blinkyが実行するタスクの選択候補に表示されますので、それをクリックします。
  4. 下段のペインで、`newt build ubit_blinky'が実行されます。

また、タスクに定義されていなくてもnewtコマンドを実行することができます。日本語キーボードの場合、Ctrl-@(バッククォート)キーを押下すると下段のペインにターミナルが表示・非表示されますので、そこで直接、newt version等のコマンドを入力し、実行することができます。
尚、build_ubit_blinkyタスクに関しては、その定義でisBuildCommandtrueになっていますので、Ctrl-Shift-Bキーで、実行できます。

アプリケーションのデバッグ

micro:bit本体とUSB通信ケーブルで接続して、VSCodeからアプリケーションをデバッグすることができます。まずは、デバッグ環境の構成を定義します。

デバッグ環境構成の定義(GDB)

VScodeのメニューから[実行(Debug)]-[構成を開く(Open Configuration)]を選択し、環境の選択の中からGDBを選択します。launch.jsonファイルが追加され、テキストエディタに表示されますので、次の内容で上書き保存します。

launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "gdb_ubit_blinky",
            "type": "gdb",
            "request": "attach",
            "executable": "${workspaceRoot}\\bin\\targets\\ubit_blinky\\app\\apps\\blinky\\blinky.elf",
            "target": ":3333",
            "cwd": "${workspaceRoot}",
            "gdbpath": "C:\\Program Files (x86)\\GNU Tools ARM Embedded\\7 2018-q2-update\\bin\\arm-none-eabi-gdb.exe",
            "remote": true

        }
    ]
}

サンプルプログラムのデバッグ

サンプルプログラムのLチカをステップ実行でデバッグしてみます。

ブレークポイントの追加

main.cを開き、行番号の左で、ブレークポイントを追加・削除できますので、例えば、図の行77に、ブレークポイントを追加します(赤い点)。
image.png

GDBサーバーの開始

次の手順で、GDB サーバーを開始します。

  1. Ctrl-Shift-Pキーを押下し、検索ボックスを開きます。
  2. tasksと入力すると、候補が絞り込まれますので、タスク: タスクの実行 / Tasks: Run Taskをクリックします。
  3. debug_ubit_blinkyが実行するタスクの選択候補に表示されますので、それをクリックします。
  4. 下段のペインで、`newt debug ubit_blinky -n'が実行され、micro:bit本体裏の通信LED(オレンジ色)が激しく点滅します。

image.png

デバッグ実行の開始

次の手順で、デバッグ実行を開始します。

  1. Ctrl-Shift-Dキーを押下し、左縦のアクティビティバーから「実行(Debug)」アイコンを選択し、左側のペインを切り替えます。
  2. 「実行(Debug)」ドロップダウンリストで、gdb_ubit_blinkyを選択します。
  3. 「実行(Debug)」横の緑色の「デバッグの開始」ボタンをクリックするとGDBセッションが開始されます。
  4. すぐさま、デバッグが開始され、ブレークポイントで、一時停止しますので、変数g_task1_loopsにカーソルを合わせると、現在値が表示されます。
  5. 「続行(F5)」で、処理が続行され、次のブレークポイントで一時停止します。

image.png

まとめ

micro:bitで本格的な組込みソフトウェア開発ができることを確認しました。

  • リアルタイムオペレーティングシステムの実装であるApache Mynewt を使いました。
  • C/C++による本格的な組込みソフトウェア開発環境を構築しました。
  • サンプルプログラムのLチカをmicro:bit本体で動作させました。
  • VSCodeでサンプルプログラムをデバッグ実行し、ステップ実行できることを確認しました。
4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3