• 検索結果がありません。

1 機能概要 複数ペリフェラル ( デバイスと呼びます ) を並行動作させて その IO 完了などのイベントを1カ所で待ち合わせて イベントドリブン処理を可能にします イベントは16 個を扱えます シーケンス処理を組めるように 特定のイベントだけ選別して待ち合わせる機能があります 待ち合わせるときに

N/A
N/A
Protected

Academic year: 2021

シェア "1 機能概要 複数ペリフェラル ( デバイスと呼びます ) を並行動作させて その IO 完了などのイベントを1カ所で待ち合わせて イベントドリブン処理を可能にします イベントは16 個を扱えます シーケンス処理を組めるように 特定のイベントだけ選別して待ち合わせる機能があります 待ち合わせるときに"

Copied!
7
0
0

読み込み中.... (全文を見る)

全文

(1)

1

MSP430 複数ペリフェラルを並行動作させる方式 [ マルチ IO システム ]

Version3.0 2014.11.26 PIC 山内 一男

この方式では、複数の IO 処理を並行して実行できますので、MSP430 を幅広く利用できます。 OS を使用せずに、複数ペリフェラルを並行動作させて、IO 完了やソフトイベントなどを複数管理して通知することができま す。 これにより、イベントドリブン型の並行処理システムを構築できます。 この方式のライブラリ自体は、デバイスシリーズに依存していません。 ドライバーと ISR に特別なマクロコールを組み込んで ライブラリと連携して実現します。 ドライバーと ISR はデバイスシリーズに依存します。 現在は、MSP430G2553 と MSP430FR5969 に実装してあります。 別途マルチ IO システムとして example を提供 いたします。

内容

1 機能概要 ... 2 1.1 従来方式との違い、改善点 ... 2 2 方式概要 ... 2

2.1 イベント定義テーブル ( the table of events ) ... 3

2.2 IO 制御テーブル (The common table for IO control) ... 3

2.2.1 IO 制御テーブルにアクセスするマクロ ... 3

2.2.2 LPM mode control ... 4

2.2.3 IO status and IO completed ... 4

2.3 Event Manager の動作 ... 4 2.4 Event Manager の関数例 ... 4 3 ドライバーと ISR へのインプリメント ... 5 3.1 ドライバー ... 5 3.2 ISR ... 5 4 アプリケーションでのイベント処理例 ... 5 4.1 イベント ハンドリング ... 5 4.2 リトライ例 ... 7

(2)

2

1 機能概要

複数ペリフェラル(デバイスと呼びます)を並行動作させて、その IO 完了などのイベントを1カ所で待ち合わせて、イベ ントドリブン処理を可能にします。 イベントは16個を扱えます。  シーケンス処理を組めるように、特定のイベントだけ選別して待ち合わせる機能があります。 待ち合わせるときに、適切な LPM0、LPM3、LPM4 を選んで wait します。 delay イベントを起こすことで、タイムアウト監視やリトライが可能です。

1.1 従来方式との違い、改善点

複数のデバイスを動作させたとき、従来の __bis_SR_register(LPMx_bits+GIE); で待ち合わせる方法は、  wait が解除されたのはどのデバイスが完了したのか判断ができません。  LPM0/LPM3/LPM4 どれで待つかはアプリケーションが適切に判断する必要があります。

 ISR が先に wait 解除し、アプリケーションが後から wait するクロス状態が起きると、永遠に wait することになります。 今回提案する方式は、ドライバーと ISR に所定の手続きを追加することで、  複数のペリフェラル IO の待ち合わせを可能にします。  複数同時の IO 完了もIOctl領域の bit にプールされますので、取りこぼしがありません。  ISR の wait 解除とアプリケーションの IO 完了のタイミングが、クロスしても正常に判定できます。  特定のペリフェラル IO 完了だけ選別することができますので、A->B->C のように IO 完了をシーケンスに組むこともで きます。  ドライバーが必要な LPMx を設定しますので、アプリケーションは LPM 制御の意識が不要になります。

2 方式概要

下記の構成要素が連携して動作します。

(3)

3

driver(デバイスに必要な初期設定をして ISR を呼ぶもの)と ISR は、IO 情報を IOctl に書き込んで、wait と event を管理する event manager と相互連携して動きます。

AP は、IO 要求(サイズ、バッファアドレス)を IO_req にセットして、driver を呼びます。

driver は device に必要な設定をして IO を開始します。 ISR は device からの割り込みを処理して、IO 完了した ら AP を active にします。

driver と ISR は、IO 情報を IOctl に書き込んで、event manager に通知します。 event manager は IO 中 の LPMx wait の制御と、AP へ IO 完了の device_ID を通知します。

2.1 イベント定義テーブル ( the table of events )

 IO 要求や完了などのイベントは device ID で識別します。 これは、ユーザが再定義可能です。  イベントは下記のように bit 対応で定義します。 max16 個です。 “Driver.h”で定義します。

/* ======== device ID(uint16_t), user need to define ============== */ // the fixed ID

