首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

如何重新定位中断向量表

什么意思,为什么要这么做?
海纳百川  有容乃大

我用DP256做了一个重新映射矢量区的例子,贴出来供大家参考:

http://bbs.eccn.com/uploadImages/9S12DP256_Vector_Remapping.zip

[此贴子已经被strongchen于2006-7-28 11:15:54编辑过]

海纳百川  有容乃大
这个参考是用CW4.5做的。现在做一些说明:
1. 要修改PRM文件。我修改的是文件Full_Chip_Simulation_linker.prm。
2. 修改方法:
1). 我要将中断映射到0xEF80~0xEFFF处,所以要将这段地址空出来。因此,我将ROM_C000段的地址改为0xC000 TO 0xEF7F,又增加了一个ROM_BOOT段,地址为:0xF000 TO 0xFFEF。
2). 定义一个段名:
BOOT_CODE INTO ROM_BOOT;
3). 原矢量地址和跳转矢量地址的定义:
VECTOR 0 BootStart
VECTOR 1 JClockFail

VECTOR ADDRESS 0xEFFE _Startup
VECTOR ADDRESS 0xEFFC ClockFail
海纳百川  有容乃大
文件在这里:
海纳百川  有容乃大
http://bbs.eccn.com/uploadImages/9S12DP256_Vector_Remap.zip
海纳百川  有容乃大
大家可以结合AN2153来看我这个参考工程。
海纳百川  有容乃大
之所以要将中断矢量映射到另一块空间,是因为中断矢量一般在内存地址的最后部分。而FLASH的保护区,一般也选在其后部。为了保护boot程序,我们一般把它放在FLASH的保护区里,这样就不会被意外地擦除或修改。这样,中断矢量也就不能修改了。但是我们的应用程序应该可以修改和升级,这样可能导致中断入口地址的改变。如何解决这个矛盾呢?就采用重新映射中断矢量的办法。实际上,它的工作原理是,在原中断矢量区写入的是一个跳转指令的入口地址。而跳转指令从另一个地址表中取跳转目的地址。这个地址表,就是所谓的中断矢量映射区。采用这种结构,可以使得用户在编程时,不用考虑中断矢量是否映射,可以采用完全相同的程序结构。
海纳百川  有容乃大
这条汇编指令采用的是PC变址相对间接寻址方式。它实际上以地址0xEFFE,EFFF中的数据为目的地址进行跳转。“,PCR”只表示它根据程序计数器PC的数据进行变址寻址。在本例中,我们将_Startup的地址值(0xC000)写入了映射矢量0xEFFE,EFFF中,则执行这个指令后,程序就跳转到0xC000处继续运行。

[此贴子已经被strongchen于2006-8-1 9:16:57编辑过]

海纳百川  有容乃大
在这个例子里,引导程序BOOT.C和应用程序MAIN.C是写在一个PROJECT里的。在实际的应用中,引导程序和应用程序可以同时由不同的组分别来做。生产时,可以先将BOOT程序写入芯片,然后在最后阶段将应用程序通过BOOT下载入芯片。
海纳百川  有容乃大
关于这个问题,需要了解CPU进入及退出中断服务程序的过程。当中断发生后,CPU响应一个中断时,首先要将正在执行的程序地址保持到堆栈中(严格地说,应该是下一条指令的地址),然后将一些寄存器的内容,如CCR、A/B及X/Y寄存器,也压入栈,然后再到中断矢量中读取中断服务程序的入口地址,然后再从此地址开始执行指令。当退出中断服务程序时,要按序将堆栈中断的数据恢复到个寄存器中,再将保存在堆栈中的地址读回PC中,使程序回到中断前的程序中顺序执行。
所以,CPU响应中断的过程,应该是先入栈,再进中断服务程序,再出栈,再回到原程序。必须要有一组入栈和出栈的对应操作。
在我的例子程序中,当CPU响应中断时,会自动执行入栈的操作,然后读取的,还是原中断矢量区中的数据(如0xFFFC~0xFFFD),作为中断服务程序的入口地址。进入这个中断服务程序后,再跳转到另一个中断服务程序的入口,再执行真正的中断服务程序。这个真正的中断服务程序也是用interrupt的函数写的,因此它的最后一句指令是中断返回指令RTI。这样,当程序执行到这句指令时,就会进行出栈的操作。
由于这是中断函数而不是子函数,所以它的最后一句指令是RTI而不是RTS。也就是说,不能用JSR来调用。必须产生中断响应的过程,再跳转过来。
海纳百川  有容乃大
中断向量的重新映射与S12内部模块(寄存器、RAM和EEPRO)的映射是不同的。内部模块的映射是相应的通过寄存器,真正地改变这些模块的物理地址。而中断向量的物理地址实际上是不能改变的,我们将其重新映射,实际上是通过跳转指令,将其入口地址转向另一块数据区,即所谓的中断向量映射区。
海纳百川  有容乃大
返回列表