SlideShare a Scribd company logo
1 of 132
組み込みアプリケーション開発ガイド
Stellaris を使用した
目的
 Stellarisの仮想HW/評価ボードを使い次の事を学びま
す
 簡単なプログラムの作成
 gcc の使い方
 組み込みシステム開発の基本
 Coretex-M3 の基本
 TOPPERS/ASP によるプログラムの実行
 TOPPERS/ASP の概要
 iTRON の概要
 組み込みアプリケーション開発ガイド
 組み込みアプリケーション開発の基本
 iTRON の API
 割り込みの使用方法
第一部:簡単なプログラムの作成
Stellaris で簡単なプログラムを書く
 出来ること
 TLMu(仮想HW) でのみの簡単な動作
 Stellaris で簡単なプログラムを書く方法
 スタートアップルーチン
 レジスタへのアクセス
 出来ないこと
 C の規約を満たしていない(BSS のクリア)
 割り込みの処理
Stellaris(LM3S811) のメモリ構成
0x0000 0000
0x2000 0000
8K
128KFlash ROM
SRAM
0x4000 0000
各種レジスタ
プログラムの配置
0x0000 0000
0x2000 0000
8K
128K
BSS
Program
Vector Table
DATA
Heap
Stack
ReadOnly Data
Cortex-M3 の形
式
TLMu での簡易 make
CFLAGS = -Wall -ggdb -O2 -mcpu=cortex-m3 -mthumb $(DEFS)
LDFLAGS = -Wl,-Ttext,0x000000c0
LDFLAGS += -Wl,-Tdata,0x20000000
LDFLAGS += -nostartfiles
LDLIBS += -nostdlib Cortex-m3 の
指定
開始アドレス
の指定
SRAMアドレス
の指定
一般的な startfiles
を使わない
スタートアップファイル
.global _start
.cpu cortex-m3
.thumb_func
_start:
movw r3, #8192
movt r3, #0x2000
mov sp, r3
bl run
スタックの設定
Cのルーチン
へ
C プログラム
void run(void)
{
*(volatile int *) (MAGIC_TRACE) = 0;
putstr("Hello, I am the ARMn");
#ifdef TEST_GPIO
test_gpio();
#endif
exit(0);
}
Cのルーチン
の先頭
GPIO 用テストプログラムの例
void
test_gpio()
{
*(volatile int *) (GPIO_A_ADDR + 0x400) = 0xFF;
#ifdef PL061
// pl061
*(volatile int *) (GPIO_A_ADDR + (0xFF << 2)) =
0xFF;
#endif
// stellaris
*(volatile int *) (GPIO_A_ADDR) = 0xFF;
}
GPIO の
アドレス
volatile が必要
簡易プログラムで未達成な事
• BSS のクリア
 C の規約を満たしていない(BSS のクリア)
• vector の処理
 割り込みの処理 → TLMu でしか動かない
TI 提供のプログラムを動かす
 出来ること
 実機/TLMu 上での動作
 割り込み等の処理
 TI提供のプログラムの構造
 スタートアップルーチン
 割り込み
 各種ライブラリ
 Hello までの道のり
 出来ないこと
 タスクを使った同時処理
スタートアップルーチン
 startup_gcc.c として提供されている
__attribute__ ((section(".isr_vector")))
void (* const g_pfnVectors[])(void) =
{
(void (*)(void))((unsigned long)pulStack + sizeof(pulStack)),
// The initial stack pointer
ResetISR, // The reset handler
NmiSR, // The NMI handler
FaultISR, // The hard fault handler
IntDefaultHandler, // The MPU fault handler
IntDefaultHandler, // The bus fault handler
IntDefaultHandler, // The usage fault handler
0, // Reserved
0, // Reserved
0, // Reserved
割り込みを使用可能
 vector の設定を追加
 割り込みルーチンを追加
#ifdef __GNUC__
void Timer0IntHandler(void)
__attribute__((__interrupt__));
#endif
void
Timer0IntHandler(void)
#ifdef __GNUC__
void Timer0IntHandler(void)
__attribute__((__interrupt__));
#endif
void
Timer0IntHandler(void)
各種ライブラリ
 初期設定ライブラリ
 OLED ライブラリ
 割り込み等の制御ライブラリ
Hello までの道のり
int
main(void)
{
//
// Set the clocking to run directly from the crystal.
//
SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC |
SYSCTL_OSC_MAIN |
SYSCTL_XTAL_6MHZ);
//
// Initialize the OLED display.
//
OSRAMInit(false);
//
// Hello!
//
OSRAMStringDraw("Hello World! 4", 0, 0);
OSRAMStringDraw("GNU M. Thomas", 0, 46);
//
// Exit.
//
DiagExit(0);
}
#__GNUC__
void Timer0IntHandler(void)
__attribute__((__interrupt__));
#
void
Timer0IntHandler(void)
クロックの設定
OLEDの設定
OLEDへの表
示
タイマ使用例
//
// Enable the peripherals used by this example.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
//
// Enable processor interrupts.
//
IntMasterEnable();
//
// Configure the two 32-bit periodic timers.
//
TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PER);
TimerConfigure(TIMER1_BASE, TIMER_CFG_32_BIT_PER);
TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet());
TimerLoadSet(TIMER1_BASE, TIMER_A, SysCtlClockGet() / 2);
//
// Setup the interrupts for the timer timeouts.
//
IntEnable(INT_TIMER0A);
IntEnable(INT_TIMER1A);
TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
//
// Enable the timers.
//
TimerEnable(TIMER0_BASE, TIMER_A);
TimerEnable(TIMER1_BASE, TIMER_A);
//
// Loop forever while the timers run.
//
while(1)
{
}
#__GNUC__
void Timer0IntHandler(void)
__attribute__((__interrupt__));
#
void
Timer0IntHandler(void)
タイマの選択
割り込みを有
効化
タイマの設定
タイマの
割り込み設定
タイマを有効化
無限ループで
割り込みを待つ
第二部:TOPPERS/ASP による
プログラムの実行
TOPPERS/ASP を動かす
 TOPPERS/ASP の構成
 サンプルプログラムを動かす
TOPPERS/ASPの構成
 kernel
 カーネルの本体
 arch/arm_m_gcc
 cortex-m3 の固有部分
 target/lm3s811_gcc
 Lm3s811_gcc の固有部分
サンプルプログラムを作るには?
 cfg を用意する
 sample プログラムを用意する
