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

MSP430 メッセージマネージャ Ver3 Version /12/24 PIC 山内一男 この資料は 1 複数 IOの管理方式 Ver3 2 MSP430 SPIマルチスレーブ システムVer3 3 MSP430 メッセージマネージャVer3 4 ExampleプロジェクトVer

N/A
N/A
Protected

Academic year: 2021

シェア "MSP430 メッセージマネージャ Ver3 Version /12/24 PIC 山内一男 この資料は 1 複数 IOの管理方式 Ver3 2 MSP430 SPIマルチスレーブ システムVer3 3 MSP430 メッセージマネージャVer3 4 ExampleプロジェクトVer"

Copied!
7
0
0

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

全文

(1)

1

MSP430 メッセージマネージャ Ver3

Version 3.0 2014/12/24 PIC 山内 一男 この資料は 「① 複数IOの管理方式Ver3」、 「② MSP430 SPIマルチスレーブ・システムVer3」、 「③ MSP430 メッセージマネージャVer3」、「④ ExampleプロジェクトVer3」 とシリーズになっています。 先に①②を理解していただく必要があります。 本書は、SPIのマスターとマルチスレーブを接続して通信するときに、「メッセージ交換による情報伝達」をサポートするメッセ ージマネージャの機能と動作を説明するものです。 pointの語彙は赤文字にしてあります。 メッセージマネージャは、「処理速度が速いアプリケーション」が生成する送信メッセージを、「低速のSPI通信」で漏れなく情 報伝達できるよう、メッセージマネージャがバッファにプールして、相互のスループットの相違を吸収する役割を持ちます。 また、 SPI通信のパケット形式に合わせて、メッセージフォーマットを書き込み・読み出しする機能を持ちます。 内容 1 メッセージマネージャの概要 ...2 1.1 役割 ...2 1.2 機能概要 ...2 1.2.1 システム全体のブロック図 ...2 1.2.2 動作概要 ...2 1.2.3 バッファ管理 ...3 2 メッセージ ...3 2.1 メッセージのフォーマット ...3 2.2 メッセージエラーのチェック ...4 2.3 コマンド/アンサー ...4 3 API の概要 ...5 3.1 メッセージ構造体 ...5 3.1.1 送信メッセージの構造体 ...5 3.1.2 受信メッセージ構造体 ...5 3.2 メッセージ操作の関数 ...5 3.2.1 SPI IO 構造体を登録 ...5 3.2.2 送信バッファの登録 ...6 3.2.3 送信メッセージの書き込み ...6 3.2.4 送信メッセージの取り出しと buffer 解放 ...6 3.2.5 受信したコマンド/アンサーと data の取り出し ...6 3.2.6 コーリングシーケンス ...6 4 コマンド/アンサーの処理例 ...7

(2)

2

1 メッセージマネージャの概要

1.1 役割  瞬間的な送信メッセージのトラフィック増加をバッファリングして、低速の SPI 通信で漏れなくメッセージを送信できるように することが message manager の重要な機能です。  例えば、timer から定期イベントが起きて、これを 6 台のスレーブに通知しようとすると、瞬時に6個の送信メッセージが 生成されます。 SPI 通信でこれを全て配信するには時間がかかりますし、その間にも別の送信メッセージが生成される ケースもあります。 つまりアプリケーションと SPI 通信のスループットの相違を吸収する役割を持ちます。  一方、受信メッセージは即座に処理する方式をとっていますので、バッファリングはしていません。  また、アプリケーションが扱うメッセージを、所定のフォーマットに変換して SPI パケットに格納する/取り出すことを、容易に できるようにサポートします。 これにより、アプリケーションが、直接 SPI 通信の構文やバッファ内の配置を意識せずに、メ ッセージを扱えるようになります。 1.2 機能概要 1.2.1 システム全体のブロック図  システム全体の構成要素・階層構造は Figure 1 になります。  アプリケーションが、event 処理や SPI 通信のフローを制御します。 処理フローの説明は後述します。  アプリケーションは、送信メッセージをbufferに入れて、message managerがこれをプールします。  SPI 通信するときは、message manager から一つ buffer を取り出し、これをsend bufferとします。

receive buffer も用意して、これらを IO request 構造体に set して SPI driver に渡します。  SPI 通信の完了は、event manager からアプリケーションに、IO 完了のeventとして通知されます。

