如何從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;
}