cfg
#__GNUC__
void Timer0IntHandler(void)
__attribute__((__interrupt__));
#
void
Timer0IntHandler(void)
タスクの設定
各種資源の
設定
/*
* @(#) $Id: sample1.cfg 718 2008-01-01 12:30:48Z hiro $
*/
/*
* サンプルプログラム(1)のシステムコンフィギュレーションファイル
*/
INCLUDE("target_timer.cfg");
INCLUDE("syssvc/syslog.cfg");
INCLUDE("syssvc/banner.cfg");
INCLUDE("syssvc/serial.cfg");
INCLUDE("syssvc/logtask.cfg");
#include "sample1.h"
CRE_TSK(TASK1, { TA_NULL, 1, task, MID_PRIORITY, STACK_SIZE, NULL });
CRE_TSK(TASK2, { TA_NULL, 2, task, MID_PRIORITY, STACK_SIZE, NULL });
CRE_TSK(TASK3, { TA_NULL, 3, task, MID_PRIORITY, STACK_SIZE, NULL });
CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, MAIN_PRIORITY,
STACK_SIZE, NULL });
DEF_TEX(TASK1, { TA_NULL, tex_routine });
DEF_TEX(TASK2, { TA_NULL, tex_routine });
DEF_TEX(TASK3, { TA_NULL, tex_routine });
CRE_CYC(CYCHDR1, { TA_NULL, 0, cyclic_handler, 2000, 0 });
CRE_ALM(ALMHDR1, { TA_NULL, 0, alarm_handler });
#ifdef CPUEXC1
DEF_EXC(CPUEXC1, { TA_NULL, cpuexc_handler });
#endif /* CPUEXC1 */
#__GNUC__
void Timer0IntHandler(void)
__attribute__((__interrupt__));
#
void
Timer0IntHandler(void)
#__GNUC__
void Timer0IntHandler(void)
__attribute__((__interrupt__));
#
void
Timer0IntHandler(void)
サンプルプログラム
/*
* タスクの起動
*/
SVC_PERROR(act_tsk(TASK1));
SVC_PERROR(act_tsk(TASK2));
SVC_PERROR(act_tsk(TASK3));
/*
* 並行実行されるタスク
*/
void task(intptr_t exinf)
{
volatile ulong_t i;
…..
TOPPERS/ASP を動かす
 ソースの展開
 開発環境とコンフィギュレータの準備
 コンフィグレート
 コンパイル
 仮想環境での実行
 実機での実行
ソースの展開
 lm3s811_toppers.tar.gz を展開
差し替え予定
開発環境とコンフィギュレータの準備
 コンパイラ
 CodeSourcery が提供している arm-none-eabi を使用
(Linux 用のコンパイラではない点に注意)
 コンフィギュレータ
 TOPPERS 用のコンフィギュレータ
 boost ライブラリが必要
コンフィギュレータって何?
cfg ファイル
ソースファイル
リソース用の
ソースファイル
ARM 用
コンパイラ
ARM用
実行ファイル
コンフィギュレータ
コンフィグレート
 perl ../lm3s811_toppers/asp/configure -T lm3s811_gcc -A sample1
コンパイル
 make
 arm-none-eabi-size asp で確認
第三部:組み込みアプリケーション
開発ガイド
LED を点灯させる
 LED というペリフェラル
 仕様書の確認
 コンフィグレート/コンパイル/動作確認
 volatile について
 ソースの修正
 コンパイル/動作確認
 PL061 との違い
LED というペリフェラル
 LED というペリフェラル:光るという意味において豆電球
と同じ!!
電池と豆電球の回路の例 電池とLED回路の例
+
-
LM3S811 評価ボード上の LED 例
User’s Manual より抜粋
ボード上の
LED
LM3S811 評価ボードの回路図の例
User’s Manual より抜粋
GPIO というペリフェラル
PC5/CCP1
はここにつな
がっている
User’s Manual より抜粋
実際の LM3S811 SoC
仕様書(datasheet)を確認する
Data Sheet より抜粋
更に仕様書(datasheet)を確認する
Data Sheet より抜粋
更に更に仕様書(datasheet)を確認する
Data Sheet より抜粋
更に更に更に仕様書(datasheet)を確認する
飛ばしすぎです!!
GPIO ってなんでしたっけ?
 LED はペリフェラル
 GPIO は General Purpose Input Output
 Output なら LED などの出力するための機器がつながる
 Input なら SW(スイッチ)などの入力するための機器がつなが
る。
 Output/Input はソフトウェアで制御する
 SoC によっては他の機能とピンが共用している
 GPIO と他の機能のどちらを使うかはソフトウェアで制御
LED を光らせるには?
 該当するピンを GPIO として使用するように宣言
 例:PIN13 は GPIO のPC5と CCP1 とで共用している
 GPIO を Output と使用するように宣言
 GPIO を制御して PC5 から1を出力するようにする
 0 を出力することで光る場合もある。回路による。
この部分はTI が用意する
SterallisWare のライブラリ
を使用する。
ここが今回のポイント
LED を光らせる準備
 該当するピンを GPIO として使用するように宣言
 実際には特定のアドレスに対して“ある”値を書き込む
 ここは StellarisWare のライブラリを使うことで解決!
StellarisWare より抜粋
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
LED を光らせる準備
 GPIO を Output と使用するように宣言
 実際には特定のアドレスに対して“ある”値を書き込む
 ここは StellarisWare のライブラリを使うことで解決!
StellarisWare より抜粋
GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE, LED_GPIO_PIN_5);
LED を光らせるには?(準備OK?)
 GPIO を制御して PC5 から1を出力するようにする
 PC5(Port C の5番は) は 0x4000 6000 の 5ビット目。
Port C のベースは 0x4000 6000 番地
5番は 5ビット目
オフセットが 0x000番地
LED を光らせるには?(準備OK?)
 GPIO を制御して PC5 から1を出力するようにする
 PC5(Port C の5番は) は 0x4000 63FC の 5ビット目。
Port C のベースは 0x4000 6000 番地
5番は 5ビット目
オフセットが 0x000番地だけど仕様書が
間違い?0x3FC
LEDを光らせるプログラムはこんな感じ?
#define LED_GPIO_C_ADDR
(0x400063FC)
#define LED_GPIO_PIN_5 (1 << 5)
int *gpio_c;
gpio_c = (int *)LED_GPIO_C_ADDR;
for ( i = 0 ; i < 1000000; ++i ) {
*gpio_c = LED_GPIO_PIN_5;
*gpio_c = 0;
}
*gpio_c = 0;
実はこのプログラムちゃんと動きません、、、
on/off を繰り返しているつもり
実際の動きあわせて修正
とりあえずコンパイル・実行
$ perl ../lm3s811_toppers/asp/configure -T lm3s811_gcc -A led
$ make USE_QEMU=true
$ ls asp
asp
$ mv asp led
実機で実行するには?
$ perl ../lm3s811_toppers/asp/configure -T lm3s811_gcc -A led
$ make
$ ls asp
asp
$ mv asp led
$ arm-none-eabi-objcopy -O binary led led.bin
なぜ動かないか?LED というペリフェラル
 LED はメモリ素子ではありません
 C のプログラムはアドレスへの書き込みはメモリだと
思っています。(そのように最適化される)
コンパイラはメモリへのアクセスを最適化する
#define LED_GPIO_C_ADDR
(0x400063FC)
#define LED_GPIO_PIN_5 (1 << 5)
int *gpio_c;
gpio_c = (int *)LED_GPIO_C_ADDR;
for ( i = 0 ; i < 1000000; ++i ) {
*gpio_c = LED_GPIO_PIN_5;
*gpio_c = 0;
}
*gpio_c = 0;
gpio_c というメモリ用のポインタを
用意
gpio_c に 0x400063FC という
アドレスを設定
コンパイラはメモリに 0x20 と 0 を
繰り返し書いていると思っている
コンパイラはメモリに最終的に 0 を
書いていると思っている
コンパイラはこの繰り返しは無駄。最後に0を書いているのだから、
繰り返しをせずに 0 とだけ書いておこうと判断する”かも”しれない。
最適化されてしまったソース
#define LED_GPIO_C_ADDR
(0x400063FC)
#define LED_GPIO_PIN_5 (1 << 5)
int *gpio_c;
gpio_c = (int *)LED_GPIO_C_ADDR;
for ( i = 0 ; i < 1000000; ++i ) {
*gpio_c = LED_GPIO_PIN_5;
*gpio_c = 0;
}
*gpio_c = 0;
最適化されないように教える手段
 volatile を使う
#define LED_GPIO_C_ADDR
(0x400063FC)
#define LED_GPIO_PIN_5 (1 << 5)
volatile int *gpio_c;
gpio_c = (int *)LED_GPIO_C_ADDR;
for ( i = 0 ; i < 1000000; ++i ) {
*gpio_c = LED_GPIO_PIN_5;
*gpio_c = 0;
}
*gpio_c = 0;
コンパイラに最適化しないように指示。
volatile とは?
volatile とは?
volatileの目的は,黙っていると処理系で行われる最適化を抑止すること
にある.例えば,メモリ・マップ方式の入出力をもつマシンでは,ステータ
ス・レジスタに対するポインタは,ポインタによる見かけ上,冗長な参照
をコンパイラが除去するのを防ぐのに,volatileへのポインタと宣言する
ことが可能である.
プログラミング言語C 第2版
ANSI規格準拠より抜粋
StellarisWare を使う
 StellarisWare ではhw_types.h にそのためのマクロが用意
されている。
 HWREG (単純なアクセス)
 HWREGBITW(ビットバンドを使ったアクセス)
HWREGBITW(LED_GPIO_C_ADDR, 5) = 1;
led-fix のコンパイル・実行
$ perl ../lm3s811_toppers/asp/configure -T lm3s811_gcc -A led-fix
$ make USE_QEMU=true
$ ls asp
asp
$ mv asp led-fix
スイッチ(SW) を使う
 SW というペリフェラル
 volatile について
 コンフィグレート/コンパイル/動作確認
 (仕様書の確認:割愛)
 ソースの修正
 コンパイル/動作確認
 StellarisWare を使う
SW というペリフェラル
 SW というペリフェラル:スィッチ という Input 用のペリ
フェラル。LED と同様にメモリではない。
電池と豆電球とSWの回路の例 電池とLEDとSWの回路の例
+
-
GPIO 復習
 LED はペリフェラル
 SW もペリフェラル
 GPIO は General Purpose Input Output
 Output なら LED などの出力するための機器がつながる
 Input なら SW(スイッチ)などの入力するための機器がつなが
る
 Output/Input はソフトウェアで制御する
 SoC によっては他の機能とピンが共用している
 GPIO と他の機能のどちらを使うかはソフトウェアで制御
ユーザズマニュアルで確認
User’s Manual より抜粋
LED を光らせるには?
 該当するピンを GPIO として使用するように宣言
 例:PIN14 は GPIO のPC4だけの機能。
 GPIO を Input と使用するように宣言
 GPIO を制御して PC4 から入力値を得るようにする
 今回の回路では 0 が on。回路による。
