RTOS:シングルスレッドによるLチカ
USBにMSP432を接続した状態でCCSを起動し、Resource Exploerを立ち上げる
ボードが検出される(されない場合は手動で選択)のでUSE MY BOARDをクリックし、NEXTを押す
確認画面が表示されるが、OKを押し読み込む。
XDCtoolsのバージョンが違う等警告が出るかもしれないが、問題ないのでOK。
プロジェクトの構成
main_tirtos.c : main関数が含まれている。ここでスレッドを立ている。
コードの解説
#include <stdint.h>
一定の大きさを持つ整数型を定義してあるヘッダファイル
unit8_t とか長さを指定して整数定義する場合にインクルードする。マイコンのソースを書くならおまじない的においておく。
/* POSIX Header files */
#include <pthread.h>
汎用的なスレッド表記を使うために、pthreadを読み込む。これは以前に標準的なC言語として解説しているのでそちらを参照されたい。
/* RTOS header files */
#include <ti/sysbios/BIOS.h>
#include <ti/drivers/Board.h>
この2行は、TI-RTOSで記載する場合は記述を行う。
extern void *mainThread(void *arg0);
後で解説する別のファイルで定義されている関数の宣言。externは同じファイル内で定義されていないのでつける。スレッドをいくつも使う場合はここが増えていく事になる。
/* Stack size in bytes */
#define THREADSTACKSIZE 1024
定数を宣言しているだけ、C言語の標準的な表記なので他に任せる。
The following (weak) function definition is needed in applications that do *not* use the NDK TCP/IP stack:
void __attribute__((weak)) NDK_hookInit(int32_t id) {}
日本語では、 ”NDKのTCP/IPスタックを使用しないアプリケーションでは、以下の(弱い)関数定義が必要です。”
NDKってそもそもなんだ?というのは現時点では不明(はじめて触る人にわかるはずがない)のでここは、そのままにしておく。
main関数の部分
Board_init();はRTOSを使うならメインで最初に呼び出す。
それ以降はpthreadの標準的な書き方になっている。これは以前C言語のptheadについて解説しているのでそこを理解していれば難しくない。
pthread_attr_init(&attrs);
で属性パラメータを初期化し、属性を設定する。
ご丁寧に、戻り値retcでエラーが発生するとwhile (1) {}なので事実上の停止するよに記載している。
if (retc != 0) {
/* failed to set attributes */
while (1) {}
}
プロの方から見ればエラー処理はそりゃ大事だが
retc = pthread_attr_setschedparam(&attrs, &priParam);
という所を
pthread_attr_setschedparam(&attrs, &priParam);
とだけ書いて、 if (retc != 0) {・・・}の部分のエラー処理をないコードを書いても動作する。
retc = pthread_create(&thread, &attrs, mainThread, NULL);
の部分でcreateしmainThreadが生成スレッドとして呼び出す関数名を入れる事になる。
BIOS_start();
はC言語のjoinと同じ。joinはそのかわり書かない。ここで上でcreatしたスレッドが永遠と実行される事になる。
続いて、empty.cの方を解説する。
/* For usleep() */
#include <unistd.h>
C言語で処理を止める、<unistd.h>ライブラリーのsleep関数を使っているので、インクルードする。
#include <stdint.h>は上で解説済み。
#include <stddef.h>は、size_tとかNULLとか使う時にインクルードする。この例題では本来は使っていないのでいらないはず。コメントアウトしてもコンパイルはとおる。
/* Driver Header files */
#include <ti/drivers/GPIO.h>
// #include <ti/drivers/I2C.h>
// #include <ti/drivers/SPI.h>
// #include <ti/drivers/UART.h>
// #include <ti/drivers/Watchdog.h>
と以下で使う機能に応じて、ヘッダーファイルを読み込む。よく使うI2CとかSPI、UARTなんかはコメントアウトして用意してくれている。例えばADC使うとなれば自分で足す事になる。GPIOは使うので、コメントアウトははずしてある。
スレッドの関数の中を見ていく。
void *mainThread(void *arg0)
GPIO_init();
は初期化する部分で、SPIを初期化するならSPI_init();という感じでスレッド内で利用するペリフェラルの初期化をする。複数のペリフェラルを使うなら、RTOSを使う以上は、そえぞれのペリフェラル_init()を並べる事になる。
GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
GPIO_setConfigでGPIOをセットする。
CONFIG_GPIO_LED_0
という名前でアサインされているピンを指定(どこでアサインされているかは後ほど)、GPIO_CFG_OUT_STD
はスタンダードにhighとlowを指定する働きの時にこう記述する。
ここでプルアップを選択したりという事もできる。詳細は以下を参照。
https://software-dl.ti.com/simplelink/esd/simplelink_cc13x2_26x2_sdk/4.20.00.35/exports/docs/tidrivers/doxygen/html/group___g_p_i_o___pin_config_settings.html
GPIO_CFG_OUT_LOW
でLOW状態にする。むろんHIGHもある。
/* Turn on user LED */
GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);
CONFIG_GPIO_LED_0という名前のピンをCONFIG_GPIO_LED_ON=1にする
GPIO_write(CONFIG_GPIO_LED_0, 1);
って書いても同じ
スレッドは無限に続くように記載するので
while (1) {
sleep(time);
GPIO_toggle(CONFIG_GPIO_LED_0);
}
sleep(1)で1秒停止してくれる。
C言語標準の関数で処理が止められる?
C言語だとSleepと大文字から始まるとmsec単位でSleep(500)で0.5秒になる。
がこれに置き換えをするとエラーになる(変更して試してほしい)
usleepはusec単位でC言語だと止められる。これはエラーにはならない。1000000で1秒だからと置き換えを実施してみる・・・がしかし動かない・・・ずっとLEDが点灯したままになる。
GPIO_toggleはtoggleしたいピンの名称を入れる。
CONFIG_GPIO_LED_0ってピンのアサインされている。これは、MSP432E401Yのボード上のLED0に対応している。
それを指定しているファイルが、
empty.syscfg
というファイル。
右クリックしOpen Withを選択、Sysconfig editorで開く。
CONFIG_GPIO_LED_0の設定が見る事ができる。例えば、ここでまずUseHardwareの部分をクリックする。
MSP432E401Yのボード上にあるハードが表示される。CONFIG_GPIO_LED_0という名前は、LaunchPadLED D1としますよ!と書いてある訳。
試しに、LaunchPadLED D2を選択し、ビルトして書き込んでみるとお隣が点滅する。
CONFIG_GPIO_LED_0という名前のアサインをLaunchPadLED D1に戻して、もう一つLEDを点滅させる。
+ADDのボタンを押すと一つ追加する。
Nameがデフォルトでは、CONFIG_GPIO_0のように入っているが、CONFIG_GPIO_LED_1に変更してみる。その上で、Use HardwareをLaunchPadLED D2にする。ここで既にアサインされているピンを割り当てしようとしてもコンフリクトしていると怒られる。
/* Configure the LED pin */
GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
GPIO_setConfig(CONFIG_GPIO_LED_1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
/* Turn on user LED */
GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);
GPIO_write(CONFIG_GPIO_LED_1, CONFIG_GPIO_LED_OFF);
while (1) {
sleep(time);
GPIO_toggle(CONFIG_GPIO_LED_0);
GPIO_toggle(CONFIG_GPIO_LED_1);
}
と編集してビルトし送り込んでみる。
初期状態がONとOFFなので交互に点滅させられる。
TI-RTOSでは、どのピンを何のペリフェラルに使うかは、.syscfgの中で定義され、GUIで選択したり、名前を与える事で、自動的にコードを生成してくれる。
このファイルをOpen WithでText Editorで開くと自動生成されたコードが確認できる。
上の例の場合はLaunchPadにあるLEDやスイッチはリストに出てくるが、任意のGPIOを指定する場合は、HardwareをNoneにしておいて、PinMux Peripheral and Pin Configuration をクリックすると展開されてGPIOピンが見える、選択のリストをクリックすると指定できるピンすべてが現れる。
コメント
コメントを投稿