やっつけな日常(68) STM32 Nucleo、Mbed OS6 でもバッチリ

Joseph Halfmoon

Arduino Uno R3用の「バニラ味」シールドボードにLCDを搭載。Arduino Uno R3、Uno R4、そしてSTM32 Nucleo F072RBに接続し動作OK。ここまでArduino IDE環境で開発でしたが、今回はArm御本家のRTOS、Mbed OS6環境で動作させてみたいです。クラウドで開発。

※「やっつけな日常」投稿順 Index はこちら

Arm Mbed OS6 と Keil Studio Cloud

Arm Mbed OSは、Arm社がArm Cortex-Mシリーズのコアを搭載した各社マイコンどものために提供してくれている実時間オペレーティングシステムです。Arm社提供なので、個別半導体メーカのコマケー話に関係なく、統一したお作法で「マルチスレッド」のプログラムを開発することが可能です。現在の最新バージョンは OS6 とよばれています。詳しいことは以下へ。

An introduction to Arm Mbed OS 6

さて Arm Mbed OS を開発する一番簡単な方法は、これまたArm社が提供してくれているクラウド開発環境を使用することです。名高いArm純正のツールチェーンを使用した開発環境を「ノーインストール」で即座に使用することが可能っす(無料だが要登録。)この環境を使えば即座にMbed OSを使用できます。

https://studio.keil.arm.com/

勿論、手元のローカル環境でのスタンドアロン開発もサポートされているのですが、インストールの手間やら後々の更新の手間など考えるとクラウド環境はお楽。

ざっと調査してみたところでは以下のようです。

    1. STM32 NucleoシリーズボードのほとんどがMbed OS対応
    2. ルネサス製のマイコン搭載したいくつかのボードはMbed OS対応だが、Arduino Uno R4はターゲットに入っていない

なお、Arduino Uno R4ターゲットのArduino環境では、これまた人気のRTOS、FreeRTOSがヘッダをインクルードするだけで使えます。Uno R4の場合はこちらの方がお楽かな(Uno R4上でのFreeRTOS関係はこちらから。)また、Arduino環境のSTM32のボードパッケージ内にはFreeRTOSは見当たりませんでした。大人の事情?

久しぶりにKeil Studio Cloudにログイン

しばらくKeil Studio Clocdにログインしていなかったですが、問題なく開くことができました。新たにプロジェクトを作りますが、テンプレートに Mbed OS上の blink を指定しておきました。こうすればMbed OS上で動作するLチカのコードが生成されています。

新たに生成したプロジェクトにターゲット・ボードを設定しておきます。こんな感じ。KeilStudioCloud

Mbed OS6を動作させるには、NUCLEO-F072RBのSTM32F072RBマイコンのRAM容量はギリギリ(Flashは余裕)なのですが、今回は収まりました。活用を考えるとも少しRAM容量のある機種が望ましいデス。

なお、Arduino Uno R4はターゲットボードに含まれていないのですが、Arduinoは「レガシー」ということでMbed OSでも配慮されとります。一例をあげるとこんな感じ。LegacyPinNames

Arduino Uno互換のピンソケットを持つボードが多いので、各社マイコン毎異なるチップの端子名など調べずともArduino UnoのSDA、SCLは参照できるっと。

今回は以前にAQM1602用にMbed OS上で作成済のコードをAQM0802用に書き変えて対応しました。まずヘッダファイルが以下に

#ifndef AQM0802_H
#define AQM0802_H

#include "mbed.h"

#define LCD_ADDR    (0x7c)
#define LCD_HLINE   (0x80)
#define LCD_LLINE   (0xC0)
#define LCD_MAXLEN  (8)

class AQM0802 {
private:
    I2C& i2cRef;
    char wdata[2];
    int status;

public:
    AQM0802(I2C& ch);
    int writeCommand(char cmd);
    int writeData(char dat);
    int clear();
    int displaySTR(char Lin, const char* message);
    int init();

};

#endif //AQM0802_H

上記対応の実体関数等が以下に。

#include "AQM0802.h"

AQM0802::AQM0802(I2C& ch) : i2cRef(ch)
{
    wdata[0]=0;
    wdata[1]=0;
}

int AQM0802::writeCommand(char cmd)
{
    status =0;
    wdata[0] = 0x0;
    wdata[1] = cmd;
    status = i2cRef.write(LCD_ADDR, wdata, 2, 0);
    return status;
}

int AQM0802::writeData(char dat)
{
    status =0;
    wdata[0] = 0x40;
    wdata[1] = dat;
    status = i2cRef.write(LCD_ADDR, wdata, 2, 0);
    return status;
}

int AQM0802::clear()
{
    status =0;
    wdata[0] = 0x0;
    wdata[1] = 0x01;
    status = i2cRef.write(LCD_ADDR, wdata, 2, 0);
    return status;
}

int AQM0802::displaySTR(char Lin, const char* message)
{
    int idx = 0;
    status =0;
    wdata[0] = 0x0;
    wdata[1] = Lin;
    status = i2cRef.write(LCD_ADDR, wdata, 2, 0);
    
    wdata[0] = 0x40;
    while ((status == 0) && (idx < LCD_MAXLEN) && (*message != 0)) {
        wdata[1] = *message++;
        status = i2cRef.write(LCD_ADDR, wdata, 2, 0);
        idx++;
    }

    return status;
}

int AQM0802::init()
{
    status =0;
    wdata[0] = 0x0;
    wdata[1] = 0x38;
    thread_sleep_for(40);
    status = i2cRef.write(LCD_ADDR, wdata, 2, 0);
    thread_sleep_for(2);
    wdata[1] = 0x39;
    status = i2cRef.write(LCD_ADDR, wdata, 2, 0);
    thread_sleep_for(2);
    wdata[1] = 0x14;
    status = i2cRef.write(LCD_ADDR, wdata, 2, 0);
    thread_sleep_for(2);
    wdata[1] = 0x70;
    status = i2cRef.write(LCD_ADDR, wdata, 2, 0);
    thread_sleep_for(2);
    wdata[1] = 0x56;
    status = i2cRef.write(LCD_ADDR, wdata, 2, 0);
    thread_sleep_for(2);
    wdata[1] = 0x6c;
    status = i2cRef.write(LCD_ADDR, wdata, 2, 0);
    thread_sleep_for(2);
    wdata[1] = 0x38;
    status = i2cRef.write(LCD_ADDR, wdata, 2, 0);
    thread_sleep_for(2);
    wdata[1] = 0x01;
    status = i2cRef.write(LCD_ADDR, wdata, 2, 0);
    thread_sleep_for(2);
    wdata[1] = 0x0c;
    status = i2cRef.write(LCD_ADDR, wdata, 2, 0);
    thread_sleep_for(2);
    wdata[1] = 0x01;
    status = i2cRef.write(LCD_ADDR, wdata, 2, 0);
    
    return status;
}

そして肝心の main はこんな感じです。mainOnMbedOS

ビルドして、ボードへ書き込み(ボードをUSB接続して、クラウド環境に「接続」しておけばクラウド環境からの書き込みOK)したところが以下に。HelloMbedOS6

Mbed OS6でもお楽。

やっつけな日常(67) STM32 Nucleo、Arduino用LCDシールドでバッチリ へ戻る

やっつけな日常(69) STM32 Nucleo、LCDシールドはF401REに落ち着いた? へ進む