この部分はTI が用意する
SterallisWare のライブラリ
を使用する。
ここが今回のポイント
SWを使う準備
StellarisWare より抜粋
 該当するピンを GPIO として使用するように宣言
 ここは StellarisWare のライブラリを使うことで解決!
 (実はすでに LED でやっている)
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
SWを使う準備
 GPIO を Input と使用するように宣言
 実際には特定のアドレスに対して“ある”値を書き込む
 ここは StellarisWare のライブラリを使うことで解決!
StellarisWare より抜粋
GPIOPinTypeGPIOInput(GPIO_PORTC_BASE, SW_GPIO_PIN_4);
SWから情報得るにはこんな感じ?
int *gpio_c;
gpio_c = (int *)GPIO_C_ADDR;
while ( 1 ) {
v = *gpio_c;
if ( SW_GPIO_PIN_4 & v ) {
*gpio_c = 0;
} else {
*gpio_c =
LED_GPIO_PIN_5;
}
}
SW の値を呼んでいるつもり。
しかし volatile 宣言されて
いないので動かない。
動かないことを確認
$ perl ../lm3s811_toppers/asp/configure -T lm3s811_gcc -A led-sw
$ make USE_QEMU=true
$ ls asp
asp
$ mv asp led-sw
なぜ動かないか?SWというペリフェラル
 SW はメモリ素子ではありません
 C のプログラムはアドレスへの読み込みはメモリだと
思っています。(そのように最適化される)
 volatile 宣言することで解決
実際にソースを修正して
確認してみよう
修正済みのソースを確認する
$ perl ../lm3s811_toppers/asp/configure -T lm3s811_gcc -A led-sw-fix
$ make USE_QEMU=true
$ ls asp
asp
$ mv asp led-sw-fix
タスクを使う
 タスクを使おう
 LEDタスクとSWタスク(cfg ファイルの確認)
 dly_tsk を使う
 rot_rdq を使う
 セマフォを使う(led task を high priority にする)
 コンパイル/動作確認
タスクを使おう
 iTRON ではタスクを有効に使う
 タスクはコンテキストを保持することが可能
 CPU を仮想化する技術
 CPU の使用率を上げることができる
 割り込みはコンテキストを保持できない
 割り込み処理では wait することができない
 タスクの優先順位と割り込みを理解 → RTOS の理解
システム例(SW タスクとLEDタスク)
SW タスク(main_task) led_task
SWを見る
ことだけに
専念
LEDを光ら
せることだ
けに専念
g_flag
LED タスクの例
void
led_task(intptr_t exinf)
{
while ( 1 ) {
if ( g_flag ) {
HWREGBITW(GPIO_C_ADDR, LED_GPIO_PIN_5_BIT) = 1;
} else {
HWREGBITW(GPIO_C_ADDR, LED_GPIO_PIN_5_BIT) = 0;
}
}
}
led-sw-task.cfg の確認
INCLUDE("target_timer.cfg");
INCLUDE("syssvc/syslog.cfg");
INCLUDE("syssvc/banner.cfg");
INCLUDE("syssvc/serial.cfg");
INCLUDE("syssvc/logtask.cfg");
#include "led-sw-task.h"
CRE_TSK(LED_TASK, { TA_NULL, 0, led_task, TASK_PRIORITY, STACK_SIZE,
NULL });
CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, TASK_PRIORITY, STACK_SIZE,
NULL });
リソース名称 TA_ACT: すぐに起動
TA_NULL:すぐに起動しな
い
関数名
プライオリティ
Led-sw-task.h 内
で定義
スタックサイズ
本システムでは512
led-sw-task のコンパイル・実行
$ perl ../lm3s811_toppers/asp/configure -T lm3s811_gcc -A led-sw-task
$ make USE_QEMU=true
$ ls asp
asp
$ mv asp led-sw-task
main_task の例
void
main_task(intptr_t exinf)
{
init_peripheral();
g_flag = 0;
Display96x16x1StringDraw("g_flag = 0", 0, 12);
HWREGBITW(GPIO_C_ADDR, LED_GPIO_PIN_5_BIT) = 0;
act_tsk(LED_TASK);
while ( 1 ) {
g_flag = HWREGBITW(GPIO_C_ADDR, SW_GPIO_PIN_4_BIT);
#if 0
Display96x16x1StringDraw(g_flag?"1":"0", 54, 12);
#endif
}
ext_ker();
assert(0);
}
LED_TASK を起動
g_flag を変更。led_task は
g_flag を見て LED を点滅
させるはず。
うまく意図通りに動かないのはなぜか?
 iTRON ではタスクは自動的に切り替わらない
 プライオリティを含めたタスクの設計が必要
簡単なしかし禁じ手の方法を確かめる
 dly_tsk(100) を main_task に追加する
 性能が悪いことを確認する
実際にソースを修正して
確認してみよう
dly_tsk は問題を回避はした
がスマートな方法ではない
rot_rdq を使う
 rot_drq (TASK_PRIORITY); を追加
 レディキューをローテートする。
 スマートではない。(API として記憶にとどめる程度?)
修正済みのソースを実行し確認する
$ perl ../lm3s811_toppers/asp/configure -T lm3s811_gcc -A rod-rdq
$ make USE_QEMU=true
$ ls asp
asp
$ mv asp rod-rdq
プライオリティを変えてコンパイルしてみる
 cfg の修正
CRE_TSK(LED_TASK, { TA_NULL, 0, led_task, TASK_PRIORITY, STACK_SIZE,
NULL });
CRE_TSK(LED_TASK, { TA_NULL, 0, led_task, TASK_PRIORITY - 1, STACK_SIZE,
NULL });
スマートな方法はセマフォを使うこと
 cfg にセマフォの資源を追加
 CRE_SEM(SEM_FOR_LED_TASK, { TA_NULL, 1, 1 });
 led_task に wai_sem を追加
 wai_sem(SEM_FOR_LED_TASK);
 main_task に sig_sem を追加
 sig_sem(SEM_FOR_LED_TASK);
 main_task に dly_tsk をやむなく追加
cfg にセマフォの資源を追加
INCLUDE("target_timer.cfg");
INCLUDE("syssvc/syslog.cfg");
INCLUDE("syssvc/banner.cfg");
INCLUDE("syssvc/serial.cfg");
INCLUDE("syssvc/logtask.cfg");
#include "led-sw-sem.h"
CRE_TSK(LED_TASK, { TA_NULL, 0, led_task, TASK_PRIORITY, STACK_SIZE,
NULL });
CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, TASK_PRIORITY, STACK_SIZE,
NULL });
CRE_SEM(SEM_FOR_LED_TASK, { TA_NULL, 1, 1 });
led_task に wai_sem を追加
void
led_task(intptr_t exinf)
{
while ( 1 ) {
wai_sem(SEM_FOR_LED_TASK);
if ( g_flag ) {
HWREGBITW(GPIO_C_ADDR, LED_GPIO_PIN_5_BIT) = 1;
} else {
HWREGBITW(GPIO_C_ADDR, LED_GPIO_PIN_5_BIT) = 0;
}
}
}
main_task を修正
HWREGBITW(GPIO_C_ADDR, LED_GPIO_PIN_5_BIT) = 0;
act_tsk(LED_TASK);
while ( 1 ) {
flag = HWREGBITW(GPIO_C_ADDR, SW_GPIO_PIN_4_BIT);
if ( g_flag != flag ) {
g_flag = flag;
sig_sem(SEM_FOR_LED_TASK);
}
Display96x16x1StringDraw(flag?"1":"0", 54, 12);
dly_tsk(100);
}
禁じ手の dly_tsk
 main_task が dly_tsk を使っていて美しくない。
解決には割り込みの知識が
必要
修正済みのソースを実行し確認する
$ perl ../lm3s811_toppers/asp/configure -T lm3s811_gcc -A led-sw-sem
$ make USE_QEMU=true
$ ls asp
asp
$ mv asp led-sw-sem
タスクを使う
 カウントするプログラム
 コンフィグレート/コンパイル/動作確認
 表示が乱れる件について
 排他制御
 動作確認
システム例(カウントタスク)
count_task count_task
totalcount[0] count[1]
cfg を確認
 2つの TASK が共通の関数を使う事に注意
 count_task に渡される引数が違う
 これにより自分のタスク番号を認識
 ローカル変数はそれぞれのスタック内に領域獲得
 グローバル変数は共通
