日韩一区二区三区精品,欧美疯狂xxxxbbbb牲交,热99re久久免费视精品频,人妻互换 综合,欧美激情肉欲高潮视频

歷史上的今天

今天是:2024年10月14日(星期一)

正在發(fā)生

2018年10月14日 | Exynos4412之C語言實現(xiàn)流水燈

發(fā)布者:jingyan 來源: eefocus關(guān)鍵字:Exynos4412  C語言  流水燈 手機看文章 掃描二維碼
隨時隨地手機看文章

在前邊我們使用匯編完成了一個流水燈實驗: 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 流水燈

Tiny4412 流水燈


關(guān)鍵字:Exynos4412  C語言  流水燈 引用地址:Exynos4412之C語言實現(xiàn)流水燈

上一篇:Exynos4412按鍵檢測(輪詢方式)
下一篇:Exynos4412的啟動過程分析

推薦閱讀

汽車行業(yè)是使用人工智能(AI)來模仿、增強和支持人類行為的前沿領(lǐng)域。利用先進的基于機器的精確定位系統(tǒng),現(xiàn)在的半自動駕駛汽車和未來的完全自動駕駛汽車將依賴AI系統(tǒng)來執(zhí)行各種任務(wù)。根據(jù)Tractica的最新分析,雖然自動駕駛將成為人工智能在汽車行業(yè)消費的主要動力,但AI在汽車行業(yè)的用例實際上要廣泛得多,包括汽車人機交互(HMI)功能,如語音/語音識別...
加拿大EMS企業(yè)增強安大略省生產(chǎn)基地的原型制造/新品導(dǎo)入功能。 來自加拿大的SigmaPoint科技公司,為了增強其在物聯(lián)網(wǎng)領(lǐng)域的競爭力,在安大略省基奇納市的Catalyst 137物聯(lián)網(wǎng)制造中心,設(shè)立一個面積達1,500平方米,技術(shù)先進的原型構(gòu)造/新品導(dǎo)入中心,并為此添置第二臺環(huán)球儀器Fuzion2-37?貼片機,以此來增強其高產(chǎn)出、及靈活應(yīng)對新產(chǎn)品的能力。 作為一家E...
先說一下,為什么要用14位AD。 最早TEK在設(shè)計第1臺便攜示波器的時候,TDS1000、2000系列采用的是 5寸 屏幕,其垂直分辨率是240,這時選擇8位AD即2的8次方=256點正好跟屏幕匹配,當(dāng)設(shè)計TDS3000的時候,其屏幕為6.5英寸,垂直分辨率為480,所以TEK選擇了9位AD(512點),屏幕和AD也恰好匹配。隨著現(xiàn)在數(shù)字示波器屏幕越來越大,而大多數(shù)廠家仍然使用8位AD,...
廣告摘要聲明廣告【文/伍勿武】10月12日晚間,諾力股份發(fā)布公告稱,全資子公司中鼎集成與廣東瑞慶時代新能源科技有限公司(以下簡稱“廣東瑞慶時代?)簽訂了建設(shè)自動倉儲系統(tǒng)的合同,合同總金額約為2.39億元。其中,廣東瑞慶時代為寧德時代新能源科技股份有限公司的全資子公司。諾力股份表示,該合同的簽訂有利于鞏固中鼎集成在倉儲物流、特別是新能源領(lǐng)域...

史海拾趣

小廣播
設(shè)計資源 培訓(xùn) 開發(fā)板 精華推薦

最新單片機文章

 
EEWorld訂閱號

 
EEWorld服務(wù)號

 
汽車開發(fā)圈

 
機器人開發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號 京ICP備10001474號-1 電信業(yè)務(wù)審批[2006]字第258號函 京公網(wǎng)安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved