Board logo

标题: 如何重新定位中断向量表 [打印本页]

作者: shpdlizj    时间: 2006-7-25 13:16     标题: 如何重新定位中断向量表

想把中断向量表从0xff80——0xffff重新映射到0x7f80——0x7fff,该什么做,请高手指点。
作者: strongchen    时间: 2006-7-25 14:56

什么意思,为什么要这么做?
作者: 碧落星空    时间: 2006-7-25 16:22

中断向量表可以重新映射吗?
作者: shpdlizj    时间: 2006-7-25 16:27

因为我的软件有boot和firmware两个程序组成,boot出厂前用BDM烧进去,firmware出厂后用串口下载进去(这样软件远程升级就方便了),所以我的boot放在dp256的3F页并且这部分保护以来防止意外修改或以外檫除。而firmware才真正执行我的所有功能,所以firmware的中断入口地址不能在3F这个页了,只好映射到3E这个页了。我看了AN2153,但那是用汇编写的,我不知道用C应该怎么来弄。
作者: 碧落星空    时间: 2006-7-25 16:38

我觉得重新映射的话应该是初始化时修改寄存器吧?
你说的是转移吧?
作者: shpdlizj    时间: 2006-7-25 17:33

邵贝贝的书上讲了,但我感觉代码不对,AN2153文档里也讲了,而且有原代码;可惜这些代码都是汇编,用C不知道该怎么弄
作者: strongchen    时间: 2006-7-28 11:15

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

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

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


作者: strongchen    时间: 2006-7-28 11:19

这个参考是用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
作者: strongchen    时间: 2006-7-28 11:25

文件在这里:

作者: strongchen    时间: 2006-7-28 11:28

http://bbs.eccn.com/uploadImages/9S12DP256_Vector_Remap.zip
作者: strongchen    时间: 2006-7-28 11:30

大家可以结合AN2153来看我这个参考工程。
作者: shpdlizj    时间: 2006-7-28 13:05

很好
作者: shpdlizj    时间: 2006-7-28 13:29

我对汇编不熟悉,PCR表示PC寄存器吗?请问:asm JMP [0xEFFE,PCR];的意思是什么?
作者: shpdlizj    时间: 2006-7-28 17:29

多谢指点
作者: strongchen    时间: 2006-7-31 10:11

之所以要将中断矢量映射到另一块空间,是因为中断矢量一般在内存地址的最后部分。而FLASH的保护区,一般也选在其后部。为了保护boot程序,我们一般把它放在FLASH的保护区里,这样就不会被意外地擦除或修改。这样,中断矢量也就不能修改了。但是我们的应用程序应该可以修改和升级,这样可能导致中断入口地址的改变。如何解决这个矛盾呢?就采用重新映射中断矢量的办法。实际上,它的工作原理是,在原中断矢量区写入的是一个跳转指令的入口地址。而跳转指令从另一个地址表中取跳转目的地址。这个地址表,就是所谓的中断矢量映射区。采用这种结构,可以使得用户在编程时,不用考虑中断矢量是否映射,可以采用完全相同的程序结构。
作者: strongchen    时间: 2006-8-1 09:16

这条汇编指令采用的是PC变址相对间接寻址方式。它实际上以地址0xEFFE,EFFF中的数据为目的地址进行跳转。“,PCR”只表示它根据程序计数器PC的数据进行变址寻址。在本例中,我们将_Startup的地址值(0xC000)写入了映射矢量0xEFFE,EFFF中,则执行这个指令后,程序就跳转到0xC000处继续运行。

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


作者: strongchen    时间: 2006-8-1 09:30

在这个例子里,引导程序BOOT.C和应用程序MAIN.C是写在一个PROJECT里的。在实际的应用中,引导程序和应用程序可以同时由不同的组分别来做。生产时,可以先将BOOT程序写入芯片,然后在最后阶段将应用程序通过BOOT下载入芯片。
作者: shpdlizj    时间: 2006-8-2 14:08     标题: 您的示例里中断地址影射很好,但我有点疑问。

您在boot.c文件的汇编里用的中断重影射地址指令是JMP而不是JSR,我不知道这地方是否有问题,能否请您做些解释。谢谢。
作者: strongchen    时间: 2006-8-2 14:50

关于这个问题,需要了解CPU进入及退出中断服务程序的过程。当中断发生后,CPU响应一个中断时,首先要将正在执行的程序地址保持到堆栈中(严格地说,应该是下一条指令的地址),然后将一些寄存器的内容,如CCR、A/B及X/Y寄存器,也压入栈,然后再到中断矢量中读取中断服务程序的入口地址,然后再从此地址开始执行指令。当退出中断服务程序时,要按序将堆栈中断的数据恢复到个寄存器中,再将保存在堆栈中的地址读回PC中,使程序回到中断前的程序中顺序执行。
所以,CPU响应中断的过程,应该是先入栈,再进中断服务程序,再出栈,再回到原程序。必须要有一组入栈和出栈的对应操作。
在我的例子程序中,当CPU响应中断时,会自动执行入栈的操作,然后读取的,还是原中断矢量区中的数据(如0xFFFC~0xFFFD),作为中断服务程序的入口地址。进入这个中断服务程序后,再跳转到另一个中断服务程序的入口,再执行真正的中断服务程序。这个真正的中断服务程序也是用interrupt的函数写的,因此它的最后一句指令是中断返回指令RTI。这样,当程序执行到这句指令时,就会进行出栈的操作。
由于这是中断函数而不是子函数,所以它的最后一句指令是RTI而不是RTS。也就是说,不能用JSR来调用。必须产生中断响应的过程,再跳转过来。
作者: strongchen    时间: 2006-8-4 10:39

中断向量的重新映射与S12内部模块(寄存器、RAM和EEPRO)的映射是不同的。内部模块的映射是相应的通过寄存器,真正地改变这些模块的物理地址。而中断向量的物理地址实际上是不能改变的,我们将其重新映射,实际上是通过跳转指令,将其入口地址转向另一块数据区,即所谓的中断向量映射区。
作者: shpdlizj    时间: 2006-8-4 16:51

非常感谢1
作者: chenxingcx4520    时间: 2011-5-9 14:44

16# strongchen
最近刚接触BOOTLOADER,一直困惑中断向量表重分配的方法,我用的是9S12HY128不像HY64支持IVBR中断向量表硬件重定位,只能采用您long long 之前自创的二次跳转方法,我想请教一下PCR具体代表什么含义,哪边能查到,还有请教以下的指令(AN4258 S12BOOTLOADER Main中)是什么含义,谢谢
#define __SEG_START_REF(a)  __SEG_START_ ## a
#define __SEG_END_REF(a)    __SEG_END_ ## a
#define __SEG_SIZE_REF(a)   __SEG_SIZE_ ## a
#define __SEG_START_DEF(a)  extern INT8 __SEG_START_REF (a) []
#define __SEG_END_DEF(a)    extern INT8 __SEG_END_REF   (a) []
#define __SEG_SIZE_DEF(a)   extern INT8 __SEG_SIZE_REF  (a) []

__SEG_START_DEF (RAM_CODE);
__SEG_END_DEF   (RAM_CODE);
__SEG_SIZE_DEF  (RAM_CODE);





欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0