CRE_TSK(COUNT_TASK_A, { TA_NULL, 0, count_task, LOW_PRIORITY, STACK_SIZE,
NULL });
CRE_TSK(COUNT_TASK_B, { TA_NULL, 1, count_task, LOW_PRIORITY, STACK_SIZE,
NULL });
CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, TASK_PRIORITY, STACK_SIZE, NULL });
count_task に与えられる引数
main_task の方がプライオリティが高い
main_task がコントロール
act_tsk(COUNT_TASK_A);
act_tsk(COUNT_TASK_B);
while ( 1 ) {
dly_tsk(10);
rot_rdq(LOW_PRIORITY);
if ((count[0] + count[1]) == total ) {
Display96x16x1StringDraw("OK ", 0, 12);
} else {
Display96x16x1StringDraw("Failed", 0, 12);
}
syslog(LOG_INFO, "%d + %d = %d", count[0], count[1], total);
}
count_task の制御
コンパイル実行する
$ perl ../lm3s811_toppers/asp/configure -T lm3s811_gcc -A task_count
$ make USE_QEMU=true
$ ls asp
asp
$ mv asp task_count
意図通りに動かない理由
count_task count_task
資源の競合
count[0] count[1]
total
OLED の表示もおかしくなる
count_task count_task
資源の競合
count[0] count[1]
total
OLED
競合回避するためにはセマフォを使う
 cfg にセマフォの資源を追加
 CRE_SEM(SEM_FOR_TASK, { TA_NULL, 1, 1 });
 count_taskに wai_sem/sig_sem を追加
 wai_sem(SEM_FOR_TASK);
 sig_sem(SEM_FOR_TASK);
cfg にセマフォの資源を追加
CRE_TSK(COUNT_TASK_A, { TA_NULL, 0, count_task, LOW_PRIORITY, STACK_SIZE,
NULL });
CRE_TSK(COUNT_TASK_B, { TA_NULL, 1, count_task, LOW_PRIORITY, STACK_SIZE,
NULL });
CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, TASK_PRIORITY, STACK_SIZE, NULL });
CRE_SEM(SEM_FOR_TASK, { TA_NULL, 1, 1 });
count_taskに wai_sem/sig_sem を追加
while ( 1 ) {
wai_sem(SEM_FOR_TASK);
saved_task = total;
count[task_no] ++;
saved_task ++;
total = saved_task;
if ( task_no ) {
Display96x16x1StringDraw("task 0", 30,
12);
} else {
Display96x16x1StringDraw("task 1", 30,
12);
}
sig_sem(SEM_FOR_TASK);
}
修正済みのソースを実行し確認する
$ perl ../lm3s811_toppers/asp/configure -T lm3s811_gcc -A task-count-fix
$ make USE_QEMU=true
$ ls asp
asp
$ mv asp task-count-fix
ADC を使う
 コンフィグレート/コンパイル/動作確認
 割り込みをつかう
 パラメタ変更
 コンパイル/動作確認
システム例(ADC:割り込みを使用)
main_task adc_isr
OLED
割り込みの特徴
 非同期のお知らせシステム
 割り込み処理ルーチン中は他の処理は出来ない
 タスクなどの処理は出来ない
 多重割り込みするためには仕組みが必要
 多重割り込みは難しい
 割り込みを wait することは出来ない
 wai_sem などで待つことができない
 コンテキストを保持できないため
 割り込み要因をクリアする必要がある
あまり美しくない割り込みルーチンの例
void
adc_isr(intptr_t exinf)
{
char i_adc_str[] = "i 0";
unsigned long value;
ADCIntClear(ADC0_BASE, 3);
ADCSequenceDataGet(ADC0_BASE, 3, &value);
syslog(LOG_INFO, "intr wheel d %d", value);
i_adc_str[2] = '0' + value / 100;
Display96x16x1StringDraw(i_adc_str, 50, 12);
}
割り込み要因のクリア
美しくない
美しくない
美しくない
割り込みを使用するには
cfg に資源の追加の必要がある。
CRE_TSK(ADC_TASK, { TA_NULL, 0, adc_task, LOW_PRIORITY, STACK_SIZE, NULL });
CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, TASK_PRIORITY, STACK_SIZE, NULL });
ATT_ISR({ TA_NULL, 0, INT_ADC3, adc_isr, 1 });
CFG_INT(INT_ADC3, { TA_ENAINT, ADC_INTR_PRIORITY });
追加の資源
コンパイル実行する
$ perl ../lm3s811_toppers/asp/configure -T lm3s811_gcc –A adc-intr
$ make USE_QEMU=true
$ ls asp
asp
$ mv asp adc-intr
割り込みを使う
 まずはタスクのみの動作なので非常に遅いレスポンス
 USE_ADC_INTR を有効にして割り込みを使う
資源の競合
OLED の表示がおかしくなる
main_task adc_isr
OLED
wai_sem が使えな
い!!
表示がうまくいくようにタスクを使う
main_task adc_isr
OLED
adc_task
g_flag
ソースの変更
 割り込みを使う
 #define USE_ADC_INTR
 adc_isr を変更
 g_flag = 1; だけにする
 セマフォを使う
割り込みを使う
#define USE_ADC_INTR
#ifdef USE_ADC_INTR
ADCIntEnable(ADC0_BASE, 3);
IntEnable(INT_ADC0SS3);
#endif
adc_isr の変更
void
adc_isr(intptr_t exinf)
{
#if 0
char i_adc_str[] = "i 0";
unsigned long value;
#endif
ADCIntClear(ADC0_BASE, 3);
#if 0
ADCSequenceDataGet(ADC0_BASE, 3, &value);
syslog(LOG_INFO, "intr wheel d %d", value);
i_adc_str[0] = '0' + value / 100;
i_adc_str[1] = 0;
Display96x16x1StringDraw(i_adc_str, 50, 12);
#endif
g_flag = 1;
}
重い処理をタスク
に移動
フラグの書き換え
adr_task の追加
void
adc_task(intptr_t exinf)
{
unsigned long value;
char t_adc_str[] = "t 0";
while ( 1 ) {
if ( g_flag == 1 ) {
wai_sem(SEM_FOR_TASK);
dly_tsk(10);
ADCSequenceDataGet(ADC0_BASE, 3, &value);
syslog(LOG_INFO, "adc_task wheel %d", value);
t_adc_str[2] = '0' + value / 100;
Display96x16x1StringDraw(t_adc_str, 50, 12);
sig_sem(SEM_FOR_TASK);
g_flag = 0;
} else {
dly_tsk(90);
}
}
}
セマフォで排他可能
フラグを待つ
またも禁じ手のdly_tsk
フラグをリセット
main_task の変更
while ( 1 ) {
wai_sem(SEM_FOR_TASK);
ADCSequenceDataGet(ADC0_BASE, 3, &value);
syslog(LOG_INFO, "wheel %d", value);
adc_str[4] = '0' + value / 100;
Display96x16x1StringDraw(adc_str, 0, 12);
sig_sem(SEM_FOR_TASK);
dly_tsk(100);
}
セマフォで排他可能
cfg の変更
CRE_TSK(ADC_TASK, { TA_NULL, 0, adc_task, LOW_PRIORITY, STACK_SIZE,
NULL });
CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, TASK_PRIORITY, STACK_SIZE,
NULL });
ATT_ISR({ TA_NULL, 0, INT_ADC3, adc_isr, 1 });
CFG_INT(INT_ADC3, { TA_ENAINT, ADC_INTR_PRIORITY });
CRE_SEM(SEM_FOR_TASK, { TA_NULL, 1, 1 });
セマフォの追加
大変更をした adr-intr の改変版を実行
 割り込みを使う
 #define USE_ADC_INTR
 adc_isr を変更
 g_flag = 1; だけにする
 セマフォを使う
実際にソースを修正して
確認してみよう
修正済みのソースを実行し確認する
$ perl ../lm3s811_toppers/asp/configure -T lm3s811_gcc -A adc-task
$ make USE_QEMU=true
$ ls asp
asp
$ mv asp adc-task
何が美しくなかったのか?
void
adc_isr(intptr_t exinf)
{
char i_adc_str[] = "i 0";
unsigned long value;
ADCIntClear(ADC0_BASE, 3);
ADCSequenceDataGet(ADC0_BASE, 3, &value);
syslog(LOG_INFO, "intr wheel d %d", value);
i_adc_str[2] = '0' + value / 100;
Display96x16x1StringDraw(i_adc_str, 50, 12);
}
必要以上のスタックの消費
UART を使った出力
OLED を使った出力
シンプルになった割り込みルーチンの例
void
adc_isr(intptr_t exinf)
{
char i_adc_str[] = "i 0";
unsigned long value;
ADCIntClear(ADC0_BASE, 3);
ADCSequenceDataGet(ADC0_BASE, 3, &value);
syslog(LOG_INFO, "intr wheel d %d", value);
i_adc_str[2] = '0' + value / 100;
Display96x16x1StringDraw(i_adc_str, 50, 12);
g_flag = 1;
} dly_tsk を必要とする
情報の受け渡し方
iTRON の FLG API を使う
 g_flag をつかった情報受け渡しの欠点
 読み出し側が g_flag を読むタイミングを決定できない
 結果としてポーリングすることになる
 ポーリングの実装として dly_tsk をつかうことになる。
 FLG API を使う
 フラグ情報が変わった時に情報を伝えることができる
 割り込みでも使用できる API がある
 wait しないことが保障されている API の用意
