FreeRTOS(PIC18版)の割り込みは、1箇所のベクタで「タイマ1(タスクスイッチやTickカウント等に使用)」「シリアル受信」「シリアル送信」を判別してそれぞれ振り分けてます。(他のプロセッサの実装はまだ見ていない)
PIC18では、高位のと低位の2段階の割り込みプライオリティをつけられるのですが、FreeRTOSでは割り込みプライオリティモードを使わない設定(従来のPIC16シリーズと同じ=PIC16CXXXX互換モード)を使用しています。
普段はそれでも良いのですが、今回のシステムではタイマ1より優先度の高い割り込みを使用したく、LowベクタとHighベクタを設定して割り込みプライオリティモードを使用できるようにOSを修正することにします。
■まずは、FreeRTOS側の「port.c」
・static関数「prvLowInterrupt」を変更
//#pragma code high_vector=0x08
#pragma interruptlow prvLowInterrupt ← #pragmaはこのように変更
static void prvLowInterrupt( void )
{
/* Was the interrupt the tick? */
if( PIR1bits.CCP1IF )
{
prvTickISR(); ← インラインasmから通常の関数コールに変更
// _asm
// goto prvTickISR
// _endasm
}
/* Was the interrupt a byte being received? */
if( PIR1bits.RCIF )
{
vSerialRxISR(); ← インラインasmから通常の関数コールに変更
// _asm
// goto vSerialRxISR
// _endasm
}
/* Was the interrupt the Tx register becoming empty? */
if( PIR1bits.TXIF )
{
if( PIE1bits.TXIE )
{
vSerialTxISR(); ← インラインasmから通常の関数コールに変更
// _asm
// goto vSerialTxISR
// _endasm
}
}
}
・prvLowInterruptの直下に低優先度の割り込みベクタを追加
#pragma code _LOW_INTERRUPT_VECTOR = 0x001018
void _low_ISR (void)
{
_asm goto prvLowInterrupt _endasm ← prvLowInterruptへジャンプ
}
#pragma code
・・・
■次に、ユーザー関数側(mainなど)で高位のベクタとレジスタの設定。
//高優先度の割り込み関数
#pragma interrupt HighISR
void HighISR(void)
{
if( PIRnbits.割り込みフラグ ) ← ここはユーザー環境に合わせて
{
タイマ1より優先度の高い割り込み関数名();
}
}
// スタートアップ
#pragma code _RESET_INTERRUPT_VECTOR = 0x001000
void _reset (void)
{
_asm goto _startup _endasm
}
//高優先度の割り込みベクタ
#pragma code high_vector=0x01008
void _high_ISR (void)
{
_asm goto HighISR _endasm ← HighISRへジャンプ
}
#pragma code
・・・
■割り込みプライオリティモードを有効にするために、OSのスケジューリングを有効にする前にレジスタ設定をします。
FreeRTOSのタイマ割り込みはCCP1なので、以下のように設定すればOKです。
これで、CCP1の割り込みプライオリティが「低」に設定されます。
(ちなみにデフォルトは「高」となっていますので気をつけて下さい)
IPR1bits.CCP1IP = 0;
最後に、割り込み優先順位を有効するためのレジスタを設定します。
RCONレジスタのIPENを1にすることで、割り込みプライオリティモードが設定されます。
(IPEN=0で、PIC16CXXXX互換モード)
RCONbits.IPEN = 1;