ucos的中断向量表构建

今天又review了一下以前写过的ucos代码,发现ucos在重新setup中断向量表的操作xxxx

void OS_CPU_InitExceptVect (void)
{
    (*(INT32U *)OS_CPU_ARM_EXCEPT_UNDEF_INSTR_VECT_ADDR)       =         OS_CPU_ARM_INSTR_JUMP_TO_HANDLER;
    (*(INT32U *)OS_CPU_ARM_EXCEPT_UNDEF_INSTR_HANDLER_ADDR)    = (INT32U)OS_CPU_ARM_ExceptUndefInstrHndlr;

    (*(INT32U *)OS_CPU_ARM_EXCEPT_SWI_VECT_ADDR)               =         OS_CPU_ARM_INSTR_JUMP_TO_HANDLER;
    (*(INT32U *)OS_CPU_ARM_EXCEPT_SWI_HANDLER_ADDR)            = (INT32U)OS_CPU_ARM_ExceptSwiHndlr;

    (*(INT32U *)OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_VECT_ADDR)    =         OS_CPU_ARM_INSTR_JUMP_TO_HANDLER;
    (*(INT32U *)OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptPrefetchAbortHndlr;

    (*(INT32U *)OS_CPU_ARM_EXCEPT_DATA_ABORT_VECT_ADDR)        =         OS_CPU_ARM_INSTR_JUMP_TO_HANDLER;
    (*(INT32U *)OS_CPU_ARM_EXCEPT_DATA_ABORT_HANDLER_ADDR)     = (INT32U)OS_CPU_ARM_ExceptDataAbortHndlr;

    (*(INT32U *)OS_CPU_ARM_EXCEPT_ADDR_ABORT_VECT_ADDR)        =         OS_CPU_ARM_INSTR_JUMP_TO_HANDLER;
    (*(INT32U *)OS_CPU_ARM_EXCEPT_ADDR_ABORT_HANDLER_ADDR)     = (INT32U)OS_CPU_ARM_ExceptAddrAbortHndlr;

    (*(INT32U *)OS_CPU_ARM_EXCEPT_IRQ_VECT_ADDR)               =         OS_CPU_ARM_INSTR_JUMP_TO_HANDLER;
    (*(INT32U *)OS_CPU_ARM_EXCEPT_IRQ_HANDLER_ADDR)            = (INT32U)OS_CPU_ARM_ExceptIrqHndlr;

    (*(INT32U *)OS_CPU_ARM_EXCEPT_FIQ_VECT_ADDR)               =         OS_CPU_ARM_INSTR_JUMP_TO_HANDLER;
    (*(INT32U *)OS_CPU_ARM_EXCEPT_FIQ_HANDLER_ADDR)            = (INT32U)OS_CPU_ARM_ExceptFiqHndlr;
}

大多数ARM 处理器都支持把RAM remap 到0x00000000 的地址上来,这样就给了重构中断向量提供了可能

ucos里通过调用这个函数就可以重新初始化0x00000000-0x0000003f 这段ram的内容,实际就是重构中断向量表.

以irq中断向量来说:

(*(INT32U *)OS_CPU_ARM_EXCEPT_IRQ_VECT_ADDR)               =         OS_CPU_ARM_INSTR_JUMP_TO_HANDLER;
    (*(INT32U *)OS_CPU_ARM_EXCEPT_IRQ_HANDLER_ADDR)            = (INT32U)OS_CPU_ARM_ExceptIrqHndlr;

#define OS_CPU_ARM_INSTR_JUMP_TO_HANDLER                0xE59FF018

OS_CPU_ARM_ExceptIrqHndlr //是ucos core中的一小段用asm写的irq例程.相当于函数入口地址

#define OS_CPU_ARM_EXCEPT_IRQ_VECT_ADDR      (OS_CPU_ARM_EXCEPT_IRQ            * 0x04 + 0x00)

 

 

 

 

 

 

 

#define OS_CPU_ARM_EXCEPT_IRQ_HANDLER_ADDR             (OS_CPU_ARM_EXCEPT_IRQ            * 0x04 + 0x20)

#define OS_CPU_ARM_EXCEPT_IRQ         0x06 //irq 在8个中断向量里是number6,reset 是number0

先在irq 所在的number6中断向量上(地址是0x00000018) 写入   " 0xE59FF018" 这样一个指令(LDR PC,[PC,0x18] 的指令码)

然后在 0x00000018+0x20 的地址处填上 ucos core 函数OS_CPU_ARM_ExceptIrqHndlr 的地址.

这样在产生irq中断后,PC会被弹到 0x00000018 来取指“0xE59FF018” 执行LDR PC,[PC,0x18] 的操作

这里 pc+0x18 的 位置正好是填充OS_CPU_ARM_ExceptIrqHndlr 的位置,使PC获得OS_CPU_ARM_ExceptIrqHndlr 的入口地址,然后调转过去,执行这个函数(实际是asm代码段)

在OS_CPU_ARM_ExceptIrqHndlr() 函数里

ucos会做保存上下文的操作,然后调用一个叫OS_CPU_ExceptHndlr的函数,这个函数实际上就是给用户中断处理程序的接口函数(call back),用户在自己的BSP c代码里要实现这个函数 完成针对于自己处理器中断控制器的ISR例程。

这个函数原型是,

void OS_CPU_ExceptHndlr (CPU_DATA except_type)

参数except_type 在asm里由R0传递过来,

值可能为:

#define OS_CPU_ARM_EXCEPT_RESET                                                                    0x00
#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR                                                              0x01
#define OS_CPU_ARM_EXCEPT_SWI                                                                      0x02
#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT                                                           0x03
#define OS_CPU_ARM_EXCEPT_DATA_ABORT                                                               0x04
#define OS_CPU_ARM_EXCEPT_ADDR_ABORT                                                               0x05
#define OS_CPU_ARM_EXCEPT_IRQ                                                                      0x06
#define OS_CPU_ARM_EXCEPT_FIQ                                                                      0x07
#define OS_CPU_ARM_EXCEPT_NBR                                                                      0x08

其实就是那8个中断向量number, 对于irq来说 是number6

--------------------------

这一点在ucos AN-1014 datasheet上也说得很

Below is the sequence of events that take place when an IRQ occurs
(assuming the I-bit in the CPSR is 0):
The CPU switches mode to IRQ mode (MODE = 0x12);
The CPSR is saved into the SPSR_irq register;
The return address PC is saved into R14_irq (i.e. the Link Register of the IRQ mode);
The I-bit of the CPSR is set to 1 disabling further IRQs;
The PC is forced to address 0x00000018;
The PC is loaded with the address of OS_CPU_ARM_ExceptIrqHndlr() because of the
LDR PC,[PC,#0x18] instruction that we placed at address 0x00000018.
The CPU executes the code in OS_CPU_ARM_ExceptIrqHndlr(), then
OS_CPU_ARM_ExceptHndlr() (found in OS_CPU_A.S).
OS_CPU_ARM_ExceptHndlr() calls OS_CPU_ExceptHndlr() (found in BSP.C) to
determine the source of the interrupt and handle it accordingly.
When OS_CPU_ARM_ExceptHndlr() returns from OS_CPU_ExceptHndlr(), it calls
OSIntExit() (in case of task interrupted) which determines whether there has been a
more important task that has been made ready to run by the exception handler or,
whether we simply need to return to the interrupted task.
If the interrupted task is still the highest priority task, OSIntExit() returns to
OS_CPU_ARM_ExceptHndlr() which simply returns to this task.
If there is a more important task, OSIntExit() calls OSIntCtxSw() (see OS_CPU_A.S) which
takes care of switching to the more important task.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值