禁じ手のdly_tsk
FLG を使う
main_task adc_isr
OLED
adc_task
FLG
FLG を使うための変更箇所
 cfg に資源を追加
 ポーリングに代わる API
 wai_flg
 clr_flg
 割り込みでの API
 iset_flg
cfg に資源を追加
CRE_TSK(ADC_TASK, { TA_NULL, 0, adc_task, LOW_PRIORITY, STACK_SIZE,
NULL });
CRE_TSK(MAIN_TASK, { TA_ACT, 0, main_task, TASK_PRIORITY, STACK_SIZE,
NULL });
ATT_ISR({ TA_NULL, 0, INT_ADC3, adc_isr, 1 });
CFG_INT(INT_ADC3, { TA_ENAINT, ADC_INTR_PRIORITY });
CRE_SEM(SEM_FOR_TASK, { TA_NULL, 1, 1 });
CRE_FLG(ADC_FLG, { TA_WMUL, 0x00U });
FLG 資源の追加
ポーリングに代わる API
void
adc_task(intptr_t exinf)
{
unsigned long value;
char t_adc_str[] = "t 0";
FLGPTN flgptn;
while ( 1 ) {
wai_flg(ADC_FLG, 0x01U, TWF_ORW, &flgptn);
clr_flg(ADC_FLG, ~0x1);
wai_sem(SEM_FOR_TASK);
ADCSequenceDataGet(ADC0_BASE, 3, &value);
#if 0
syslog(LOG_INFO, "adc_task wheel %d", value);
#endif
t_adc_str[2] = '0' + value / 100;
Display96x16x1StringDraw(t_adc_str, 50, 12);
sig_sem(SEM_FOR_TASK);
}
}
FLG の利用
割り込みでの API
void
adc_isr(intptr_t exinf)
{
ADCIntClear(ADC0_BASE, 3);
iset_flg(ADC_FLG, 0x1);
}
FLG の利用
修正済みのソースを実行し確認する
$ perl ../lm3s811_toppers/asp/configure -T lm3s811_gcc -A adc-task-fix
$ make USE_QEMU=true
$ ls asp
asp
$ mv asp adc-task-fix
タイマーを使う
 コンフィグレート/コンパイル/動作確認
 パラメタ変更
 割り込みを使う
 割り込みからFLGとMSGを使う
 コンパイル動作確認
2つのタイマ割り込みを使った例
timer1_sr
timer_task
FLG
timer0_isr
FLG
ソースを実行し確認する
$ perl ../lm3s811_toppers/asp/configure -T lm3s811_gcc -A timer
$ make USE_QEMU=true
$ ls asp
asp
$ mv asp timer
ここで応用問題
 main_task を表示用スレッドにする。
 現在は timer_task が表示も兼ねている
 timer_task から FLG で main_task へ表示を促す
 表示すべきデータはグローバル変数で受け渡す
新しいシステム
timer1_sr
timer_task
FLG
timer0_isr
FLG
main_task
FLG
表示データ
MBX(メッセージボックス)を使う
 渡したい情報
 FLG による1ビットの情報
 表示すべきデータ(複雑なデータ)
渡したい情報が複雑な場合
MBX を使うことができる
MBX の基本
 メッセージの送信
 snd_mbx( TIMER_MBX, (T_MSG *)&g_user_msg );
 メッセージの受信
 rcv_mbx( TIMER_MBX, (T_MSG **)&umsg );
 追加資源
 CRE_MBX(TIMER_MBX, { 0, TMAX_MPRI, NULL });
 データ構造例
struct user_msg {
T_MSG t_msg;
uint8_t version;
uint8_t led_on_off;
uint8_t msg_n;
uint8_t app_intr_no;
};
共通ヘッダ
使用者の定義
ソースを実行し確認する
$ perl ../lm3s811_toppers/asp/configure -T lm3s811_gcc -A timer-msg
$ make USE_QEMU=true
$ ls asp
asp
$ mv asp timer-msg
改訂履歴
バージョン 改訂内容 担当 改訂日
1.0 初版 鈴木量三朗 2012/12/20

More Related Content

What's hot

OpenCM IDE、OpenCM 485 EXPを用いてのDynamixel Xシリーズの制御
OpenCM IDE、OpenCM 485 EXPを用いてのDynamixel Xシリーズの制御OpenCM IDE、OpenCM 485 EXPを用いてのDynamixel Xシリーズの制御
OpenCM IDE、OpenCM 485 EXPを用いてのDynamixel Xシリーズの制御ROBOTIS Japan
 
StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件yaegashi
 
OPcache の最適化器の今
OPcache の最適化器の今OPcache の最適化器の今
OPcache の最適化器の今y-uti
 
Zynq VIPを利用したテストベンチ
Zynq VIPを利用したテストベンチZynq VIPを利用したテストベンチ
Zynq VIPを利用したテストベンチMr. Vengineer
 
libcのputcharについて
libcのputcharについてlibcのputcharについて
libcのputcharについてkusabanachi
 
php-src の歩き方
php-src の歩き方php-src の歩き方
php-src の歩き方do_aki
 
Boost.Coroutine
Boost.CoroutineBoost.Coroutine
Boost.Coroutinemelpon
 
cdev_write and_comwrite
cdev_write and_comwritecdev_write and_comwrite
cdev_write and_comwritekusabanachi
 
ZynqMPのブートとパワーマネージメント : (ZynqMP Boot and Power Management)
ZynqMPのブートとパワーマネージメント : (ZynqMP Boot and Power Management)ZynqMPのブートとパワーマネージメント : (ZynqMP Boot and Power Management)
ZynqMPのブートとパワーマネージメント : (ZynqMP Boot and Power Management)Mr. Vengineer
 
PHP AST 徹底解説
PHP AST 徹底解説PHP AST 徹底解説
PHP AST 徹底解説do_aki
 
Rtミドルウェア講習会 第3部資料 配布版
Rtミドルウェア講習会 第3部資料 配布版Rtミドルウェア講習会 第3部資料 配布版
Rtミドルウェア講習会 第3部資料 配布版openrtm
 
130711 01
130711 01130711 01
130711 01openrtm
 
4章 Linuxカーネル - 割り込み・例外 3
4章 Linuxカーネル - 割り込み・例外 34章 Linuxカーネル - 割り込み・例外 3
4章 Linuxカーネル - 割り込み・例外 3mao999
 
発表資料 Fortranを用いた高位合成技術FortRockの開発
発表資料 Fortranを用いた高位合成技術FortRockの開発発表資料 Fortranを用いた高位合成技術FortRockの開発
発表資料 Fortranを用いた高位合成技術FortRockの開発貴大 山下
 

What's hot (20)

OpenCM IDE、OpenCM 485 EXPを用いてのDynamixel Xシリーズの制御
OpenCM IDE、OpenCM 485 EXPを用いてのDynamixel Xシリーズの制御OpenCM IDE、OpenCM 485 EXPを用いてのDynamixel Xシリーズの制御
OpenCM IDE、OpenCM 485 EXPを用いてのDynamixel Xシリーズの制御
 
スタートアップ機能の等価回路モデル
スタートアップ機能の等価回路モデルスタートアップ機能の等価回路モデル
スタートアップ機能の等価回路モデル
 
StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件
 
OPcache の最適化器の今
OPcache の最適化器の今OPcache の最適化器の今
OPcache の最適化器の今
 
競プロでGo!
競プロでGo!競プロでGo!
競プロでGo!
 
Zynq VIPを利用したテストベンチ
Zynq VIPを利用したテストベンチZynq VIPを利用したテストベンチ
Zynq VIPを利用したテストベンチ
 
libcのputcharについて
libcのputcharについてlibcのputcharについて
libcのputcharについて
 
php-src の歩き方
php-src の歩き方php-src の歩き方
php-src の歩き方
 
ZynqMPのQEMU
ZynqMPのQEMUZynqMPのQEMU
ZynqMPのQEMU
 
Boost.Coroutine
Boost.CoroutineBoost.Coroutine
Boost.Coroutine
 
Kiso sekkei 01rev03
Kiso sekkei 01rev03Kiso sekkei 01rev03
Kiso sekkei 01rev03
 
cdev_write and_comwrite
cdev_write and_comwritecdev_write and_comwrite
cdev_write and_comwrite
 