Figure 1 Block diagram 1.2.2 動作概要

 アプリケーションは、下記①~⑤を endless loop で処理します。 ① アプリケーションは、常にevent待ちをする

(3)

3

② SPI 通信完了のeventが起きた時は、受信したメッセージを処理する

③ 他の master/slave に通知する event が起きた時は、送信メッセージを buffer に格納して、message manager に渡してプールしてもらう

④ 1つの event 処理が完了したら、message manager から次の送信メッセージを一つ取出す、 送信メッセージがない時は①に戻る

⑤ 送信メッセージの入った buffer をsend bufferとし、べつにreceive bufferも用意して、SPI 通信の driver をコールして①に戻る

 SPI 通信の完了も event ですので、①~⑤を繰り返すことで、プールされていた送信メッセージは処理されます。  example プロジェクトの master は、SPI 通信を優先するために、message manager にプールされている送信メッ

セージがなくなるまで、SPI 通信を続けます。 その間に起きる event は、message manager がプールしていますので、 event の取りこぼしは起きません。

1.2.3 バッファ管理

 アプリケーションは複数のbufferを確保して、これらのアドレスを、事前にmessage managerに登録します。 masterでは、全てのslaveに配信するケースが有るので、slave台数分のバッファが必要になります。

slaveでは、同時発生する可能性のあるevent数分のバッファが必要になります。

message managerは、登録されたbufferID (ハンドル:0~n)をつけて、これをアプリケーションに返します。 デフォルトでは6個(変更可能)まで管理できます。

 アプリケーションが、送信メッセージをmessage managerに格納する/取り出すときは、IDでアクセスできます。

ID=free(未指定)にすると、空いているbufferに順に格納し、あるいは順番にbufferからメッセージを取り出します。 バッファの空がなく格納できないとき、格納済みメッセージがなく取り出しできないときは、errorが返ります。

message managerは、それぞれのbufferに対して、メッセージ格納済み(送信要求flag on)か、取り出し済み で空いているか(送信要求flag off)の管理をします。

ただし、FIFO管理はオーバヘッドが大きいので、ID(0優先)の順でアクセス管理しています。

2 メッセージ

2.1 メッセージのフォーマット

送信メッセージは、下記のヘッダーをつけて、SPI パケットに書き込み、master と slave 間でメッセージを交換します。 word(16bits)は、リトルエンディアンの2byte に変換されます。

① メッセージフォーマット(byte単位:uint8_t/char)

size(n), s-ID, cmd1,cmd2, data1, data2, ...., data(n-5), endマーク ② header:size(1byte)、s-ID (1byte)、cmd1+cmd2(2byte)

size : パケット長、sizeを含めたバイト長 ・・ SPIパケットと同じもの

s-ID : slave-ID、masterは通信先slaveを指定、slaveは自分のIDを指定 (最初にmasterが送ったIDを、slaveは自分のIDとして記録) cmd1+cmd2 : コマンド/アンサー:word(uint16_t)

endマーク(1byte) : 終了記号 “]” ③ data

(4)

4 2.2 メッセージのエラーチェック  受信したメッセージのsizeで指定された最後のbyteが、endマークか判定されます。 これでbyte落ちやbitズレの有無 をチェックします。  masterは、size=0の受信メッセージは、slaveが無応答と判断します。 2.3 コマンド/アンサー

 master が slave に送るのをコマンド、slave が master に送るのをアンサーと呼び、文字 code を区分しています。  事前に、master と slave のアプリケーションは、コマンド/アンサーとそれに対応する処理、data 内容を取り決めます。

ここは、アプリケーションの処理とロジックに直接ディペンドします。

コマンド/アンサーの送信側は、下記のような指示やデータ種別を伝えて処理依頼します。 master ・・ test コード送信、再スタート指示

slave ・・ test 結果報告、ADC 測定データ通知、LED 情報(on/off)通知

 コマンド/アンサーの受信側は、このコマンド/アンサーの種別を判別して、必要な動作とdata処理をします。 SPI通信では、送信と受信を同時に行います。 ですからマスターの指示コマンドに対し、スレーブからの結果アンサーは 次以降の通信で返事が帰ってくることになります。 つまり、受信したコマンド/アンサー(_cmd_xxx/_ans_xxx)の 識別をして処理をする必要があります。  マスターは_cmd_xxx(x:大文字)、 スレーブは_ans_xxx(x:小文字)で識別できるようにしてあります。 デモexampleのMessage_manager.hでは下記のような定義をしてあります。 最後の_Nopは、送信メッセージがないことを表します。

