裸機(jī)_GPIO實(shí)驗(yàn)_C語(yǔ)言
引入:我們執(zhí)行C語(yǔ)言程序時(shí)候,Main函數(shù)是被誰(shuí)調(diào)用?執(zhí)行完要返回給誰(shuí)?
答:編譯器編譯代碼 = 啟動(dòng)文件(標(biāo)準(zhǔn)庫(kù)文件) + hello.c;由啟動(dòng)文件來(lái)調(diào)用main,最后main返回給啟動(dòng)文件。
思路回顧 啟動(dòng)文件標(biāo)準(zhǔn)庫(kù)文件是編譯器自動(dòng)在代碼前添加的,用來(lái)設(shè)置C程序的堆棧(無(wú)對(duì)戰(zhàn)空間沒(méi)法運(yùn)行C程序)等,然后調(diào)用main函數(shù)。所以我們執(zhí)行裸板的時(shí)候,需要自己寫(xiě)啟動(dòng)文件,來(lái)得以調(diào)用C代碼。
@******************************************************************************
@ File:crt0.S
@ 功能:通過(guò)它轉(zhuǎn)入C程序
@******************************************************************************
.text
.global _start
_start:
ldr r0, =0x53000000 @ WATCHDOG寄存器地址
mov r1, #0x0
str r1, [r0] @ 寫(xiě)入0,禁止WATCHDOG,否則CPU會(huì)不斷重啟
ldr sp, =1024*4 @ 設(shè)置堆棧,注意:不能大于4k, 因?yàn)楝F(xiàn)在可用的內(nèi)存只有4K
@ nand flash中的代碼在復(fù)位后會(huì)移到內(nèi)部ram中,此ram只有4K
bl main @ 調(diào)用C程序中的main函數(shù)
halt_loop:
b halt_loop
啟動(dòng)文件初始化兩部分:
C代碼軟件初始化:
0·設(shè)置棧(sp->SRAM)-SRAM不用初始化
1·設(shè)置返回地址
2·調(diào)用main
3·清理工作硬件初始化:
1·關(guān)看門(mén)狗
2·初始化時(shí)鐘(我們程序簡(jiǎn)單,速度慢點(diǎn)沒(méi)關(guān)系,這里沒(méi)用到)
3·初始化SDRAM(我們程序比較小,SRAM中4KB夠用了,這里沒(méi)用到)
#define GPFCON (*(volatile unsigned long *)0x56000050)
#define GPFDAT (*(volatile unsigned long *)0x56000054)
int main()
{
GPFCON = 0x00000100; // 設(shè)置GPF4為輸出口, 位[8:7]=0b01
GPFDAT = 0x00000000; // GPF4輸出0,LED1點(diǎn)亮
return 0;
}
Makefile關(guān)于
*(volatile unsigned long *)
的解釋請(qǐng)看點(diǎn)補(bǔ)充知識(shí)嵌入式中的*(volatile unsigned int *)
理解
led_on_c.bin : crt0.S led_on_c.c
arm-linux-gcc -g -c -o crt0.o crt0.S
arm-linux-gcc -g -c -o led_on_c.o led_on_c.c
#-g:加入調(diào)試信息 -c只編譯不連接
arm-linux-ld -Ttext 0x0000000 -g crt0.o led_on_c.o -o led_on_c_elf
#-Ttext 0x0000000:指定代碼段地址0
arm-linux-objcopy -O binary -S led_on_c_elf led_on_c.bin
# binary:二進(jìn)制的 -S:不從源文件復(fù)制重定位信息和符號(hào)信息到目標(biāo)文件中去
arm-linux-objdump -D -m arm led_on_c_elf >
led_on_c.dis
# -D:反匯編所有段 -m arm:指定反匯編文件使用arm架構(gòu)
clean:
rm -f led_on_c.dis led_on_c.bin led_on_c_elf *.o