ZynqMPのブートとパワーマネージメント : (ZynqMP Boot and Power Management)
ZynqMPのブートとパワーマネージメント : (ZynqMP Boot and Power Management)ZynqMPのブートとパワーマネージメント : (ZynqMP Boot and Power Management)
ZynqMPのブートとパワーマネージメント : (ZynqMP Boot and Power Management)
 
PHP AST 徹底解説
PHP AST 徹底解説PHP AST 徹底解説
PHP AST 徹底解説
 
VerilatorとSystemC
VerilatorとSystemCVerilatorとSystemC
VerilatorとSystemC
 
コルーチンの使い方
コルーチンの使い方コルーチンの使い方
コルーチンの使い方
 
Rtミドルウェア講習会 第3部資料 配布版
Rtミドルウェア講習会 第3部資料 配布版Rtミドルウェア講習会 第3部資料 配布版
Rtミドルウェア講習会 第3部資料 配布版
 
130711 01
130711 01130711 01
130711 01
 
4章 Linuxカーネル - 割り込み・例外 3
4章 Linuxカーネル - 割り込み・例外 34章 Linuxカーネル - 割り込み・例外 3
4章 Linuxカーネル - 割り込み・例外 3
 
発表資料 Fortranを用いた高位合成技術FortRockの開発
発表資料 Fortranを用いた高位合成技術FortRockの開発発表資料 Fortranを用いた高位合成技術FortRockの開発
発表資料 Fortranを用いた高位合成技術FortRockの開発
 

Similar to Stellaris を使った組み込みアプリ開発ガイド

リアルタイムOsのカスタマイズ
リアルタイムOsのカスタマイズリアルタイムOsのカスタマイズ
リアルタイムOsのカスタマイズKazuhiro Takahashi
 
Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputingNoboru Irieda
 
C base design methodology with s dx and xilinx ml
C base design methodology with s dx and xilinx ml C base design methodology with s dx and xilinx ml
C base design methodology with s dx and xilinx ml ssuser3a4b8c
 
