UCT μT-Kernel DevKit tuned for FM3-GCC無償評価版のARMv6-M対応化改造、とりあえず一旦ここで一区切りしておきますか。前回(29-Aug-2013)との違いは、WFI対応と一部のコメントの修正くらい。ディレクトリ内にあるkernel-rom.mot(他一式)は、08-Sep-2013のusermain.cを組み込んでいます。
あとはLPC1114向けに色々直してけばいいのかなーと思うのですが、ちょっと気になったのがlib/libtk/src/sysdepend/app_mb9af312k/disint.Sにあるこの記述。ソースをまるっと引用しますよ。
.code 16
.syntax unified
.thumb
/*
* Disable external interrupt
* UINT disint( void )
* Disable interrupt by Rise prioperty to 0.
*/
.text
.align 2
.thumb_func
.globl Csym(disint)
.type Csym(disint), %function
Csym(disint):
mrs r0, basepri
ldr r1, =MAX_EXTINT_PRI
msr basepri, r1
bx lr
/*
* Enable external interrupt (restore to original state)
* UINT enaint( UINT intsts )
* Enable interrupt.
*/
.text
.align 2
.thumb_func
.globl Csym(enaint)
.type Csym(enaint), %function
Csym(enaint):
msr basepri, r0
bx lr
|
PSR側の割り込み禁止フラグではなくNVIC側の割り込み優先度をいじって割り込みを完全に禁止する意図って、なんなんですかね。割り込みが発生した際にスタック上にxPSRが積まれるので、これを触りたくない(ARM7TDMI版のcpu_support.Sではスタック上に保存されたPSRの割り込み禁止フラグを消す処理が行われているが、これを嫌った?)という理由くらいしか思いつかないのですが…
とりあえず下手に改変して怪我するのも嫌なのでこれは放置しておきますが、なんなんだろうと疑問に思っていることは確かです。59.05kg(18:05)
13-Sep-2013補足:Cortex-MのxPSRにはARM7TDMIのようなIRQ/FIQ禁止フラグはありません。cpsid i/cpsie iに連動してMSRのPRIMASK.PMの内容が変化するようです。
Cortex-M3とは異なり、Cortex-M0ではBASEPRIレジスタが無いので、PRIMASKレジスタの操作に置き換える必要があります。NVIC周りも多少手を入れる必要がまだ残っています…
25-Sep-2013補足:cpsid命令の説明に書かれていますが、cpsid iを実行するなどしてPRIMASK.PM=1とした場合、優先順位は0に引き上げられます。この状態で発生可能な例外は、優先順位-1, -2を持つNMIや各種のFault等に限られます。
ARMv6-M/ARMv7-MではSVC命令による例外の発生にも優先順位が設定されており、SVC例外を発生できない状態ではHardFault例外として扱われます(ARMv6-M Architecture Reference ManualにはSVC命令の項目にこのことがちゃんと書かれているのですが、ARMv7-M Architecture Reference manualではB1.5.4 Exception priorities and pre-emptionのPriority escalationの項を見ないと分からないのですごく分かりにくいです)。
この、「SVC命令の実行は禁止されることがある」という問題を避けるのがbasepriの操作を行う意図のようです。icrt0.Sでは以下のように、SVC例外の優先順位を(Faultを除いて)一番高く設定しています。
ldr r5, =SCB_SHPR2
movs r6, #0 /* SVC pri = 0 */
str r6, [r5]
ldr r5, =SCB_SHPR3
ldr r6, =0x10F00000 /* Pendsv pri = 0xF, sistick pri = 0x1 */
str r6, [r5]
ldr r5, =NVIC_IPR_FORCE_DISPATCH
ldr r6, [r5]
movt r6, #0xc030 /* force dispatch pri = 0xC, IRQ #94 pri = 0x3 */
str r6, [r5]
|
とはいえ、これでもSVC例外のコンテキスト中ではSVC命令を発行できない点に注意が必要です。また、NVICのIPRレジスタの設定はμT-Kernel自体が使用する例外のみ優先順位を下げており、他はデフォルトの優先順位0のままだったりしますので、きちんと優先順位を下げておかないと困った問題を招きそうに見えます。
ARMv6-MではARMv7-Mのようにbasepriレジスタを操作して「どうにかしてSVCを使う」という手段が使えない以上、μT-KernelではSVCの使用を諦めた方が良さそうです。正直なところ、Wikipediaのプロテクトモードの歴史にある「石頭」を真っ先に思い出しました。