在前邊我們使用匯編完成了一個流水燈實驗: Tiny4412匯編流水燈代碼,Tiny4412裸機LED操作
但是,匯編語言可讀性太差,在這一節(jié)我們用 C語言來實現(xiàn)了同樣的功能,而以后的試驗也盡量用 C語言實現(xiàn)。
我們在編寫上位機程序時,C語言程序執(zhí)行的第一條指令,并不在main函數(shù)中。生成一個 C程序的可執(zhí)行文件時,編譯器通常會在我們的代碼中加上幾個被稱為啟動文件的代碼—— crtl.o 、crti.o、crtend.o 、crtn.o 等,它們是標準庫文件。這些代碼設(shè)置C程序的堆棧等,然后調(diào)用 main 函數(shù)。它們依賴于操作系統(tǒng),在裸板上這些代碼無法執(zhí)行,所以需要自己寫一個。
這段代碼很簡單, 關(guān)鍵指令只有2條。自己編寫的 start .S啟動文件內(nèi)容如下:
====================================================================
.text
.globl _start
_start:
ldr sp, =0x02027800
// 調(diào)用C函數(shù)之前必須設(shè)置棧,棧用于保存運行環(huán)境,給局部變量分配空間
// 參考ROM手冊P14, 我們把棧指向BL2上方1K處(1K已經(jīng)夠用),
//0x02020000 (iRAM基地址) + 5K(iROM代碼用) + 8K(BL1用) + 16K(BL2用) + 1K(用作棧)
bl main // 調(diào)用main函數(shù)(main這個名稱不是固定的,可以隨意改)
halt_loop:
b halt_loop
====================================================================
它在第 4行設(shè)置好棧指針后,就可以通過第8行調(diào)用C函數(shù) main了--------------- C函數(shù)執(zhí)行前,必須設(shè)置棧。
問:CPU不是有看門狗嘛?為什么沒有看到關(guān)看門狗的代碼?這樣程序能正常運行嗎?
答:在上一篇文章《Exynos 4412的啟動過程分析》中,我們已經(jīng)介紹過了,在執(zhí)行我們的程序前,CPU會首先執(zhí)行iROM中的代碼和BL1的代碼,在這兩部分程序中會關(guān)閉看門狗。
其實我們自己關(guān)閉看門狗也很簡單,只需往寄存器WTCON寫入0即可;
問:為什么調(diào)用C函數(shù)要設(shè)置棧?
答:1. 棧的整體作用
1) 保存現(xiàn)場;
2) 傳遞參數(shù):匯編代碼調(diào)用C函數(shù)時,需傳遞參數(shù);
3) 保存臨時變量:包括函數(shù)的非靜態(tài)局部變量以及編譯器自動生成的其他臨時變量;
2. 詳細解釋
1)保存現(xiàn)場
現(xiàn)場,意思就相當(dāng)于案發(fā)現(xiàn)場,總有一些現(xiàn)場的情況,要記錄下來的,否則被別人破壞掉之后,你就無法恢復(fù)現(xiàn)場了。而此處說的現(xiàn)場,就是指CPU運行的時候,用到了一些寄存器,比如r0,r1等等,對于這些寄存器的值,如果你不保存而直接跳轉(zhuǎn)到子函數(shù)中去執(zhí)行,那么很可能就被其破壞了,因為其函數(shù)執(zhí)行也要用到這些寄存器。因此,在函數(shù)調(diào)用之前,應(yīng)該將這些寄存器等現(xiàn)場,暫時保持起來(入棧push),等調(diào)用函數(shù)執(zhí)行完畢返回后(出棧pop),再恢復(fù)現(xiàn)場。這樣CPU就可以正確的繼續(xù)執(zhí)行了。保存寄存器的值,一般用的是push指令,將對應(yīng)的某些寄存器的值,一個個放到棧中,把對應(yīng)的值壓入到棧里面,即所謂的壓棧。然后待被調(diào)用的子函數(shù)執(zhí)行完畢的時候,再調(diào)用pop,把棧中的一個個的值,賦值給對應(yīng)的那些你剛開始壓棧時用到的寄存器,把對應(yīng)的值從棧中彈出去,即所謂的出棧。其中保存的寄存器中,也包括lr的值(因為用bl指令進行跳轉(zhuǎn)的話,那么之前的PC的值是存在lr中的),然后在子程序執(zhí)行完畢的時候,再把棧中的lr的值pop出來,賦值給PC,這樣就實現(xiàn)了子函數(shù)的正確的返回。
2)傳遞參數(shù)
C語言進行函數(shù)調(diào)用的時候,常常會傳遞給被調(diào)用的函數(shù)一些參數(shù),對于這些C語言級別的參數(shù),被編譯器翻譯成匯編語言的時候,就要找個地方存放一下,并且讓被調(diào)用的函數(shù)能夠訪問,否則就沒發(fā)實現(xiàn)傳遞參數(shù)了。對于找個地方放一下,分兩種情況。一種情況是,本身傳遞的參數(shù)不多于4個,就可以通過寄存器r0~r3傳送參數(shù)。因為在前面的保存現(xiàn)場的動作中,已經(jīng)保存好了對應(yīng)的寄存器的值,那么此時,這些寄存器就是空閑的,可以供我們使用的了,那就可以放參數(shù)。另一種情況是,參數(shù)多于4個時,寄存器不夠用,就得用棧了。
3)臨時變量保存在棧中
包括函數(shù)的非靜態(tài)局部變量以及編譯器自動生成的其他臨時變量。
現(xiàn)在,我們可以很容易寫出控制 LED 的程序了。畢竟是用C語言嘛,相當(dāng)?shù)撵`活。 main 函數(shù)在 led.c 文件中,代碼如下:
#define GPM4CON (*(volatile unsigned int *)0x110002E0)
#define GPM4DAT (*(volatile unsigned int *)0x110002E4)
void delay(volatile int time)
{
for(; time > 0; time-- );
}
int main(void)
{
unsigned long tmp = 0;
int i = 0;
// GPM4_0-GPM4_3 設(shè)置為輸出功能
tmp = GPM4CON;
tmp &= ~0xffff;
tmp |= 0x1111;
GPM4CON = tmp;
// 實現(xiàn)流水燈
while(1)
{
GPM4DAT = i;
if (++i == 16)
i = 0;
delay(9999999);
}
return 0;
}
來看看Makefile:
====================================================================
objs := start.o led.o
led.bin : $(objs)
arm-linux-ld -Tled.lds -N -o led.elf $^
arm-linux-objcopy -O binary -S led.elf $@
arm-linux-objdump -D -m arm led.elf > led.dis
%.o:%.c
arm-linux-gcc -Wall -marm -c -O2 -o $@ $<
%.o:%.S
arm-linux-gcc -Wall -marm -c -O2 -o $@ $<
clean:
rm -f *.dis *.bin *.elf *.o
====================================================================
執(zhí)行 make 命令時,它的目是去生成第1個目標,即 led.bin ;
led.bin 依賴于start.o 和 led.o,所以要先生成這 2個.o 文件;
start.o 依賴于start.S ,符合第 11 行的規(guī)則,會使用第 12 行的命令生成start.o ;
類似的, led.o 依賴于led.c ,符合第 8行的規(guī)則,會使用第 9行的命令生成 led.o ;
當(dāng)這 2個.o 文件都生成之后,就會執(zhí)行第 4~6行的命令生成 led.bin文件: 第 4行將編譯得到的 .o 文 件連接為led.elf
可執(zhí)行程序,第 5行是生成二進制格式的可執(zhí)行程序,第 6行是得到反匯編程序以供查看。
鏈接腳本還和匯編流水燈一樣。
好了,下面開始驗證我們的程序了。
1.將程序源碼上傳到服務(wù)器,并執(zhí)行make,生成led.bin文件。
2.借鑒上一個實驗的步驟,將程序燒寫到SD卡。
3.將SD卡插到Tiny4412開發(fā)板,上電即可看到流水燈效果(和匯編流水燈效果一樣)。
Tiny4412 流水燈
上一篇:Exynos4412按鍵檢測(輪詢方式)
下一篇:Exynos4412的啟動過程分析
推薦閱讀
史海拾趣
設(shè)計資源 培訓(xùn) 開發(fā)板 精華推薦
- EEworld&TI 喊你來玩BLE+ZigBee+6lowpan!
- 解鎖 TE 掌上信息智庫,獲取一站式資源!
- ADI有獎下載活動之16 太陽能光伏逆變器解決方案
- 你評論,我送禮!《玩轉(zhuǎn)TI MSP430 Launchpad》TI社區(qū)與EEWORLD聯(lián)合首發(fā)!
- 有獎活動 | 來 Pl BridgeSwitch™ 技術(shù)中心探秘半橋電機驅(qū)動器新技術(shù)
- 閱讀 TI工業(yè)應(yīng)用方案(電器、電力傳輸)精彩專題,挑戰(zhàn)你的記憶力!好禮相送
- 參加MSP430F5529培訓(xùn),長知識、免費送、超低團、搶樓得!