初学ARM,犹如幼儿学步,蹒跚跌撞,始获得一点点站立的经验.
深恐日后忘却,故做了一些日记.
今日无事,整理一下,贴之于论坛,希望:
1) 于我一样在入门时迷茫的朋友,希冀能提供一点帮助,少走点弯路.
2) 于我理解的错误,希冀有高人指点一二.
3) 没有第3了,我刚才明明想到3点的,忘了,呵呵.
【开发环境】keil for arm 2.40a
【arm 芯片】LPC2138
===========================================================================
2006/05/8
关于向量中断
Vectors: LDR PC,Reset_Addr
LDR PC,Undef_Addr
LDR PC,SWI_Addr
LDR PC,PAbt_Addr
LDR PC,DAbt_Addr
NOP /* Reserved Vector */
; LDR PC,IRQ_Addr
LDR PC,[PC, #-0x0FF0] /* Vector from VicVectAddr */
LDR PC,FIQ_Addr
Reset_Addr: DD Reset_Handler
Undef_Addr: DD Undef_Handler?A
SWI_Addr: DD SWI_Handler?A
PAbt_Addr: DD PAbt_Handler?A
DAbt_Addr: DD DAbt_Handler?A
DD 0 /* Reserved Address */
IRQ_Addr: DD IRQ_Handler?A
FIQ_Addr: DD FIQ_Handler?A
为什么是 LDR PC,[PC,#-0x0FF0]?
irq的向量号是6,中断时的PC地址是0x18.
基于ARM的机构,此指令<=>LDR PC,[0x20,#-0x0FF0] <=> LDR PC,[#-0x0FD0]
对32位数, -0x0FD0 = 0xFFFF F030.
这个就是向量中断地址寄存器的地址.
当向量中断irq中有某个中断源发生中断,VICVectAddr中存放的是那个发生中断的中断源
的ISR地址.
这样,LDR PC,[PC,#-0x0FF0]将自动跳转到ISR处理程序.
VICVectAddr 0xFFFF F030
... ...
VICVectAddr0 0xFFFF F100
VICVectAddr0 0xFFFF F104
... ...
===========================================================================
2006/05/9
中断嵌套的问题
对于采用VIC的芯片,有时候涉及到中断嵌套的问题.
比如我现在做的LED显示,VIC中断分配如下:
TIMER1: 用做ARTX操作系统的时钟源.
TIMER0: 用于LED显示扫描.
UART0: 用做通讯.
这里的关键是: TIMER0必须没大约1ms中断一次,而每次扫描的时间从100us-400us不等.
为了不至于使UART的数据丢失,在TIMER0进入中断后,必须"立即"使能UART0的中断.
但UART0和TIMER0都是使用的同一个中断irq.当TIMER0进入中断后,PSR中的I位是自动置'1'了的.
也就是irq已经禁止了.
我强行打开I如何?但如果TIMER0没执行完毕,而UART0中断发生,势必会破坏寄存器的内容.
所以此时涉及到中断嵌套的问题.
keil建议的解决方案如下:
void timer0_srv (void) __irq {
T0IR = 1; // Clear interrupt flag
IENABLE; // allow nested interrupts
longtimerdelay (); // 这里处理一段花费比较长时间的任务
IDISABLE; // disable interrupt nesting
VICVectAddr = 0; // Acknowledge Interrupt
}
// Macros for Interrupt Nesting
#define IENABLE /* Nested Interrupts Entry */ \
__asm { MRS LR, SPSR } /* Copy SPSR_irq to LR */ \
__asm { STMFD SP!, {LR} } /* Save SPSR_irq */ \
__asm { MSR CPSR_c, #0x1F } /* Enable IRQ (Sys Mode) */ \
__asm { STMFD SP!, {LR} } /* Save LR */ \
#define IDISABLE /* Nested Interrupts Exit */ \
__asm { LDMFD SP!, {LR} } /* Restore LR */ \
__asm { MSR CPSR_c, #0x92 } /* Disable IRQ (IRQ Mode) */ \
__asm { LDMFD SP!, {LR} } /* Restore SPSR_irq to LR */ \
__asm { MSR SPSR_cxsf, LR } /* Copy LR to SPSR_irq */ \
==============================================================
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) | Powered by Discuz! 7.0.0 |