こんにちは、
私は以下のプラットフォームでアプリケーションを開発しています:
MCU:NXP S32K314
RTD 7.0.0(AUTOSAR・マカル)
FreeRTOS 7.0.0
S32 Design Studio 3.6.4
開発中に、優先度の高い割り込みに関連するデッドロックに遭遇しました。私の理解が正しいかどうか、また推奨される解決策があるかどうかをお伺いしたいと思います。
FreeRTOSでは、configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITYよりも高い優先度を持つISRは、FreeRTOS APIを呼び出してはならないと規定されています。
しかし、多くのRTD MCAL APIは、内部的に以下の呼び出しチェーンを通じてFreeRTOSのクリティカルセクションAPIを実行していることがわかりました。
MCAL API
↓
SchM_Enter_xxx()
↓
OsIf_SuspendAllInterrupts()
↓
SuspendAllInterrupts()
↓
OsIf_Interrupts_SuspendAllInterrupts()
↓
taskENTER_CRITICAL_FROM_ISR()そして、
MCAL API
↓
SchM_Exit_xxx()
↓
OsIf_ResumeAllInterrupts()
↓
ResumeAllInterrupts()
↓
OsIf_Interrupts_ResumeAllInterrupts()
↓
taskEXIT_CRITICAL_FROM_ISR()この挙動は、DIOやGPTのような単純なペリフェラルレジスタアクセスのみを行うAPIでも存在します。
MCAL API が高優先度 ISR (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY より高い優先度) から呼び出されると、taskENTER_CRITICAL_FROM_ISR() の内部呼び出しによって FreeRTOS の割り込みマスキング状態が不整合になります。
その結果、taskEXIT_CRITICAL_FROM_ISR() が戻った後、BASEPRI が正しく復元されず、SysTick や PendSV などの優先度の低い割り込みがマスクされたままになります。
xPortSysTickHandler() が実行されなくなるため、スケジューラは最終的に停止します。
以下のようなAPIを使用して、この問題を再現することができました。
Dio_FlipChannel()
GPT(PIT)割り込みプロセッシング
SchMの排他領域を使用するその他のMCAL API
RTDで生成されたソースコードを直接変更することを避けるため、GNUリンカーの--wrapオプションを使用して以下の関数をラップしました。
OsIf_Interrupts_SuspendAllInterrupts() OsIf_Interrupts_ResumeAllInterrupts()
ラッパーは現在の割り込み優先度をチェックします。
添付のWrapperExample.cを参照してください。
現在のISRの優先度がconfigLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITYよりも高い場合、元の関数はスキップされます。
そうでない場合は、元の実装を呼び出します。
この回避策は、生成されたRTDソースを変更せずにデッドロックを解消するようです。
この挙動はRTD MCALのデザイン上当然のことですか?
高優先度のISRからDIO、GPT、CAN、または他のMCAL APIを呼び出すのは推奨されますか?
NXPは、ウォッチドッグサービスやGPIOトグルなどの高優先度リアルタイム機能に対して専用ドライバ(複雑デバイスドライバ)の実装を推奨していますか?
GNUリンカーの--wrapオプションを使用してOsIf_Interrupts_SuspendAllInterrupts()とOsIf_Interrupts_ResumeAllInterrupts()をラップすることは、許容できる回避策でしょうか?
生成されたRTDソースコードを変更する必要のない、この問題に対する公式または推奨される解決策はありますか?
何かアドバイスやご提案があれば、大変ありがたく思います。
よろしくお願いします。