本帖最后由 stopshooting 于 2016-7-10 03:11 编辑
在STM8 IAP的官方bootloader例程中, 中断向量表的重定向是这样的。
[mw_shl_code=c,true]/* Redirected interrupt vector table
* Copyright (c) 2008 STMicroelectronics
*/
#include "main.h"
typedef void @far (*interrupt_handler_t)(void);
struct interrupt_vector {
unsigned char interrupt_instruction;
interrupt_handler_t interrupt_handler;
};
@far @interrupt void NonHandledInterrupt (void)
{
/* in order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction
*/
return;
}
extern void _stext(); /* startup routine */
struct interrupt_vector const UserISR_IRQ[32] @ MAIN_USER_RESET_ADDR;
//redirected interrupt table
struct interrupt_vector const _vectab[] = {
{0x82, (interrupt_handler_t)_stext}, /* reset */
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 1)}, /* trap */
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 2)}, /* irq0 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 3)}, /* irq1 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 4)}, /* irq2 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 5)}, /* irq3 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 6)}, /* irq4 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 7)}, /* irq5 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 8)}, /* irq6 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+ 9)}, /* irq7 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+10)}, /* irq8 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+11)}, /* irq9 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+12)}, /* irq10 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+13)}, /* irq11 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+14)}, /* irq12 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+15)}, /* irq13 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+16)}, /* irq14 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+17)}, /* irq15 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+18)}, /* irq16 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+19)}, /* irq17 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+20)}, /* irq18 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+21)}, /* irq19 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+22)}, /* irq20 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+23)}, /* irq21 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+24)}, /* irq22 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+25)}, /* irq23 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+26)}, /* irq24 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+27)}, /* irq25 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+28)}, /* irq26 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+29)}, /* irq27 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+30)}, /* irq28 */
{0x82, (interrupt_handler_t)(UserISR_IRQ+31)}, /* irq29 */
};
[/mw_shl_code]
其中MAIN_USER_RESET_ADDR 为0x9000,也就是说用户APP的中断向量表是放在0x9000上的
我的问题是,为什么重定向的地址是(interrupt_handler_t)(UserISR_IRQ+xx)?
根据上面的程序,
(UserISR_IRQ+ 1)表示0x9004,(UserISR_IRQ+ 2)表示0x9008,
(UserISR_IRQ+ 3)表示0x900c,
(UserISR_IRQ+ 4)表示0x9010,
(UserISR_IRQ+ N)表示(0x9000+N*4),而bootloader的的中断向量表是放在0x8000上的,
从这个表格中可以看出,bootloader的中断向量表_vectab中的interrupt_handler_t变量的地址明明就是0x8005, 0x8009, 0x800d, 0x8011, ((0x8000+N*4)+1)啊。。
难道重定向后的地址不应该0x9005, 0x9009, 0x900d, 0x9011, (0x9000+N*4+1)吗?
也就是 (interrupt_handler_t)((void*) (interrupt_handler_t)(UserISR_IRQ+xx)+(void*)1)吗?
用STVD仿真看到附件的图片:
可以看到中断向量表的interrupt_handler_t变量所在地址与其内容的比较
时隔多日再次回到这里,也不知道当时是不是脑抽了,这都没想明白。
0x82 0x9004 是一个语句,要跳到新建的中断向量表处,新建的中断向量表有0x82 IRQHander。
当然是要跳到0x9004了,0x9004刚好就是 0x82 IRQHander 这个语句中0x82的地址。
当时脑抽想着要跳到0x9005才对。。。然而这个0x9005不过是中断函数的地址的地址,而非中断中断函数的地址。。。当然了,也可以直接跳到中断函数的地址,毕竟中断函数地址的地址是已知的,不过还没有试过。
一周热门 更多>