コンテナセキュリティにおける権限制御(OCHaCafe5 #3 Kubernetes のセキュリティ 発表資料)
コンテナセキュリティにおける権限制御(OCHaCafe5 #3 Kubernetes のセキュリティ 発表資料)コンテナセキュリティにおける権限制御(OCHaCafe5 #3 Kubernetes のセキュリティ 発表資料)
コンテナセキュリティにおける権限制御(OCHaCafe5 #3 Kubernetes のセキュリティ 発表資料)NTT DATA Technology & Innovation
 
20130329 rtm3
20130329 rtm320130329 rtm3
20130329 rtm3openrtm
 
Dbts2013 特濃jpoug log_file_sync
Dbts2013 特濃jpoug log_file_syncDbts2013 特濃jpoug log_file_sync
Dbts2013 特濃jpoug log_file_syncKoji Shinkubo
 
130522 01
130522 01130522 01
130522 01openrtm
 
RTミドルウエア講習会2015
RTミドルウエア講習会2015RTミドルウエア講習会2015
RTミドルウエア講習会2015Yuki Suga
 
20130329 rtm2
20130329 rtm220130329 rtm2
20130329 rtm2openrtm
 
Android デバッグ小ネタ
Android デバッグ小ネタAndroid デバッグ小ネタ
Android デバッグ小ネタl_b__
 
201110 01 Polytech Center 1
201110 01 Polytech Center 1201110 01 Polytech Center 1
201110 01 Polytech Center 1openrtm
 
ET2016 組込みシステムに適した コンポーネントシステムTECSの最新状況
ET2016 組込みシステムに適したコンポーネントシステムTECSの最新状況ET2016 組込みシステムに適したコンポーネントシステムTECSの最新状況
ET2016 組込みシステムに適した コンポーネントシステムTECSの最新状況Takuya Azumi
 
130522 rt講習会(説明用)
130522 rt講習会(説明用)130522 rt講習会(説明用)
130522 rt講習会(説明用)openrtm
 
1.コース概要
1.コース概要1.コース概要
1.コース概要openrtm
 
Polyphony の行く末(2018/3/3)
Polyphony の行く末(2018/3/3)Polyphony の行く末(2018/3/3)
Polyphony の行く末(2018/3/3)ryos36
 
PBL1-v1-008j.pptx
PBL1-v1-008j.pptxPBL1-v1-008j.pptx
PBL1-v1-008j.pptxNAIST
 
Nedo講座・rtmセミナー
Nedo講座・rtmセミナーNedo講座・rtmセミナー
Nedo講座・rtmセミナーopenrtm
 

Similar to Stellaris を使った組み込みアプリ開発ガイド (20)

Minix smp
Minix smpMinix smp
Minix smp
 
リアルタイムOsのカスタマイズ
リアルタイムOsのカスタマイズリアルタイムOsのカスタマイズ
リアルタイムOsのカスタマイズ
 
Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputing
 
C base design methodology with s dx and xilinx ml
C base design methodology with s dx and xilinx ml C base design methodology with s dx and xilinx ml
C base design methodology with s dx and xilinx ml
 
コンテナセキュリティにおける権限制御(OCHaCafe5 #3 Kubernetes のセキュリティ 発表資料)
コンテナセキュリティにおける権限制御(OCHaCafe5 #3 Kubernetes のセキュリティ 発表資料)コンテナセキュリティにおける権限制御(OCHaCafe5 #3 Kubernetes のセキュリティ 発表資料)
コンテナセキュリティにおける権限制御(OCHaCafe5 #3 Kubernetes のセキュリティ 発表資料)
 
20130329 rtm3
20130329 rtm320130329 rtm3
20130329 rtm3
 
Reconf_201409
Reconf_201409Reconf_201409
Reconf_201409
 
Interrupts on xv6
Interrupts on xv6Interrupts on xv6
Interrupts on xv6
 
Dbts2013 特濃jpoug log_file_sync
Dbts2013 特濃jpoug log_file_syncDbts2013 特濃jpoug log_file_sync
Dbts2013 特濃jpoug log_file_sync
 
130522 01
130522 01130522 01
130522 01
 
RTミドルウエア講習会2015
RTミドルウエア講習会2015RTミドルウエア講習会2015
RTミドルウエア講習会2015
 
20130329 rtm2
20130329 rtm220130329 rtm2
20130329 rtm2
 
Android デバッグ小ネタ
Android デバッグ小ネタAndroid デバッグ小ネタ
Android デバッグ小ネタ
 
201110 01 Polytech Center 1
201110 01 Polytech Center 1201110 01 Polytech Center 1
201110 01 Polytech Center 1
 
ET2016 組込みシステムに適した コンポーネントシステムTECSの最新状況
ET2016 組込みシステムに適したコンポーネントシステムTECSの最新状況ET2016 組込みシステムに適したコンポーネントシステムTECSの最新状況
ET2016 組込みシステムに適した コンポーネントシステムTECSの最新状況
 
130522 rt講習会(説明用)
130522 rt講習会(説明用)130522 rt講習会(説明用)
130522 rt講習会(説明用)
 
1.コース概要
1.コース概要1.コース概要
1.コース概要
 
Polyphony の行く末(2018/3/3)
Polyphony の行く末(2018/3/3)Polyphony の行く末(2018/3/3)
Polyphony の行く末(2018/3/3)
 
PBL1-v1-008j.pptx
PBL1-v1-008j.pptxPBL1-v1-008j.pptx
PBL1-v1-008j.pptx
 
Nedo講座・rtmセミナー
Nedo講座・rtmセミナーNedo講座・rtmセミナー
Nedo講座・rtmセミナー
 

More from ryos36

Pycairo を使ってみる その1
Pycairo を使ってみる その1Pycairo を使ってみる その1
Pycairo を使ってみる その1ryos36
 
ストーリーとは
ストーリーとはストーリーとは
ストーリーとはryos36
 
CNN でテニス選手の動きを解析する
CNN でテニス選手の動きを解析するCNN でテニス選手の動きを解析する
CNN でテニス選手の動きを解析するryos36
 
Polyphony の並列化
Polyphony の並列化Polyphony の並列化
Polyphony の並列化ryos36
 
Polyphony 新機能ツアー
Polyphony 新機能ツアーPolyphony 新機能ツアー
Polyphony 新機能ツアーryos36
 
Polyphony: Python ではじめる FPGA
Polyphony: Python ではじめる FPGAPolyphony: Python ではじめる FPGA
Polyphony: Python ではじめる FPGAryos36
 
研究者のための Python による FPGA 入門
研究者のための Python による FPGA 入門研究者のための Python による FPGA 入門
研究者のための Python による FPGA 入門ryos36
 
数値計算のための Python + FPGA
数値計算のための Python + FPGA数値計算のための Python + FPGA
数値計算のための Python + FPGAryos36
 
Polyphony IO まとめ
Polyphony IO まとめPolyphony IO まとめ
Polyphony IO まとめryos36
 
PYNQ 祭り: Pmod のプログラミング
PYNQ 祭り: Pmod のプログラミングPYNQ 祭り: Pmod のプログラミング
PYNQ 祭り: Pmod のプログラミングryos36
 
SDSoC でストリーム
SDSoC でストリームSDSoC でストリーム
SDSoC でストリームryos36
 
Analog Devices の IP コアを使う
Analog Devices の IP コアを使うAnalog Devices の IP コアを使う
Analog Devices の IP コアを使うryos36
 
SDSoC と Vivado
SDSoC と VivadoSDSoC と Vivado
SDSoC と Vivadoryos36
 
高速化のポイント
高速化のポイント高速化のポイント
高速化のポイントryos36
 
20周遅れ
20周遅れ20周遅れ
20周遅れryos36
 
90分 Scheme to C(勝手に抄訳版)
90分 Scheme to C(勝手に抄訳版)90分 Scheme to C(勝手に抄訳版)
90分 Scheme to C(勝手に抄訳版)ryos36
 
並列計算への道 2015年版
並列計算への道 2015年版並列計算への道 2015年版
並列計算への道 2015年版ryos36
 
NiosII と RTOS について
NiosII と RTOS についてNiosII と RTOS について
NiosII と RTOS についてryos36
 
Synthesijer で作るFORTH仮想マシン
Synthesijer で作るFORTH仮想マシンSynthesijer で作るFORTH仮想マシン
Synthesijer で作るFORTH仮想マシンryos36
 

More from ryos36 (19)

Pycairo を使ってみる その1
Pycairo を使ってみる その1Pycairo を使ってみる その1
Pycairo を使ってみる その1
 
ストーリーとは
ストーリーとはストーリーとは
ストーリーとは
 
CNN でテニス選手の動きを解析する
CNN でテニス選手の動きを解析するCNN でテニス選手の動きを解析する
CNN でテニス選手の動きを解析する
 
Polyphony の並列化
Polyphony の並列化Polyphony の並列化
Polyphony の並列化
 
Polyphony 新機能ツアー
Polyphony 新機能ツアーPolyphony 新機能ツアー
Polyphony 新機能ツアー
 
Polyphony: Python ではじめる FPGA
Polyphony: Python ではじめる FPGAPolyphony: Python ではじめる FPGA
Polyphony: Python ではじめる FPGA
 
研究者のための Python による FPGA 入門
研究者のための Python による FPGA 入門研究者のための Python による FPGA 入門
研究者のための Python による FPGA 入門
 
数値計算のための Python + FPGA
数値計算のための Python + FPGA数値計算のための Python + FPGA
数値計算のための Python + FPGA
 
Polyphony IO まとめ
Polyphony IO まとめPolyphony IO まとめ
Polyphony IO まとめ
 
PYNQ 祭り: Pmod のプログラミング
PYNQ 祭り: Pmod のプログラミングPYNQ 祭り: Pmod のプログラミング
PYNQ 祭り: Pmod のプログラミング
 
SDSoC でストリーム
SDSoC でストリームSDSoC でストリーム
SDSoC でストリーム
 
Analog Devices の IP コアを使う
Analog Devices の IP コアを使うAnalog Devices の IP コアを使う
Analog Devices の IP コアを使う
 
SDSoC と Vivado
SDSoC と VivadoSDSoC と Vivado
SDSoC と Vivado
 
高速化のポイント
高速化のポイント高速化のポイント
高速化のポイント
 
20周遅れ
20周遅れ20周遅れ
20周遅れ
 
90分 Scheme to C(勝手に抄訳版)
90分 Scheme to C(勝手に抄訳版)90分 Scheme to C(勝手に抄訳版)
90分 Scheme to C(勝手に抄訳版)
 
並列計算への道 2015年版
並列計算への道 2015年版並列計算への道 2015年版
並列計算への道 2015年版
 
NiosII と RTOS について
NiosII と RTOS についてNiosII と RTOS について
NiosII と RTOS について
 
Synthesijer で作るFORTH仮想マシン
Synthesijer で作るFORTH仮想マシンSynthesijer で作るFORTH仮想マシン
Synthesijer で作るFORTH仮想マシン
 

Stellaris を使った組み込みアプリ開発ガイド

Editor's Notes

  1. Stellaris の LM3S811 の仮想HWと実機の評価ボードを使い組み込みシステムを学びます。 基本的には仮想HWだけでよいように設計されています。 簡単なプログラムの作成 では本当に簡単なプログラムを書きます。ここでは、基本的な初期化を省いているので bss がクリアされません。Bss については詳しく言及しませんが、この初期化の部分は 組み込みシステムを扱ううえでポイントになるでしょう。 TOPPERS/ASP によるプログラムの実行 ではTOPPERS/ASP の概要をつかみます。プログラミングはしません。 iTRON などのOSをつかえば、先の bss などの問題はあまり気にしなくてもよくなります。 組み込みアプリケーション開発ガイド ではTOPPERS/ASP を使い iTRON の API や割り込みについて学びます。
  2. ここでは Stellaris をつかったごく簡単なプログラムを書く方法を学びます。これにより SystemC で記述した プログラムの確認をテストベンチではなく、実際のアプリケーションを開発することで可能とします。 作成されたプログラムは TLMu すなわち仮想HWでのみ実行可能です。
  3. 本来は ld スクリプトを書きますが、ここでは全部引数で与えてしまっています。
  4. TI のStellarisWareにはいくつかソースがあります。これは実機で動かすことが可能です。 さらに、UART や OLED のプログラムは SystemC でペリフェラルが用意されているので、仮想HWでも実行可能です。
  5. ここでは次のことを学びます。 単純なコンパイル・動作確認 TOPPERS/ASP の簡単なコンパイル・動作確認方法 仮想環境での実行 実機での実行
  6. Led をつけるためのプログラム。表示スライドにするとネタバレになります。
  7. Sw により Led をつけるためのプログラム。表示スライドにするとネタバレになります。
  8. タスクでそれぞれ、数を数えるプログラム
  9. Adc をつかった割り込みプログラム
  10. タイマーを使ったプログラム
  11. ここでは次のことを学びます。 LED を点灯させるための GPIO というペリフェラル GPIO の仕様書確認(Stellaris® LM3S811 Microcontroller Data Sheet) LED アクセスのソースを読む 実行 → ソース上には volatile がないので動かない volatile について volatile についてのソースの修正 コンパイル・動作確認 Stellaris の GPIO と PL061 との違い
  12. LED を点灯させるための GPIO というペリフェラルを学びます。 LED はひかるという意味においては豆電球と同じです。 +- の極性があります。 実際に点灯させようとすると抵抗が必要です。
  13. LM3S811 評価ボードではボード上に STATUS と書いてあるカ所に LED があります。
  14. LM3S811 の回路図の例を掲げます。 プログラマとしては回路図を読む必要は必ずしもありませんが、 ハードウェアの知識を得るためにも読めるようになっておいた方がよいでしょう。 この例では PC5/CCP1 につながっています。
  15. PC5/CCP1 は回路図上、LM3S811 という SoC(CPU) の 13番ピンにつながっています。 PC5 はいわゆる GPIO (General Purpose Input Output) です。 このように組み込みシステム用の SoC は GPIO の為のピンを持っていて、実際のペリフェラル(この場合は LED)とつながっています。
  16. 参考までに実際のチップの絵を掲げます。 しかし、実際には基板を設計するでもなければこんなところは見ないでしょう。
  17. Table 17.4 に表があります。 このように、実際のボードのユーザズマニュアルにあるデータからチップのデータシートを見ることで詳細の情報を得ることができます。 ソフトウェアの開発にはこのチップのデータシートの情報は欠かせません。
  18. 更に GPIO の仕様を確認します。通常はブロックダイアグラムとレジスタアクセスの情報を確認することでしょう。
  19. ブロックダイアグラムを掲げます。
  20. レジスタの情報の例を掲げます。
  21. ちょっと飛ばしすぎました。ここで整理しましょう。
  22. LED を光らせるためには該当するピンを GPIO として使用するように宣言(SoCに教えてあげる)ひつようがあります。 先ほどの例では 13番ピンが LED につながっていましたが SoC は知りません。 リセットして立ち上がった直後は誤動作しないようにハイインピーダンスあるいは入力になっています。 ハイインピーダンスであればつながっていないのと同じなので光ったりしません。その先にモータがついていてもまわりだすことはありません。 入力であれば 0 か 1 の入力があっても SoC は壊れることはないでしょう。 いずれにせよ SoC は何がつながっているかわからないというスタンスです。 そこで、GPIO として使いますよと SoC に教えてあげます。これで、以後 GPIO として動作します。 しかし、まだ SoC はつながっているのが Input なのか Output なのかはわかりません。 ですから、さらに、GPIO は Output として使いますよと SoC に教えてあげます。これで以後、この Output 用の GPIO として使えます。 なお、ハイインピーダンス状態や InputOutput として使うなどは SoC によって違います。 LM3S811 ではハイインピーダンスを調整するレジスタはないようです。(立ち上げ時は入力)
  23. 実際に LED を光らせる前に、該当するピンを GPIO として使用するように宣言するために、 特定のアドレスに値を書き込むのですが、 それらはStellarisWare の力を借りることにします。
  24. 実際に LED を光らせる前に、該当するピンを GPIO の Output として使用するように宣言するために、 特定のアドレスに値を書き込むのですが、 それらはStellarisWare の力を借りることにします。
  25. 実は仕様書が間違っているようです。次のスライドで修正します。
  26. 仕様書通りに動かすと動きません。0x3FC のオフセットが正解です。
  27. C で書くとこんな感じになるでしょうか? 種を明かすと、これでは動きません。 なお、この時点でPORT C 上の、他のピンはどうなるの?と考えた人は相当わかってます。 0x400063FC への書き込みは PORT C に関するすべてのピンに対して書き込みをします。 したがって、例えば 3 番に LED があり光っていたなら、上のプログラムでは消えてしまいます。 PL061 では個別にピンにアクセス可能なように、個々のピンに対してアドレスが異なるように 設計されています。 しかし、LM3S811 では PL061 の簡易版のようで、そのような機能はないようです。[仕様書に未記載) そのかわり、Cortex-M3 の機能である bit band を使用することができます。
  28. led.c は動かないプログラムになっていますが、まずは実行して動かないことを確認します。 プログラムは TOPPERS/ASP 上で動きます。 TOPPERS/ASP の方法でコンパイル・実行します。 そのため TOPPERS/ASP での実行コンパイルの経験が多少必要です。 ここでその経験をするのでもいいかもしれません。(プログラムが簡単なので) make 時には USE_QEMU=true とします。 asp ができます。 led と名前を変えておきます。
  29. 実機で実行するには make 時に何も指定しません。 led は elf 形式なので OpenOCD を使った場合そのままつかえます。 Windows で TI の LM Flah Programer をつかうなら objcopy で bin ファイルにしておきます。 以後、仮想HWでの実行のみを記述
  30. 判断はコンパイラ依存。
  31. 実際に volatile をつかってソースを修正し、実行してみる。
  32. HWREGBITW は bitband を使用する。 単純な HWREG でもよい。 今後は volatile をあまり意識せずに、便利な StellarisWare の機能を使う。
  33. 動くプログラムの確認として led-fix を試してみる。 for ( i = 0 ; i < 32; ++i ) { HWREGBITW(LED_GPIO_C_ADDR, i) = 1; str[5] = '0' + i / 10; str[6] = '0' + i % 10; Display96x16x1StringDraw(str, 0, 12); dly_tsk(300); } なお、プログラムは後半が BITBAND を使ったものになっている。
  34. LED と同様に SW
  35. 代替の仕様は回路図を見なくてもユーザズマニュアルで確認可能 回路図より簡単にわかる PC4 でわることがわかった。
  36. 実際に SW から情報をえる前に、該当するピンを GPIO として使用するように宣言するために、 特定のアドレスに値を書き込むのですが、 SL3S811 の場合は GPIO 単位での設定になり、しかも PORT C は LED と共通。
  37. 実際に SW から情報をえる前に、該当するピンを の Input として使用するように宣言するために、 特定のアドレスに値を書き込むのですが、 それらはStellarisWare の力を借りることにします。
  38. 実際にソースを修正して確認
  39. 修正済みのソースは led-sw-fix
  40. ここでは iTRON のタスクを使うことを考えます。
  41. 専念させることでモジュールわけし、設計がしやすくなります。 いろいろな意味で堅牢にもなるでしょう。
  42. .このリソースの書き方は TOPPERS/ASP 独特です。他の iTRON と共通するところも多くありますが、 あまり深入りはしません。
  43. 意図通りに動きません。これはタスクが切り替わらないためです。
  44. ここで動かない理由をソースを追って確かめます。 まずは #if0 を 1 にします。 そうすると表示がなされるので、動いていることがわかります。かつ g_flag の変更の様子もわかります。
  45. 一番簡単な方法は dly_tsk を入れることです。 ここでは意図的に 1秒待つようにしてみます。当然、1秒に一回のポーリングなので性能は出ません。 でも多くの iTRON 技術者がこの dly_tsk で“調整”してしまいます。 これはあまりスマートな方法とは言えません。
  46. Rot_rdq である程度解決するけど、無駄に タスクが回っていることを認識。 もし、他にタスクがあればその邪魔をすることに留意。
  47. 修正済みのソースは rod-rdq
  48. 小さい値のほうが priority が高い。 ただし、このようにすると act_tsk した瞬間に led_task に実行件が移り main_task には戻ってこない。 dly_tsk をいれて調整することは可能。 rod_rdq では調整できない。
  49. 実際にプログラムを変更するのは難しいかもしれない。
  50. 割り込みはもうちょい先
  51. 修正済みのソースは led-sw-sem 仮想 HW で遅い場合は dly_tsk を調整する。
  52. 専念させることでモジュールわけし、設計がしやすくなります。 いろいろな意味で堅牢にもなるでしょう。
  53. 仮想 HW で遅い場合は dly_tsk を調整する。
  54. 意図通りに動きません。理由は資源を共有しているのに排他制御をしていないからです。
  55. OLED の表示もいずれおかしくなります。これも資源競合が起こっているのに排他制御をしていないからです。 OLED の表示には一連の作業が必要です。その作業はアトミックに行われる必要があります。
  56. 修正済みのソースは task-count-fix 仮想 HW で遅い場合は dly_tsk を調整する。
  57. ADC を使った割り込みのシステムです。 いろいろやっていますが、その詳細には立ち入りません。 システムとしては、割り込みで adc で得られた情報を OLED に表示しています。 と同時に main_task でも OLED で表示しています。 ここで資源の競合が起きています。 なお、ソース上では adc_task とか g_flag とか次のステップで必要なものがすでに入ってます。 これを利用してソースを書き換えます。
  58. 美しくない理由は別途説明
  59. Adc-intr と書きつつまだこの時点では main_task しか動いていない。割り込みは上がらない。
  60. 仮想HW ではおこりにくいので dly_tsk の値を 0 とかにしてもいいかもしれない。
  61. OLED が競合するので表示がおかしくなります。 Task どうしの排他には wai_sem などがつかえますが、 割り込みには wai_sem が使えません。
  62. Adc_isr をコンパクトにして g_flag というグローバル変数で情報を adc_task に伝えます。 adc_task はコンテキストを保持可能なタスクなので wai_sem が使えます。
  63. ここでの dly_tsk は禁じ手ではない。表示するきっかけを持たないから。
  64. 修正済みのソースは adc-task 仮想 HW で遅い場合は dly_tsk を調整する。
  65. 美しくない理由は スタック消費量 排他が必要な資源へのアクセス 関数コールの先が不透明(wait するかもしれない) 処理が長い(割り込み中は他の処理ができないので割り込みは小さくすべき)
  66. おおむねシンプルになった。 基本的処理が2つになった - 割り込み要因のクリア -フラグの変更 フラグ変更がグローバル変数なので dly_tsk を読み取り側で必要とする。 (読み取り側でポーリングを必要とする)
  67. Adc_isr をコンパクトにして g_flag というグローバル変数で情報を adc_task に伝えます。 adc_task はコンテキストを保持可能なタスクなので wai_sem が使えます。
  68. 美しくない理由は スタック消費量 排他が必要な資源へのアクセス 関数コールの先が不透明(wait するかもしれない) 処理が長い(割り込み中は他の処理ができないので割り込みは小さくすべき)
  69. 美しくない理由は スタック消費量 排他が必要な資源へのアクセス 関数コールの先が不透明(wait するかもしれない) 処理が長い(割り込み中は他の処理ができないので割り込みは小さくすべき)
  70. 美しくない理由は スタック消費量 排他が必要な資源へのアクセス 関数コールの先が不透明(wait するかもしれない) 処理が長い(割り込み中は他の処理ができないので割り込みは小さくすべき)
  71. 修正済みのソースは adc-task-fix
  72. Timer0 と timer1 の割り込みを使い FLG で情報を伝達 Timer_task はその情報を表示する。
  73. メールボックスともいう。
  74. 出来ればソースレビューをした方がよい sw も追加した timer-sw-msg も用意した これを改造して sw_task を作るようにした方がよい