/* --- SPI message table of command and answer --- */ // command: master -> slave

#define _cmd_Start 0x5354 // "ST", restart

#define _cmd_Sleep 0x534C // "SL", request to sleep

#define _cmd_Report 0x5250 // "RP", request reports about error

#define _cmd_Test 0x5454 // "TT", send test data

#define _cmd_Query 0x5155 // "QU", query a slave

#define _cmd_ADC 0x4144 // "AD", request ADC data

#define _cmd_PIO 0x5049 // "PI", PIO status notice // answer: slave -> master

#define _ans_Restart 0x7374 // "st", restart

#define _ans_Nak 0x6E6B // "nk", NAK, command error

#define _ans_Busy 0x6273 // "bs", Busy

#define _ans_Report 0x7270 // "rp", reply about transfer error

#define _ans_TestACK 0x7441 // "tA", reply ACK for test data

#define _ans_TestNAK 0x744E // "tN", reply NAK for test data

#define _ans_ADC 0x6164 // "ad", send ADC data

#define _ans_PIO 0x7069 // "pi", PIO status notice // No answer, NOP

(5)

5

3 API の概要

 アプリケーションがメッセージを扱うときに使う、メッセージ構造体と関数について、概要を説明します。  exampleプロジェクト(zip)のMessage_manager.hに、使用する構造体とAPI、コーリングシーケンスの説明があ ります。 3.1 メッセージ構造体  アプリケーションは構造体を使って、送信メッセージをbufferへ書き、receive bufferからメッセージを取り出します。 構造体を使うことで、アプリケーションはdataの処理に専念できます。 3.1.1 送信メッセージの構造体  コマンド/アンサーのみでdataなしのコマンド構造体と、data付きのデータ構造体が有ります。

構造体部分は const で確保し、data部のみ変数/配列に配置ができます。 これでRAMの節約ができます。 1) コマンド構造体

 コマンド構造体は、パケットサイズ(byte)とコマンド/アンサー(2byte)を定義します。  下記例は、masterが送る「再スタート要求」のコマンド構造体です。

#define M_header 5

const struct Mess_CMD _start = { M_header, _cmd_Start }; { パケットサイズ(byte)、 コマンド } 2) データ構造体

データ構造体は、コマンド構造体に、データサイズ(byte数)とデータpointer(uint16_t *)を付加したものです。 MSP430はリトルエンディアンなので、word dataは、low byte, High byte の順でバッファに格納されます。  下記は、slaveが送るADC測定データ通知のデータ構造体です。

#define ADC_num 3

uint16_t ADC_data[ADC_num+2]; // TLV1,TLV2,adc1,adc2,adc3 // ADC answer message

const struct Mess_DATA ADC_str

= { { M_header+(ADC_num+2)*2, _ans_ADC }, (ADC_num+2)*2, ADC_data }; {{ コマンド構造体: パケットサイズ(byte) アンサー} dataサイズ(byte) 配列アドレス } 3.1.2 受信メッセージ構造体

 受信したSPIパケットから、コマンド/アンサー(M_cmd)、データサイズ(byte)とslave_IDの取り出しを指定します。  dataの取り出しは、別の関数コールで行います。

struct Mess_RECV { uint16_t M_cmd; uint8_t size_DT; uint8_t *P_sID; }; P_sID :masterでは、slaveから受信したslave_IDが格納されます。

slaveでは、masterから指定されたslave_IDが格納されます。 3.2 メッセージ操作の関数

主要な関数の仕様を説明します。 具体的な利用法はexampleプロジェクト(zip)で確認お願いします。 3.2.1 SPI IO 構造体を登録

void Mess_config( struct IO_req2Buf *SPI_req );

 message managerを初期化して、使用するSPI IO構造体(SPI_req)とリンクします。

(6)

6

れると、massage managerがプールされているbufferを取り出し、それをsend bufferアドレスと設定します。 3.2.2 送信バッファの登録

uint8_t Mess_set_BUF( uint8_t *buffer );

使用する送信bufferを登録します。 登録順で優先度が決められ、ID(ハンドル)が戻り値として返されます。 3.2.3 送信メッセージの書き込み

