RXマイコン用 FreeRTOS の依存部分コードを観ていて、疑問に思う場所があります。
ソースは
portable/Renesas/RX600/portmacro.h
で、SWINT を起動する部分です。
#pragma inline_asm vPortYield
/* Save clobbered register - may not actually be necessary if inline asm
}
上記の「553696」は「0x720E0」で、ICUの「ソフトウェア割り込み起動レジスタ(SWINTR)」
と思いますが、起動させる為、バイトで「1」を書いてから、32ビットで読み出しています。
ICUの説明を読んでも、書き込み後に32ビットで読み出す必要がある事は書かれていません。(RX64Mのハードウェアーマニュアル)
そもそも、SWINT を起動するなら、DTC用に用意してあるハードを叩かなくても、
「INT #27」のアセンブラ命令を実行すれば良いように思います。
何故、このような実装になっているか判る方いますか?
hirakuni45さん、こんにちは。NoMaYです。ああっ、なるほど!バイトサイズレジスタに「バイトで「1」を書いてから、32ビットで読み出しています。」ね。全く気付きませんでした、、、確かに、これは変ですね、、、FreeRTOS v10.2.1でも同じでした。また、他の系列(RX600v2,RX200,RX100)向けのソースも同じでした。(以下のサイトからダウンロードしたものです。)あと、この部分では、後から気になったのですが、本当にSWINTにライトされてから実際に割り込みルーチンに分岐するまでに更に何命令か遅延があるか(或いは遅延無しで済むか)どうかです。これは、ハードウェアマニュアルに何か記載があったような記憶があるので、後で調べてみようかと思い始めました。FreeRTOS - sourceforge.netsourceforge.net/projects/freertos/files/それで、「簡単なサンプルでは、「int #27」でも同じように動作はするようです。」とのことですが、ひょっとして、まだ以下のような、割り込み処理内から、ブロック解除待ちとなっているタスクのブロック解除を行い、割り込み終了後すぐにそのタスクに制御を移す、といった動作は試されてないのではありませんか?(つまり、割り込み処理との関連が無いサンプルで試されているのではないですか?) そういったサンプルであれば、SWINTでも、int #27でも、これらに対するRXマイコンの動作から考えれば、違いは出ないと思います。(だからこそ、hirakuni45さんが試されているのだろうと、私は受け取っていますが、、、)割り込み処理内のコード例 (以下のFreeRTOSカーネル 開発者ガイドから抜粋)docs.aws.amazon.com/ja_jp/freertos-kernel/latest/dg/interrupt-management.html
static uint32_t ulExampleInterruptHandler( void ){ BaseType_t xHigherPriorityTaskWoken; /* The xHigherPriorityTaskWoken parameter must be initialized to pdFALSE because it will get set to pdTRUE inside the interrupt-safe API function if a context switch is required. */ xHigherPriorityTaskWoken = pdFALSE; /* Give the semaphore to unblock the task, passing in the address of xHigherPriorityTaskWoken as the interrupt-safe API function's pxHigherPriorityTaskWoken parameter. */ xSemaphoreGiveFromISR( xBinarySemaphore, &xHigherPriorityTaskWoken ); /* Pass the xHigherPriorityTaskWoken value into portYIELD_FROM_ISR(). If xHigherPriorityTaskWoken was set to pdTRUE inside xSemaphoreGiveFromISR(), then calling portYIELD_FROM_ISR() will request a context switch. If xHigherPriorityTaskWoken is still pdFALSE, then calling portYIELD_FROM_ISR() will have no effect. Unlike most FreeRTOS ports, the Windows port requires the ISR to return a value. The return statement is inside the Windows version of portYIELD_FROM_ISR(). */ portYIELD_FROM_ISR( xHigherPriorityTaskWoken );}
ところが、割り込み処理内では、SWINTとint #27では、RXマイコンの動作が異なります。割り込み処理内(A) SWINT → 割り込み処理から抜けないとSWINTの割り込み処理ルーチンへは分岐しない(B) int #27 → 割り込み処理内からint #27の割り込み処理ルーチンへ分岐していく私が予想しているのは、以下のデファインから考えて、vPortYield()のSWINTをint #27へ書き換えるのみの場合、割り込み処理内でportYIELD_FROM_ISR()を使うようなサンプルでは動作がおかしくなる筈ではないか、というものです。
#define portYIELD() vPortYield()#define portYIELD_FROM_ISR( x ) if( x != pdFALSE ) portYIELD()
なお、前のリプライに書いたRL78のFreeRTOSのように、RL78のソフトウェア割り込み命令(BRK)を使う実装と、ソフトウェア割り込み機能もどきを使う実装の、2つの実装が可能であったように、他の部分も併せて書き換えれば、SWINTを全く使わず、int #27(もちろん他の任意のint #xxでも)のみ使う、それでもきちんと動作する、そういうポートレイヤを実装することは出来る筈だと思います。(私は、それをする場合に、RL78のソフトウェア割り込み命令(BRK)を使う実装のポートレイヤが参考になるだろう、と思ってます、、、)それで、以下はもともとのFreeRTOSのRL78のソフトウェア割り込み命令(BRK)を使う実装でのデモプログラムから抜き出したものですが、前のリプライに書いた「おまじない」と言うのは、以下のように、割り込み処理ルーチンの最初と最後で、決められたルーチンを呼び出す、というものです。(なお、以下はIAR社のアセンブラソースでのマクロ記述になっていますが、GCCでCソースにnaked属性を付けた関数に書くことも出来ると思います。ポイントは、割り込みルーチンの、まさに最初と最後のところ、で呼び出す、ことです。)FreeRTOSv10.2.1\FreeRTOS\Demo\RL78_multiple_IAR\ExampleISR.s87
vANExampleISR_ASM_Wrapper:; portSAVE_CONTEXT() must be the first thing called in the ASM; wrapper. portSAVE_CONTEXT; Once the context has been saved the C handler can be called. call !!vAnExampleISR_C_Handler; Finally the ISR must end with a call to portRESTORE_CONTEXT(); followed by a reti instruction to return from the interrupt to whichever; task is now the task selected to run (which may be different to the task; that was running before the interrupt started). portRESTORE_CONTEXT reti
Higetakaさん、こんにちは。NoMaYです。以下の件、後で調べてみようと思います。(たぶん、別スレッドにすると思います。)> SWINTRにバイトで書き込んで、32ビットワードで読み出すと、RXのパイプラインでは書き込みが保証されるというような、わかりにくい仕様があるのかもしれません。