中斷調(diào)用方式的ARM二次開(kāi)發(fā)接口設(shè)計(jì)
圖4 基于GNU工具鏈的開(kāi)發(fā)模式圖
這里選用EABI版本,其基本操作命令如表1所列。CortexM3內(nèi)核在地址0x00000000處存放一個(gè)向量表,向量表的第0個(gè)單元即地址0x00000000處存放的是堆棧頂?shù)牡刂贰ortexM3復(fù)位后即從該處取出數(shù)據(jù),用以初始化MSP寄存器。向量表中的內(nèi)容是32位的地址,這些地址是中斷異常服務(wù)程序的入口地址,其中向量表的第一個(gè)單元即地址0x00000004處存放的是復(fù)位向量,也就是說(shuō)CortexM3復(fù)位后,執(zhí)行該向量(可理解為函數(shù)指針)指向的復(fù)位代碼[4],代碼如下:
__attribute__ ((section(".stackarea")))
static unsigned long pulStack[STACK_SIZE];
表1 winARM20080331 GNU 工具鏈的命令名稱
這一句定義了一個(gè)pulStack數(shù)組,程序把這個(gè)數(shù)組作為了堆棧區(qū)。這條語(yǔ)句使用了__attribute__ ((section(".stackarea"))),把數(shù)組定位在了.stackarea這個(gè)段中。
typedef void (* pfnISR)(void);
__attribute__ ((section(".isr_vector")))
pfnISR VectorTable[]={
(pfnISR)((unsigned long)pulStack + sizeof(pulStack)),
ResetISR, //初始化堆棧
NMIException, //復(fù)位句柄
HardFaultException
};
定義了一個(gè)數(shù)組VectorTable,作為向量表,定位于.isr_vector段中。通過(guò)鏈接腳本的控制,這個(gè)表將放在正文區(qū)的最開(kāi)始,正文區(qū)又將從Flash開(kāi)始存放,這樣這個(gè)向量表就會(huì)起到存放在0x00000000開(kāi)始的地址空間的效果。向量表的第0個(gè)單元是((unsigned long)pulStack+sizeof(pulStack)),這是數(shù)組的最后一個(gè)元素,因?yàn)镃ortexM3的堆棧是向下增長(zhǎng)的。 向量表的第1個(gè)單元是ResetISR,它指向復(fù)位處理的代碼也是整個(gè)程序的入口。本程序用它來(lái)實(shí)現(xiàn)啟動(dòng)代碼的功能。
extern unsigned long _etext;
extern unsigned long _data;
extern unsigned long _edata;
extern unsigned long _bss;
extern unsigned long _ebss;
void ResetISR(void){
unsigned long *pulSrc, *pulDest; //將保存于Flash中的初始化數(shù)據(jù)復(fù)制到SRAM中
pulSrc=_etext;
for(pulDest=_data; pulDest _edata;){
*pulDest++=*pulSrc++;
} // 將.bss段清零
for(pulDest=_bss; pulDest_ebss;){
*pulDest++=0;
}
main(); //最后調(diào)用main進(jìn)入主程序
}
這段代碼用到了通過(guò)連接器賦值的幾個(gè)變量值。_etext的值為正文段結(jié)尾處的地址,這之后的Flash空間是初始化的數(shù)據(jù)值,應(yīng)該復(fù)制到SRAM中去。_data、_edata的值分別為數(shù)據(jù)段的開(kāi)始和結(jié)尾處的地址,這部分應(yīng)該是SRAM的地址。
這部分代碼的主要功能就是將保存于Flash中的初始化數(shù)據(jù)復(fù)制到SRAM中。然后將.bss段清零。最后調(diào)用main進(jìn)入到我們的主程序。
3.2 Gcc二次開(kāi)發(fā)接口設(shè)計(jì)中的關(guān)鍵技術(shù)點(diǎn)
(1) 連接器中SysCallLib地址的賦值
連接器所做的工作簡(jiǎn)單地講就是把所有目標(biāo)文件相應(yīng)的段連接到一起,并把目標(biāo)文件中的“變量地址”、“函數(shù)地址”重新定位至正確的地址空間。通過(guò)在SECTIONS段中添加函數(shù)PROVIDE來(lái)聲明函數(shù)地址,代碼如下:
SECTIONS{
PROVIDE(SysCallLib= 0x08005935);
/*對(duì)于Cortex器件來(lái)說(shuō),啟動(dòng)代碼的開(kāi)始段VectorTable一般存儲(chǔ)在.isr_vector段中*/
.isr_vector :{
. =ALIGN(4);
KEEP(*(.isr_vector)) /*啟動(dòng)代碼*/
. = ALIGN(4);
} >FLASH
}
(2) 用戶程序Flash空間和SRAM空間的設(shè)定
對(duì)于STM32系列芯片來(lái)說(shuō)向量表、.text和.rodata就應(yīng)該放到從0x08000000開(kāi)始的Flash、.data、.bss和堆棧,就應(yīng)該定位至從0x20000000開(kāi)始的SRAM中。 但是對(duì)于用戶程序,這些地址空間都需要重新設(shè)定。這些定位都可以通過(guò)鏈接腳本進(jìn)行控制。
MEMORY{
FLASH(rx) :
ORIGIN=0x08000000, LENGTH=0x20000
SRAM (rwx):
ORIGIN=0x20000000, LENGTH=0x5000
}
這些語(yǔ)句說(shuō)明了Flash和SRAM開(kāi)始的地址以及大小。只需要修改這里,ORIGIN的值即可改變用戶程序存儲(chǔ)的物理地址,通過(guò)修改LENGTH來(lái)修改空間大小。
(3) SysCallLib函數(shù)的編寫
SysCallLib函數(shù)在系統(tǒng)程序中進(jìn)行編寫,主要通過(guò)Case語(yǔ)句來(lái)實(shí)現(xiàn)跳轉(zhuǎn)。形式如下:
void SysCallLib(unsigned int Index, int *Ret, unsigned char Argc, unsigned int Arg[]);
通過(guò)函數(shù)的參數(shù)來(lái)判斷需要調(diào)用的系統(tǒng)函數(shù)。通過(guò)把SysCallLib函數(shù)作為過(guò)渡函數(shù)來(lái)為用戶編寫全新的API函數(shù),用戶使用起來(lái)更加方便,以LCD顯示圖片的函數(shù)為例,代碼如下:
void mLCD_DisplayImage(unsigned char x, unsigned char y, const unsigned char *ImagePt, unsigned char ImageXSize, unsigned char ImageYSize ){
int RetVal;
unsigned int Arg[5];
unsigned char Argc=5;
Arg[0]=x;
Arg[1]=y;
Arg[2]=(unsigned int)ImagePt;
Arg[3]=ImageXSize;
Arg[4]=ImageYSize;
SysCallLib(_SYSCALL_LCD_DIS_IMAGE, RetVal, Argc, Arg);
}
用戶只需調(diào)用簡(jiǎn)單的API函數(shù)mLCD_DisplayImage即可在LCD上顯示圖片。
c語(yǔ)言相關(guān)文章:c語(yǔ)言教程
相關(guān)推薦
技術(shù)專區(qū)
- FPGA
- DSP
- MCU
- 示波器
- 步進(jìn)電機(jī)
- Zigbee
- LabVIEW
- Arduino
- RFID
- NFC
- STM32
- Protel
- GPS
- MSP430
- Multisim
- 濾波器
- CAN總線
- 開(kāi)關(guān)電源
- 單片機(jī)
- PCB
- USB
- ARM
- CPLD
- 連接器
- MEMS
- CMOS
- MIPS
- EMC
- EDA
- ROM
- 陀螺儀
- VHDL
- 比較器
- Verilog
- 穩(wěn)壓電源
- RAM
- AVR
- 傳感器
- 可控硅
- IGBT
- 嵌入式開(kāi)發(fā)
- 逆變器
- Quartus
- RS-232
- Cyclone
- 電位器
- 電機(jī)控制
- 藍(lán)牙
- PLC
- PWM
- 汽車電子
- 轉(zhuǎn)換器
- 電源管理
- 信號(hào)放大器
評(píng)論