實驗環境說明
硬件平臺:飛凌嵌入式OK210開發板(S5PV210)
說明:開發板已經刷入OK210原廠u-boot,本文程序直接下載進CPU iRAm中運行
軟件平臺:Ubuntu15.10 + arm-linux-gcc 4.4.3
初始化棧
1、C語言運行需要棧空間來存儲臨時變量和函數調用時的所佔用的空間。我們在操作系統下寫的應用程序以及其他一些單片機程序不需要設置棧是因爲,操作系統或者單片機內置的代碼已經初始化過棧空間,所以我們可以直接使用,但是ARM需要我們自己初始化棧。
2、棧又分爲,滿減棧,滿增棧,空增棧和空減棧之分。而ATPCS(ARM-THUMB procedure call standard(ARM-Thumb過程調用標準)的簡稱,PCS規定了應用程序的函數可以如何分開地寫,分開地編譯,最後將它們連接在一起,所以它實際上定義了一套有關過程(函數)調用者與被調用者之間的協議。)規定ARM使用的是滿減棧。所以初始化棧就是把棧指針指向棧的最高位地址即可。
3、S5PV210的CPU共有6個sp(r14)寄存器,即每種處理器模式下一個sp指針,也就是說每種處理器模式下都有一個棧。但是處理器復位後默認進入SVC模式,因此我們只用初始化SVC下的sp指針即可。
4、由於裸機程序並沒有初始化SDRAM所以棧只能設置爲iRAm的內存空間,關於棧的分配《S5PV210_iROM_ApplicationNote_Preliminary_20091126》中已經給出建議,
所以初始化棧的代碼如下
/* step 1: set SVC stack*/
ldr sp, =0xd0037d80
調用C函數
設置好棧後可以通過bl指令調用C語言函數,例如
bl led_blink
完整實驗程序如下
Makefile
arm-linux-ld -Ttext 0x0 -o led.elf $^
arm-linux-objcopy -O binary led.elf led.bin
arm-linux-objdump -D led.elf > led_elf.dis
%.o : %.S
arm-linux-gcc $(CFLAGS) -o $@ $< -c
%.o : %.c
arm-linux-gcc $(CFLAGS) -o $@ $< -c
clean:
rm -rf *.o *.elf *.bin *.dis
start.S
/*
*S5PV210 彙編調用C語言
*/
.global _start
_start:
/* step 1: set SVC stack*/
ldr sp, =0xd0037d80
/* step 2: call c function*/
bl led_blink
/* step 3: while(1) */
b .
led.c
#define GPH2_CON 0xE0200C40
#define GPH2_DAT 0xE0200C44
#define rGPH2_CON *((volatile unsigned int *)GPH2_CON)
#define rGPH2_DAT *((volatile unsigned int *)GPH2_DAT)
void delay(void);
void led_blink(void)
{
/* step 1: set GPH2_CON mode to GPIO output*/
/* GPH2_CON[0-3] all 0b0001 */
rGPH2_CON = 0x01111;
/* step 2: load off into GPH0_DAT*/
rGPH2_DAT = 0xFF; //all off
while(1)
{
rGPH2_DAT = 0X0;
delay();
rGPH2_DAT = 0XFF;
delay();
}
}
void delay(void)
{
volatile unsigned int i = 60000;
while(i--);
}