こんにちは、
私は以下のプラットフォームでアプリケーションを開発しています:
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ソースコードを変更する必要のない、この問題に対する公式または推奨される解決策はありますか?
何かアドバイスやご提案があれば、大変ありがたく思います。
よろしくお願いします。
こんにちは、 @tobara さん、
このケースは現在、RTD開発チームからの意見提出を待っています。
BR、ダニエル
こんにちは、
ご質問に対する回答は以下のとおりです。
この挙動はRTD MCALの設計上当然のことですか?回答:はい、これはCAT1割り込み(つまり優先度がMAX SYSCALLより高い割り込み)からOSのAPIを呼び出すために起こります。MAX_SYSCALL以上の割り込みの手当は、RTOSの影響を受けずに最小限のレイテンシで作業を行うためです。RTOSによって生じるレイテンシを避けたいなら、最終的にRTOSを使うAPIを呼び出すべきではありません。
高優先度のISRからDIO、GPT、CAN、または他のMCAL APIを呼び出すのは推奨されますか?
回答:いいえ、最初の回答で述べた理由により、MAX_SYSCALより大きくすることはできません。
NXPは、ウォッチドッグサービスやGPIOトグルなどの高優先度リアルタイム機能に対して専用ドライバ(複雑デバイスドライバ)の実装を推奨していますか?
回答: RTD SchM、OSIf API、RTOSによる遅延に耐えられるなら、既存のドライバーを使い、MAX_SYSCALLより低い割り込みから呼び出しすればいいです。優先度アップの効果は引き続き得られますが、チケットに記載されている問題は解消されません。
GNUリンカーの--wrapオプションを使用してOsIf_Interrupts_SuspendAllInterrupts()とOsIf_Interrupts_ResumeAllInterrupts()をラップすることは、許容できる回避策でしょうか?
生成された RTD ソース コードを変更する必要のない、この問題に対する公式または推奨される解決策はありますか?回答 (ただし、RTD チームによる確認が必要です) : IRQ > MAX_SYSCALL から RTD / RTOS API を呼び出さないでください。現在のRTD->OSIF->RTOSのレイテンシに耐えられるなら、優先度の高いIRQをMAX_SYSCALLより低く設定すればいいです。
すべての回答はRTDチームによる確認が必要です。私はRTOSの観点から回答しています。
詳細なご説明をありがとうございました。
私は今、NXP RTD/MCALの以下の設計制約を理解しました。
いくつか追加の質問があります。
自動車分野以外の組み込みソフトウェアの経験から言うと、ハードウェア抽象化層はしばしばオペレーティングシステムに依存しないように設計されています。そのため、単純なGPIOおよびタイマーAPIが内部的にRTOSのクリティカルセクションAPIを呼び出していることに気づいて驚きました。
参考までに、この問題を避けるために実装したGPTドライバー(CpuPit.h/c)を添付しました。
RTDチームからのご意見やご提案をいただければ幸いです。
改めてサポートありがとうございます。