#define Interval 0x01 // interval timer, timerA1

#define DelayMs 0x02 // for delay_ms, ACLK(LPM3)-> WDT // user need to define following IDs

#define Timer0 0x04 // ACLK,LPM3

//#define Timer1 0x08 // SMCLK,LPM0

#define SPI4 0x20 // SMCLK,LPM0 rev2.0

#define ADC 0x40 // ADC

#define UartA0 0x80 // SMCLK,LPM0

#define PIO1 0x0100 // Port 1,LPM4

#define PIO2 0x0200 // 2

#define PIO3 0x0400 // 3

#define PIO4 0x0800 // 4

2.2 IO 制御テーブル (The common table for IO control)

 下記の構造体が Driver.h で定義されており、実体は IOctl_driver.c にあります。  driver と ISR がこのテーブルの device ID に該当する bit を on/off して制御します。

// common control structure for drivers and check_IOwait() struct IO_ctl {

uint16_t Rq_LPM0; // requested LPM0

uint16_t Rq_LPM3; // LPM3

uint16_t St_busy; // under IO executing

uint16_t St_endMK; // IO end mark

};

extern struct IO_ctl IOctl; // defined in IOctl_driver.c

2.2.1 IO 制御テーブルにアクセスするマクロ

アクセスの間違い防止と拡張性のため、下記のようなマクロを DriverG.h に用意してあります。 ドライバーと ISR はこのマ クロを使用して、IOctl table にアクセスします。 dev は device ID を表します。

例 IOctl_start(UartA0);

/* --- Macro define --- */

(4)

4

#define IOctl_LPM0off(dev) IOctl.Rq_LPM0 &= ~dev

#define IOctl_LPM3on(dev) IOctl.Rq_LPM3 |= dev

#define IOctl_LPM3off(dev) IOctl.Rq_LPM3 &= ~dev

#define IOctl_start(dev) IOctl.St_busy |=dev; IOctl.St_endMK &= ~dev;

#define IOctl_stop(dev) IOctl.St_busy &=~dev; IOctl.St_endMK |= dev;

2.2.2 LPM mode control

LPM0 の wait を必要なデバイスは、Rq_LPM0 の対応 bit を on にします。 IO 完了で off します。 LPM3 の wait を必要なデバイスは、Rq_LPM3 の対応 bit を on にします。 IO 完了で off します。 Event Manager は、wait するとき Rq_LPM0 と Rq_LPM3 を見て LPMx を判断して wait します。

2.2.3 IO status and IO completed

driver は、IO 開始するとき St_busy の device ID bit を on します。 IO 中か否かの識別に使います。 ISR は IO 完了(IO_completed)のとき、St_endMK の該当 bit を on にして、Active mode に復帰します。 この後、event manager が wake-up して、St_endMK: on の device ID を event として AP に返します。

2.3 Event Manager の動作

アプリケーションは、 __bis_SR_register(LPM0_bits+GIE); の代わりに Check_IOwait(); で IO 完了を待ちます。

 event manager は、IO 完了デバイスを IOctl の St_endMK(LSB first)の on bit を探して見つけだし、その device ID(uint16_t)を返します。 その時 St_endMK の device ID の bit は off します。

複数 IO 完了しているときは、この IOctl:St_endMK にプールされていますので、Check_IOwait();を呼ぶこと で順次処理することができます。

 もし IO 完了しているものがなければ(St_endMK=0)、Rq_LPM0、Rq_LPM3 の bit が on の device がある 場合は、LPM0(優先)か LPM3 で、無ければ LPM4 で wait します。

2.4 Event Manager の関数例

1) uint16_t Check_IOwait(uint8_t wait_type)

戻り値 dv_id IO 完了したデバイス識別子(Device ID)が戻ります。 wait_type: IOnowait wait しません、IO 完了なしは dv_id=0 で戻ります。

IOwait wait します、タイムアウトなしです。 2) uint16_t Check_onlyDEV(uint16_t dv_id, uint8_t wait_type)

(5)

5

3 ドライバーと ISR へのインプリメント

この方式では、ドライバーと ISR は IOctl を制御する所定の手続きの追加が必要です。

3.1 ドライバー

 ドライバーは、wait するときに必要な LPM0/LPM3 を設定し、IO の開始を設定します。 下記2行追加します。 IOctl_LPM3on(UartA0); IOctl_start(UartA0);

3.2 ISR

ISR は、IO 完了時には LPMx 解除と IO 終了を設定して、active に復帰します。 IOctl_LPM3off(UartA0);

IOctl_stop(UartA0);

__bic_SR_register_on_exit(LPM_all); LPM_all = LPM4_bits+GIE

 ISR は IO_req の U_status にエラー情報や IO 情報を返すことができます。 下記は timer が割り込み CCR 種 別を返す例です。 また、timer のように連続動作しながら、CCR 割り込みを通知する場合は、IOctl_stop(dev) ではなく IOctl_Mark_end(dev)により割り込みイベントの通知だけをすることができます。

