PC版 SYSLAB blog  http://syslab.asablo.jp/blog/......

Raisonance Ride7 & ARM Tools (17) LPC2xxx の Startup (2)
2012-09-25


さて、それでは本題に入っていこう。
Raisonance の Startup を使ってうまくいかない原因のひとつはエントリー部分に割り込み専用の処理がしてあるにもかかわらず __attribute__ ((interrupt("IRQ"))) などを使ってしまうことだ。従って、割り込みエントリーを使うなら属性指定をしてはならない。

もうひとつの原因はエントリー部分からハンドラをコールしなければならないにもかかわらずジャンプしてしまっていることだ。よって、コールに変更する。

さらにもうひとつあげるとするなら Raisonance の場合、通常スタートアップは $(RkitLib)\ARM\ から crt0_LPC23x.o の形でリンクするのでハンドラを weak 指定にしたほうがよい、といったところだろうか。

まずは IRQ を使った割り込み。
@ main_irq1.c

  void Timer0Handler(void); #define TIMER0_INT 4 volatile unsigned long timer0_counter = 0; void Timer0Handler(void) { T0IR = 1; /* clear interrupt flag */ FIO1PIN2 ^= 0x04; timer0_counter++; } void IRQ_Handler( void ) { #if 1 if ( VICIRQStatus & (1 << TIMER0_INT) && VICIntEnable & (1 << TIMER0_INT) ) Timer0Handler(); #else if(T0IR & 1) Timer0Handler(); #endif } int main(void) { SCS |= 1; FIO1DIR = 1 << 18; T0CTCR = 0; T0MR0 = 500000 - 1; T0MCR = 0x3; VICIntEnable |= (1 << TIMER0_INT); /* Enable Interrupt */ T0TCR = 1; while(1); }

割り込みが入ると IRQ_Handler をコールしてくるのでこの関数の中で割り込み先を特定し、さらにそこへ分岐していく。

次に、VicVectAddr を使った割り込み。
A main_irq2.c

  void Timer0Handler(void); #define TIMER0_INT 4 #define HIGHEST_PRIORITY 0x01 #define LOWEST_PRIORITY 0x0F #define VECT_ADDR_INDEX 0x100 #define VECT_PRIO_INDEX 0x200 volatile unsigned long timer0_counter = 0; void Timer0Handler(void) { T0IR = 1; /* clear interrupt flag */ FIO1PIN2 ^= 0x04; timer0_counter++; VICVectAddr = 0; /* Acknowledge Interrupt */ } void IRQ_Handler( void ) { void (*fpFunc)(void); fpFunc = (void*)VICVectAddr; (*fpFunc)(); } int main(void) { SCS |= 1; FIO1DIR = 1 << 18; T0CTCR = 0; T0MR0 = 500000 - 1; T0MCR = 0x3; *(unsigned long *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + TIMER0_INT*4) = (unsigned long)Timer0Handler; *(unsigned long *)(VIC_BASE_ADDR + VECT_PRIO_INDEX + TIMER0_INT*4) = HIGHEST_PRIORITY; VICIntEnable |= (1 << TIMER0_INT); /* Enable Interrupt */ T0TCR = 1; while(1); }

同じ IRQ 割り込みでも VICVectAddr に予め関数を登録しておけば割り込み先を特定する作業をすることなく呼び出すことができる。

続いて FIQ を使った割り込み。
B main_fiq.c

  #define TIMER0_INT 4 volatile unsigned long timer0_counter = 0; void Timer0FIQHandler(void) { FIO1PIN2 ^= 0x04; timer0_counter++; T0IR=1; // VICVectAddr = 0; // * Acknowledge Interrupt * } void FIQ_Handler( void ) { if ( VICFIQStatus & (1 << TIMER0_INT) && VICIntEnable & (1 << TIMER0_INT) ) { Timer0FIQHandler(); } } int main(void) { SCS |= 1; FIO1DIR = 1 << 18; T0CTCR = 0; T0MR0 = 500000 - 1; T0MCR = 0x3; VICIntSelect |= (0x1 << TIMER0_INT); VICIntEnable = (0x1 << TIMER0_INT); T0TCR = 1; while(1); }

@ の IRQ 割り込みと似ている。

最後は VICVectAddr をベクターテーブルに組み込んだ割り込み。
この時 crt0_LPC23x.s は以下の変更をする。
    ldr     PC, [PC, #-0x0120] これを有効にして(lpc21x Lpc22x の場合は 0x0FF0)
    ldr     PC, =IRQHandler  これをコメントにする。
この方法は Startup のエントリー部分を使わないので割り込み処理ルーチンに __attribute__ ((interrupt("IRQ"))) が必要だ。
C main_vic.c

 


続きを読む

[ARM]
[マイコン]

コメント(全0件)
コメントをする


記事を書く
powered by ASAHIネット