void Mess_set_CMD( uint8_t Buf_ID, const struct Mess_CMD *P_CMD ); void Mess_set_cmdDATA( uint8_t Buf_ID, const struct Mess_DATA *P_DATA );  前者は、指定IDか free(空)のバッファにコマンドを書き込み、送信要求flag onにします。

後者は、指定IDか free(空)のバッファにコマンドとワードデータを書き込み、送信要求flag onにします。 3.2.4 送信メッセージの取り出しと buffer 解放

1) uint8_t Mess_pickup_BUF(); SPI通信の直前で呼び出します、必須です。

送信要求flag onかつ優先度の高いbufferを、SPI構造体の send message バッファアドレスにセットします。 ・ 送信要求flag onのバッファがない時は、dummy(_Nop)をsend messageとしてセットします。

2) void Mess_release_BUF( void );

SPI通信が正常終了したらこの関数をコールして、取り出したbufferを送信要求flag off(空)にしてバッファを解放 します。 SPI通信をretryできるように、releaseしないと同じbufferを再度取り出します。

3.2.5 受信したコマンド/アンサーと data の取り出し

1) uint8_t Mess_get_CMD( struct Mess_RECV *Pmess );  SPI通信のIO完了後に呼び出します。

receive bufferから、コマンド/アンサーとデータのsizeがPmessにセットされます。 size=0はdataなしです。 2) void Mess_get_DATA( uint8_t size_DT, uint16_t *Pdata );

 データあり(size !=0)の場合は、ワードデータを変数か配列(*Pdata)にsize_DT(バイト)読み出します。 3.2.6 コーリングシーケンス  API関数のコーリングシーケンスは下記例のようになります。 詳細は、exampleプロジェクトで確認してください。 /* calling sequence * * Msee_config(); * Mess_set_BUF(); * ... * Mess_set_CMD(); or Mess_set_cmdDATA(); * ...

* Mess_pickup_BUF(); // <--- Calling this function is essential * SPIm4_IO_NoWait(); // SPI IO

* Mess_get_CMD();

* if( size_DT !=0 ) Mess_get_Data(); * Mess_release_BUF( void );

(7)

7

4 コマンド/アンサーの処理例

下記 code Example は、スレーブがSPI通信のIO完了eventを受けて起動され、その受信メッセージのコマンドを判 断して、コマンドに応じた処理をする部分です。 ① event待ち、event発生でwait解除されるので、eventコードに対応する処理に分岐 SPI通信の完了eventの場合は ->ラベル:SPI4へ分岐 ② SPIパケットから受信メッセージを取りだし、送信バッファを解放 ③ 受信メッセージのコマンドを判定し、各コマンドの処理に分岐 [Code Example] ① event判定

Dev_ID = Check_IOwait( IOwait ); switch ( Dev_ID )

{

/* --- SPI4 --- */

② 受信メッセージのコマンド取り込み case SPI4:

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

Mess_release_BUF(); // releasing the used buffer

③ コマンド内容により処理分岐

switch ( R_mess.M_cmd ) {

case _cmd_Start: // restart

goto Start; case _cmd_PIO:

Mess_get_DATA( 2, &LEDstatus );

// LED on/off

if( LEDstatus ) { P4OUT |= LED1; } // LED1 on

else { P4OUT &= ~LED1; } 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 …….

}

Figure 1  Block diagram

参照

関連したドキュメント

3He の超流動は非 s 波 (P 波ー 3 重項)である。この非等方ペアリングを理解する

1着馬の父 2着馬の父 3着馬の父 1着馬の母父 2着馬の母父 3着馬の母父.. 7/2

1外観検査は、全 〔外観検査〕 1「品質管理報告 1推進管10本を1 数について行う。 1日本下水道協会「認定標章」の表示が

1-1 睡眠習慣データの基礎集計 ……… p.4-p.9 1-2 学習習慣データの基礎集計 ……… p.10-p.12 1-3 デジタル機器の活用習慣データの基礎集計………

この課題のパート 2 では、 Packet Tracer のシミュレーション モードを使用して、ローカル

システムの許容範囲を超えた気海象 許容範囲内外の判定システム システムの不具合による自動運航の継続不可 システムの予備の搭載 船陸間通信の信頼性低下

1着馬の父 2着馬の父 3着馬の父 1着馬の母父 2着馬の母父

2 号機の RCIC の直流電源喪失時の挙動に関する課題、 2 号機-1 及び 2 号機-2 について検討を実施した。 (添付資料 2-4 参照). その結果、