switch ( _even_in_range( TA1IV, 0x0A) ){

case 0x02: // CCR1

P_tm1->U_status = 0x02; // CCR1 interrupt

break;

case 0x0A: // TAIFG

P_tm1->U_status = 0x01; break; default: break; } IOctl_Mark_end(Timer1);

__bic_SR_register_on_exit(LPM_all); // set active

4 アプリケーションでのイベント処理例

4.1 イベント ハンドリング

下記は、SPI スレーブのイベントドリブン処理の抜粋です。 前半 while までは、必要なデバイス(PIO、ADC、Timer0、SPI)の IO を開始しています。 while{}の中で各イベントの処理をしています。 switch(Dev_ID){}部分で、イベント(Dev_ID=PIO1、 ADC、SPI4)を case に区分して、個別の処理をしています。 // enable interrupt of P1.3, SW2

PIOx_IntEnable_HtoL( Pio1, &SW_req ); Interval_set( &Interval_req );

(6)

6 // get my temperature TLV data

ADCtemp_getTLV( ADC_data ); ADCtemp_start( );

ADCtemp_IO_NoWait( &IO_ADC ); // enable ADC timerA0_IO_NoWait( &IO_timer0 ); // timer0 trigger ADC /* --- waiting event, endless loop --- */

/* exit by SPI received start command, _cmd_Start */ while(1)

{

uint8_t text, status;

/* --- SPI transferring --- */ // sending RQSS if some messages leaved

SPI_receive();

Dev_ID = Check_IOwait( IOwait );

switch ( Dev_ID ) {

/* --- PIO1: SW2-> P1.3 interrupt --- */ case PIO1: // P1.3: SW2 interrupt

if( SW_req.U_status & SWbit )

{

LEDstatus ^= 0x00FF; // toggle

if( LEDstatus ) { P1OUT |= BIT0; } // LED on

else { P1OUT &= ~BIT0; }

// start interval to prevent from chattering of switchs Interval_CCRx_start( _ccr1 );

Mess_set_cmdDATA( s_ID, Pio_ID, &PIO_event ); // send PIO event

}

break;

case Interval: // protecting from chattering if( Interval_req.U_status == fg_CCR1 )

{

Interval_CCRx_stop( _ccr1 ); PIOx_ReEnable_HtoL ( Pio1, SWbit ); }

break;

/* --- ADC --- */ case ADC:

Mess_set_cmdDATA( s_ID, ADC_ID, &ADC_str ); // send ADC data ADCtemp_IO_NoWait( &IO_ADC ); // restart ADC break;

/* --- SPI4 --- */

case SPI4:

status = Mess_get_CMD( &R_mess ); SPIs_stop();

if ( status != IO_completed ) { // IO error

P1OUT |= BIT0; // LED on

}

else

{ // IO completed

Mess_release_BUF(); // releasing the used buffer

switch ( R_mess.M_cmd ) {

case _cmd_Start: // restart

goto Start;

case _cmd_PIO:

(7)

7 // LED on/off

if( LEDstatus ) P1OUT |= BIT0; // LED on

else P1OUT &= ~BIT0;

break;

case _cmd_Test: status = 0;

for(cnt=4; cnt< R_mess.size_DT; cnt++) {

text = rvBuf[cnt] +1;

if ( text != rvBuf[cnt+1] ) { status++; break; } }

if ( status ) Mess_set_CMD( s_ID, sdBuf_ID, &NAK_str );

else Mess_set_CMD( s_ID, sdBuf_ID, &ACK_str );

break;

default:

break;

} // end of SPI4 switch } break; default: break; } /* --- switch end --- */

4.2 リトライ例

IO エラーが起きた時など、リトライしたいときは下記ように関数を呼ぶと、5ms 後に DelayMs イベントを起こすことがで きます。 時間選択は Timer_driverG.h/Timer_driverFR.h に説明があります。 この関数は WDT をカウンタ モードで利用しています。 msDelay_NoWait( _V5ms ); 以 上

参照

関連したドキュメント

実際, クラス C の多様体については, ここでは 詳細には述べないが, 代数 reduction をはじめ類似のいくつかの方法を 組み合わせてその構造を組織的に研究することができる

のようにすべきだと考えていますか。 やっと開通します。長野、太田地区方面  

Jabra Talk 15 SE の操作は簡単です。ボタンを押す時間の長さ により、ヘッドセットの [ 応答 / 終了 ] ボタンはさまざまな機

点から見たときに、 債務者に、 複数債権者の有する債権額を考慮することなく弁済することを可能にしているものとしては、

自分は超能力を持っていて他人の行動を左右で きると信じている。そして、例えば、たまたま

、肩 かた 深 ふかさ を掛け合わせて、ある定数で 割り、積石数を算出する近似計算法が 使われるようになりました。この定数は船

この P 1 P 2 を抵抗板の動きにより測定し、その動きをマグネットを通して指針の動きにし、流

当社は違法の接待は提供しません。また、相手の政府