http://blog.csdn.net/zhanglianpin/article/details/35772723
2014
1:主要內(nèi)容
在嵌入式開發(fā)中,一般使用匯編語言做一些芯片初始化工作,當(dāng)對程序效率要求很高時,也有時會使用匯編語言,但匯編語言相對較難閱讀和理解。因此,我們希望我們以后的實(shí)驗(yàn)在初始化完芯片相關(guān)功能后使用C語言進(jìn)行編程,方便大家閱讀及理解。這一篇的內(nèi)容主要是講解使用C語言來控制LED燈閃爍。
2:相關(guān)要點(diǎn)
1,在通用PC機(jī)上寫程序都有一個叫做main的函數(shù),是程序的總?cè)肟?。在嵌入式開發(fā)時,怎么從匯編語言跳轉(zhuǎn)到C語言?在跳轉(zhuǎn)之前需要設(shè)置哪些東西?
2:,在ARM體系中,匯編和C語言之間相互調(diào)用時參數(shù)如何傳遞?
關(guān)于上面的兩個疑問,我不在這里詳細(xì)分析。我給出參考資料,大家自行參考,思索。
針對問題1: ucos在s3c2410上運(yùn)行過程整體剖析之基礎(chǔ)知識-c語言和堆棧
針對問題2:參見資料 ATPCS.pdf
3:實(shí)驗(yàn)源碼
initsystem.s
- @******************************************************************************
- @ 文件名 :initsystem.s
- @ 功 能:初始化系統(tǒng)并copy代碼
- @
- @ 作者 :張連聘
- @ 創(chuàng)建時間:2014-06-22
- @******************************************************************************
-
- .text
- .global _start
-
-
- @聲明常量
- .equ DATA_DST,0x40000000 @目的地址
- .equ DATA_SRC,0x80000000 @源地址
-
- @引入外部標(biāo)號
- .extern main
- .extern start_copy_addr
-
- _start:
-
-
-
- LDR PC, ResetAddr
-
- ResetAddr: .word ResetInit
-
- ResetInit:
-
- LDR R0,=DATA_DST @RO 指向目的地址
- LDR R1,=start_copy_addr @R1 指向源地址
- MOV R10,#128 @復(fù)制的個數(shù)為128*8*4=4K
- CopyLoop: <span style="white-space:pre"> </span>LDMIA R1!,{R2-R9} @從R1指定的內(nèi)存地址處裝載數(shù)據(jù)到R2--R9中
- STMIA R0!,{R2-R9} @把R2--R9的數(shù)據(jù)復(fù)制到R0指定的內(nèi)存中
- SUBS R10,R10,#1
- BNE CopyLoop
- LDR SP,=0X40000000+1024*64 @設(shè)置堆棧指針,LPC2220內(nèi)部有64KRAM,設(shè)置SP指針指向最高地址
-
- LDR PC,=main @調(diào)用C語言的main函數(shù)
- HaltLoop:
- B HaltLoop
- .end
main.c
- /******************************************************************************
- * 文件名 :main.c
- * 功 能:利用P2.28控制led燈閃爍
- *
- * 作者 :張連聘
- * 創(chuàng)建時間:2014-06-25
- *******************************************************************************/
-
- //定義一些控制寄存器地址
-
- #define IO2DIR (*(volatile unsigned long *)0xE0028028) //IO2輸入、輸出配置寄存器
- #define IO2SET (*(volatile unsigned long *)0xE0028024) //IO2輸出1控制寄存器
- #define IO2CLR (*(volatile unsigned long *)0xE002802C) //IO2輸出0控制寄存器
-
- #define LEDCON (1<<28)
-
- void Delay(int ms);
- void main(void)
- {
-
- IO2DIR = LEDCON; //配置P2.28為輸出口
- while (1)
- {
- IO2SET = LEDCON; //點(diǎn)亮LED燈
- Delay(6666);
- IO2CLR = LEDCON; //熄滅LED燈
- Delay(6666);
- }
- }
- /******************************************************************************
- * 名 稱:Delay
- * 功 能:軟件延時
- * 入口參數(shù):ms
- * 出口參數(shù):無
- ******************************************************************************/
- void Delay(int ms)
- {
- int i,j;
- for(i=0;i<10;i++)
- for(j=0;j<ms;j++)
- ;
- }
-
-
-
-
-
led_control.lds
- /*
- * led_control 的鏈接腳本。
- *
- *
- */
-
- MEMORY
- {
- rom (rx) : ORIGIN = 0x80000000, LENGTH = 2M
- ram (!rx) : ORIGIN = 0x40000000, LENGTH = 2M
- }
- ENTRY(_start)
- SECTIONS
- {
-
- . = 0x80000000 ;
- .init :
- {
- initsystem.o(.text)
- start_copy_addr = . ;
- } >rom
- . = 0x40000000 ;
- .main :
- AT (ADDR(.init)+SIZEOF(.init))
- {
- main.o(.text)
- } >ram
-
-
-
-
- }
makefile
- control_led.bin:main.c initsystem.s
- arm-linux-gcc -g -c -o main.o main.c
- arm-linux-gcc -g -c -o initsystem.o initsystem.s
- arm-linux-ld -Tled_control.lds -nostdlib -g main.o initsystem.o -o control_led_elf
- arm-linux-objcopy -O binary -S control_led_elf control_led.bin
- clean:
- rm -f control_led.bin control_led_elf *.o
4:源碼重點(diǎn)分析
我們在main.c里定義了一個main函數(shù),那我們在匯編代碼里怎么引用吶?
.extern main 聲明在另一個文件中定義了main函數(shù)。然后LDR PC,=main 跳轉(zhuǎn)到main函數(shù)。這里說明一下,之所以不能使用BL指令跳轉(zhuǎn),是因?yàn)閱哟a執(zhí)行的地址在0X80000000 ,而啟動代碼將main函數(shù)代碼copy到0X40000000。Bl的跳轉(zhuǎn)范圍沒有這么大。還有,這個main函數(shù)完全可以更改為其他函數(shù),只是一個普通的函數(shù)名稱。
LDR SP,=0X40000000+1024*64 使用這條指令,是設(shè)置SP堆棧指針的位置。這里講堆棧指針設(shè)置在了LPC2220這款芯片的內(nèi)部RAM的最頂端。默認(rèn)的ARM處理器是遞減堆棧。
5:總結(jié)
由上面的實(shí)驗(yàn)可見,PC機(jī)編程時的main函數(shù)只是一個普通的函數(shù)名稱,只不過他們底層設(shè)置好了,調(diào)用main函數(shù),所以我們一般說普通PC機(jī)程序總?cè)肟谑莔ain函數(shù)。其實(shí),在main函數(shù)之前已經(jīng)做了很多工作。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點(diǎn)擊舉報(bào)。