平成27年 4月28日
PIC32の周辺機能(USART)を活用する(その5) FIFO機能の検証
受信割り込みをFIFOに複数データを受信する仕様で動作させた場合、既にFIFO中に1バイト以上の受信データがある状態で受信エラーが起きた場合、受信エラー割り込みはエラー受信直後に起きるのか、それとも一旦FIFOに格納された後、CPUが読み出す直前にエラー割り込みフラグが立つのかを実際に動作させて確かめます。
実験プログラムを下記に示します。
SCI_CFG_t cfg = {
DEFAULT_SCI_CFG_PBCLK,
0x8040, //ループバックモード
0x1480, //受信側は6バイト受信で割り込み発生
1000000, //1Mbps
1,
1,
1
};
void U1ISRCB(void)
{
uint8_t ef, intf;
volatile uint8_t tmp;
getEIF(1, &ef, "");
getRXIF(1, &intf, "");
if(ef){
tmp = *sci->RXREG; //BP1
Nop();
setEIF(1, 0, "");
setRXIF(1, 0, "");
}else if(intf){
tmp = *sci->RXREG; //BP2
Nop();
setRXIF(1, 0, "");
}
Nop();
}
void test(void)
{
EI();
*sci->TXREG = 0x55; //1文字目データ
Nop();
*sci->TXREG = 0x55; //2文字目データ
Nop();
*sci->TXREG = 0x55; //3文字目データ
Nop();
while(!sci->STAbits->TRMT) //送信終了待ち
;
sci->STAbits->UTXBRK = 1; //フレーミングエラー送信要求(次の送信開始で)
*sci->TXREG = 0xaa; //このデータ値は無意味で、全て0として送信される
while(!sci->STAbits->TRMT)
;
Nop();
for(;;)
Nop(); //BP3
}
#define ligSCI1CB ligSCI1_para.func
void init(void)
{
sysPerrformanceConfig(SYS_CLK);
INTCONbits.MVEC = 1; //割り込みマルチベクタ
//ここの他の初期化関数を順次追加
ligSCI1CB = U1ISRCB; //CB関数の登録
sci = SCI_init(&cfg);
test();
}
int main(void)
{
init();
}
まず、プログラムの動作条件はPIC32のループバックモードを使用します。これで外部の配線は不要です。
USARTの初期化と割り込み処理関数は以前説明したプログラムを使用します。
プログラムの動作としては、最初に0x55を3バイト送信終了させます。その後、USARTのBREAK機能を使って受信側にフレーミングエラーを起こします。BREAK機能は少し説明が必要です。このビットを1にすると、次に送信シフトレジスタへデータを送信するタイミングでフレーミングエラーを起こします。このとき送信シフトレジスタへ転送されたデータの値は無視され全てが0のデータとして送信されます。ここで注意が必要なのは、BREAK機能はFIFOの動作とは連動していない点です。先にFIFOに複数のデータを書き込んだ状態で、BREAKビットに1を書き込んだ場合、現在シフトレジスタにあるデータが送信された次のデータがBREAK機能の対象データとなります。つまり、先にFIFOに書き込んだデータがBREAK機能によって上書きされることになります。これを避けるために、先の3バイトの送信が終了するのを待ってBREAKビットをセットし送信データをセットします。
実験した結果、受信エラー割り込みはエラー発生直後に起こります。先の例では、受信文字数はエラーを起こしたデータを含めても4バイトです。受信割り込みは6バイトに設定してあるので、今回は起きず先に受信エラー割り込みだけが発生しました。結論としてはエラービットにはFIFOがないことになります。
これで通信仕様の残りの検討ができます。通信エラーが発生するとマスタとスレーブ間での6バイト単位の同期は崩れます。受信エラー割り込みによって受信データを先に処理する必要があるためます。このためこれを再同期させる手順が必要になります。スレーブ側で発生する受信エラーでは、スレーブは既存のデータをすべて破棄することにします。既存のデータとは現在の受信データ(6バイト以内)だけではなく、それ以前に受信したマスタからの先頭データ以降の全てのデータを破棄します。実際には受信エラーを処理しても、その処理後に送信されたデータがFIFOに残っている可能性があるので、これだけでは不十分です。スレーブが受信データを破棄することによって、マスタ側ではタイムアウトとして認識されます。マスタ側ではタイムアウトを検出するとBREAK機能を使って再び受信エラーを起こさせます。このエラーによってスレーブ側の受信データは確実に全て破棄されますので、送受信数を0から始めることが出来ます。後は再実行を試みます。