如何从RAM中初始化PIE 中断向量表 ?
答:系统上电时, 所有中断向量PIE必须从FLASH复制到PIE_VECT 中 进行初始化。
PIE_VECT是CMD文件的块,在数据空间中的起始地址是0X000D00,长度为256个字。
如下图所示
上述的操作有很多方法实现,其中一个方法是
第一步 由上面可知PIE中断向量表存储在 0X0000 0D00~0X0000 0DFF 所在的256个字
为了使这段存储器与中断向量表对应 要进行以下工作 。
-
定义函数型指针变量
一个函数在存储器中要占据一定的存储空间,这个空间的起始地址是用函数名表示的,称为 函数的入口地址 。
可以使用指针指向这个入口地址。
并通过指针来调用这个函数
这种指针变量称为 函数型指针变量 其一般的形式为:
数据类型标识符 (*指针变量名) ()
例如 int ( * p) ( ) ;
上式定义了指针p , p 指向的函数返回整型数据 ,
注意:(*p)中的括弧不可缺少,标识p是先与*结合 表示是指针变量,。然后在与后面()结合,表示此指针指向函数。
在TI提供的DSP2833x_PieVect.h 中 (DSP2833x_PieVect.h 包含在DSP2833x_Device.h 中 )
在DSP2833X_PieVect.h 中定义了 PINT , 是指向中断函数类型的指针变量,然后利用结构体 建立 中断向量表 类型 PIE _VECT_TABLE
(PIE_VECT_TABLE 只是建立的一个数据类型)
Typedef interrupt void (*PINT) (void)
在上面的语句中,定义了指针PINT 为指向interrupt 型函数 的指针类型。
由于在使用interrupt时,函数应被定义成返回void ,而且无参数调用,
因此在(*PINT)的后面加上(void),表示PINT是指向函数的指针,且无参数调用。
在(*PINT)的前面加上interrupt void 表示 PINT 指向中断函数。
这样 在描述 PIE 中断矢量表 的时候,可以定义如下结构
Struct PIE_VECT_TABLE()
{
PINT PIE1_RESERVED;
PINT PIE2_RESERVED;
PINT PIE3_RESERVED;
}
开头
结尾
开头 结尾 一共 128个 中断函数
即 该结构体的元素 为函数指针类型,。 而PIE_VECT_TABLE 是一个结构类型,
结构类型中所有成员均为中断函数的首地址(即指向中断函数的指针)。因此
在定义其成员 如 PIE1_RESERVED 等时,要在其前面加上PINT 表示PIE1_RESERVED
是PINT 类型的变量,即指向中断函数的指针。
至此 定义了一个 新的结构体数据类型 PIE_VECT_TABLE
并且声明了 一个 变量 PieVectTable 数据类型是 PIE_VECT_TABLE
注意 这个声明 是 引用性 声明 加关键字extern 表示 它在别的地方 .C文件中被声明和定义 ,。
extern struct PIE_VECT_TABLE PieVecTable
(2)定义PIE中断向量表类型 变量 并分配地址
在 TI 提供的DSP2833X_Gllobal VaribleDefs.c 文件中定义了中断向量表类型变量
PieVectTable , 并通过该变量定义 "在数据空间的段名"PieVectTableFile
#pragma DATA_SECTION( PieVectTable, "PieVectTableFile")
Struct PIE_VECT_TABLE PieVectTable;
如下图所示
插入知识点 #pragma 的语法 :
#pragma CODE_SECTION(symbol ,"section name")
#pragma DATA_SECTION(symbol,"section name")
说明 :
(1)Symbol 是符号。可以实函数名。也可以实全局变量。Section name 使用户自己定义的段名。
(2)CODE_SECTION 用来定义代码段。 DATA_SECTION 用来定义数据段,
使用#pragma 需要注意
- 不能在函数体内 声明 #pragma
- 必须在符号被定义和使用前 使用#pragma.
例如: 将全局数组变量a[128]单独编译成一个新的段,取名为"mynewsect"
#pragma DATA_SECTION (a,"mynewsect");
Unsigned int a [128]
Main()
{
………..
}
定义完了 PIE 中断向量表类型的 变量 PieVectTable
并且把变量定义在段 "PieVectTableFile"
则下一步就是
在CMD文件中为中断向量表 确定存储空间
MEMORY
{
PAGE1 : /*Data Memory */
………
//PIE Vector Table
PIE_VECT : origin=0X000D00 , length =0x000100
………..
}
SECTIONS
{
PieVectTable: >PIE_VECT ,PAGE=1
}
综上:
至此 我已经完成了一个重要的事情:
我在DSP2833X_PIEVECT.h 中 定义了 函数型指针变量
Typedef interrupt (*PINT) (void)
PINT 是指向函数的指针变量
然后我 定义了 结构体 新的数据类型 PIE_VECT_TABLE
里面的类型是 函数型指针变量 。
然后我在DSP2833X_GlobalVariableDefs.c
定义了 数据类型是 PIE_VECT_TABLE 的 变量 PieVectTable
在定义这个变量之前 用
#pragma DATA_SECTION(PieVectTable ,"PieVectTableFile")
这样这个变量 编译的时候生成的段 就是 "PieVectTable "
接下来 通过 CMD 文件 把这个生成的段 放进数据存储空间 0X000D00起始地址开始的128个字中去 。 (重要)
通过memory 划分了存储空间 PIE_VECT PIE_VECT 就是 以0X00D000为起始地址的128个字。
综上 第一个阶段已经完成
下面的第二个阶段 是需要定义一个 常量 结构体 里面的成员全部是 PIE中断函数的首地址 用const 关键字修饰
在DSP2833X_PieVect.c 中定义该 常量结构体
并且还要定义 void InitPieVectTable(void) 函数
在主函数中掉用 InitBoard () //InitBoard()中 有 InitPieVectTable();
InitBoard() 虽然是在DC_Config.c 里面定义的, 但是在DC_Types.h 中声明了。
所以在main.c 文件里面 包含了头文件DC_Types.h
所以直接可以拿过来用了。
说明 这样就完成了 所有的中断向量 从FLASH 中赋值到PIE_VECT 中进行初始化
PIE_VECT 是实际的硬件地址 起始地址为0X000D00 长度为256字
这个文章的标题叫做 如何从RAM中初始化PIE中断向量表?
操作要求: 系统上电的时候,所有中断向量的PIE必须从FLASH 复制到PIE_VECT进行初始化。 PIE_VECT 是CMD 文件中的块。在数据块中的起始地址是0X000D00,长度是256个字
方法: 首先定义一个 函数指针类型的变量
函数指针类型变量的定义方法:
数据类型标识符号 (* 指针变量名)(;)
Uint16 (*P)( ) // 则 P指向的函数 返回数据是整型
//P是指向函数的指针变量
定义了 一个 指向中断函数的指针变量
Typedef interrupt void (*PINT) (void )
然后定义了一个结构体数据类型 结构体的成员名是 指向中断函数的指针变量
Struct PIE_VECT_TABLE()
{
PINT PIE1_RESERVED
PINT PIE2_RESERVED
PINT PIE3_RESERVED
………
}
然后需要定义一个变量 这个变量经过编译器产生的段 名称是PieVectTableFile
#pragma DATA_SECTION (PieVectTable,"PieVectTableFile")
Struct PIE_VECT_TABLE PieVectTable ;
结构体数据类型 变量的 定义 格式
Struct 类型名称 变量名称
类型名称是前面 用struct 定义的
例如类型名称是PIE_VECT_TABLE
在头文件 定义如下
Struct PIE_VECT_TABLE()
{
PINT PIE1_RESERVED
PINT PIE2_RESERVED
PINT PIE3_RESERVED
………
}
然后调用 CMD文件 把这个编译器生成的段名 PieVectTableFile 通过SECTION
伪指令 放到 通过MEMORY 伪指令 定义的 PIE_VECT 空间中去 。
PIE_VECT空间就是 起始地址为0X0000D00 length =0x0000100
然后在DSP2833X_PieVect.c 中定义了 一个PIE_VECT_TABLE 类型的结构体
PIE_VECT_TABLE 结构体里面的成员都是 函数型指针变量
因为此时 成员名的函数指针变量都是确定的地址 是一个常数
所以用关键字const 修饰 ,
备注:const 通常用于定义常数表。 CCS在进行编译的时候,会将这些常数放在.const段。并置于程序存储空间 使用示例如下
Const int digts[]={0,1,2,3,4,5,6,7,8,9};
回归正题
Const struct PIE_VECT_TABLE PieVectTableInit={
PIE_RESERVED,
PIE_RESERVED,
PIE_RESERVED,
…..
// Non-Peripheral Interrupts
INT13_ISR
INT14_ISR
……
}
注意上面的PIE_RESERVED 就是函数名。 是函数的首地址 是一个常量
在DSP2833X_DefaultIsr.c 中声明定义
void * 就是无类型指针类型,他所指向的内存空间没有被认为是某一种特定的类型。
(void *)0 把0强制转换为 void *,
例如 (unsigned char *)j,意思是把j强制类型转换为unsigned char *型
下来看
都需要先取出来 结构体的首地址。&PieVectTableInit;
然后在强制转换为 指向无类型的指针变量。 (void*)&PieVectTableInit
注意 指针变量的赋值格式 :
先看一个例子:
void InitPieVectTable(void)
{
int16 i;
Uint32 *Source = (void *) &PieVectTableInit;
Uint32 *Dest = (void *) &PieVectTable;
EALLOW;
for(i=0; i < 128; i++) {
*Dest++ = *Source++;
}
EDIS;
}