文章和代碼已歸檔至【Github倉(cāng)庫(kù):hardware-tutorial】,需要的朋友們自取?;蛘吖娞?hào)【AIShareLab】回復(fù) 嵌入式 也可獲取。
一、實(shí)驗(yàn)?zāi)康?/p>
(1) 掌握建立基本完整的ARM 工程,包含啟動(dòng)代碼,C語(yǔ)言程序等;
(2) 了解ARM啟動(dòng)過(guò)程,學(xué)會(huì)編寫(xiě)簡(jiǎn)單的C 語(yǔ)言程序和匯編啟動(dòng)代碼并進(jìn)行調(diào)試;
(3) 掌握如何指定代碼入口地址與入口點(diǎn);
(4) 掌握通過(guò)memory/register/watch/variable 窗口分析判斷結(jié)果。
二、實(shí)驗(yàn)環(huán)境
硬件:PC機(jī)。
軟件:ADS1.2 集成開(kāi)發(fā)環(huán)境
三、實(shí)驗(yàn)內(nèi)容
使用匯編語(yǔ)言編寫(xiě)初始化程序,并引導(dǎo)至C語(yǔ)言main函數(shù),用匯編語(yǔ)言編寫(xiě)延時(shí)函數(shù)實(shí)現(xiàn)毫秒級(jí)的延時(shí),在C語(yǔ)言中調(diào)用延時(shí)函數(shù),實(shí)現(xiàn)1s鐘定時(shí)。
四、實(shí)驗(yàn)要求
(1) 在ADS下創(chuàng)建一個(gè)工程armasmc,編寫(xiě)3個(gè)文件,如下圖所示:
其中一個(gè)初始化匯編語(yǔ)言文件Init.s,該文件中主要完成異常矢量表的建立,模式堆棧初始化,并將程序引導(dǎo)至C語(yǔ)言的main函數(shù)。
C語(yǔ)言程序保存為armasmc.c。 C語(yǔ)言中調(diào)用匯編語(yǔ)言文件delay.s中的毫秒延時(shí)程序delayxms,C語(yǔ)言將延時(shí)的毫秒數(shù)通過(guò)參數(shù)傳遞到匯編語(yǔ)言,匯編語(yǔ)言完成延時(shí),然后返回C語(yǔ)言函數(shù)。
通過(guò)AXD運(yùn)用單步執(zhí)行方式調(diào)試程序。觀察程序執(zhí)行過(guò)程中的寄存器及存儲(chǔ)器的變化情況。
(2)實(shí)驗(yàn)過(guò)程中請(qǐng)記錄并思考以下內(nèi)容:
1)如何建立異常矢量入口表?
2)如何在匯編語(yǔ)言中切換至C語(yǔ)言的main函數(shù)?。
3)如何在C語(yǔ)言中調(diào)用匯編語(yǔ)言函數(shù),并完成參數(shù)傳遞?
4)匯編語(yǔ)言函數(shù)中用到的寄存器如何保護(hù)與恢復(fù),為什么要保護(hù)參考程序中的R11?
5)將delay.s中的R11改成R4,并將兩條R11 的保護(hù)與恢復(fù)語(yǔ)句stmfd sp!,{r11} 和ldmfd sp!,{r11}刪掉,在C語(yǔ)言程序中的語(yǔ)句i–處設(shè)置端點(diǎn),觀察運(yùn)行過(guò)程中變量i的變化情況,并解釋其中的原因。
五、實(shí)驗(yàn)情況:
1、實(shí)驗(yàn)源代碼(含注釋?zhuān)?/p>
Init.s代碼:
;************************ entry.s ****************************
IMPORT Main ;在匯編程序調(diào)用該c程序前要在匯編語(yǔ)言程序中使用IMPORT偽操作來(lái)聲明該c程序
area Init,code,readonly ;定義CODE片段Init 只讀
entry ;設(shè)置程序入口偽指令
code32 ;以下為32位的ARM程序
; *********** Setup interrupt/exception vector *******************
start b Reset_Handler ;異常矢量表,根據(jù)異常矢量表進(jìn)入不同模式的中斷程序
Undefined_Handler b Undefined_Handler
SWI_Handler b SWI_Handler
Prefetch_handler b Prefetch_handler
Abort_Handler b Abort_Handler
nop ;Reserved vector
IRQ_Handler b IRQ_Handler
FIQ_Handler b FIQ_Handler
Reset_Handler ;Reset中斷,為整個(gè)中斷的實(shí)際入口點(diǎn)
bl initstack ;初始化各模式下的堆棧指針
;切換至用戶(hù)模式堆
msr cpsr_c,#0xd0 ;110 10000
bl Main
halt b halt
initstack mov r0,lr ;r0<--lr,因?yàn)楦鞣N模式下r0是相同的而各個(gè)模式?
;設(shè)置管理模式堆棧
msr cpsr_c,#0xd3 ;110 10011
ldr sp,stacksvc
;設(shè)置中斷模式堆棧
msr cpsr_c,#0xd2 ;110 10010
ldr sp,stackirq
;設(shè)置快速中斷模式堆棧
msr cpsr_c,#0xd1 ;110 10001
ldr sp,stackfiq
;設(shè)置中止模式堆棧
msr cpsr_c,#0xd7 ;110 10111
ldr sp,stackabt
;設(shè)置未定義模式堆棧
msr cpsr_c,#0xdb ;110 11011
ldr sp,stackund
;設(shè)置系統(tǒng)模式堆棧
msr cpsr_c,#0xdf ;110 11111
ldr sp,stackusr
mov pc,r0 ;返回
LTORG
stackusr dcd usrstackspace+128
stacksvc dcd svcstackspace+128
stackirq dcd irqstackspace+128
stackfiq dcd fiqstackspace+128
stackabt dcd abtstackspace+128
stackund dcd undstackspace+128
area Interrupt,data,READWRITE ;分配堆??臻g
usrstackspace space 128
svcstackspace space 128
irqstackspace space 128
fiqstackspace space 128
abtstackspace space 128
undstackspace space 128
end
delay.s代碼:
;************************* delay.s *****************************
EXPORT delayxms ;EXPORT偽指令用于在程序中聲明一個(gè)全局的標(biāo)號(hào),該標(biāo)號(hào)可在其他的文件中引用
area delay,code,readonly ;定義code片段delay只讀
code32 ;以下為32位的ARM程序
;下面是延時(shí)若干ms的子程序
delayxms
stmfd sp!,{r11} ; 寄存器入棧
sub r0,r0,#1 ;r0=r0-1
ldr r11,=1000 ;加載至r11中
loop2
sub r11,r11,#1 ;每次將r11自減一
cmp r11,#0x0 ;將r11與0比較
bne loop2 ;比較的結(jié)果不為0,則繼續(xù)調(diào)用loop2
cmp r0,#0x0 ;將r0與0比較
bne delayxms ;比較的結(jié)果不為0,則繼續(xù)調(diào)用delayxms
ldmfd sp!,{r11};
mov pc,lr;返回
end
armasmc.c代碼:
//*************************armasmc.c******************************
#include <stdio.h>
int Main()
{
extern void delayxms(int xms); //在C程序調(diào)用匯編程序之前需要在C語(yǔ)言程序中使用extern關(guān)鍵詞來(lái)聲明該匯編程序
int i=100;
while(1)
{
delayxms(1000); // 調(diào)用delayxms匯編程序
i--;
if(i==0)
i=100;
}
return 0;
}
2、實(shí)驗(yàn)過(guò)程(含結(jié)果截圖及相應(yīng)文字解釋?zhuān)?/p>
1.如何建立異常矢量入口表?
答:建立異常矢量入口表需要設(shè)置中斷類(lèi)型號(hào),并且要設(shè)置中斷服務(wù)子程序段地址,以根據(jù)異常矢量表進(jìn)入不同模式的中斷程序。在實(shí)驗(yàn)程序中也有定義:
2.如何在匯編語(yǔ)言中切換至C語(yǔ)言的main函數(shù)?
答:由上代碼可知,為保證程序調(diào)用時(shí)參數(shù)的正確傳遞,匯編程序設(shè)計(jì)要遵守ATPCS(ARM-Thumb Produce Call Standard),它是ARM程序和Thumb程序中子程序調(diào)用的基本規(guī)則,目的是為了使單獨(dú)編譯的C語(yǔ)言程序和匯編程序之間能夠相互調(diào)用。這些基本規(guī)則包括子程序調(diào)用過(guò)程中寄存器的使用規(guī)則、數(shù)據(jù)棧的使用規(guī)則和參數(shù)的傳遞規(guī)則。在C程序中不需要任何關(guān)鍵字來(lái)聲明將被匯編語(yǔ)言調(diào)用的C程序,但需要在匯編語(yǔ)言程序之前使用IMPORT偽操作來(lái)聲明該C程序。在匯編程序中通過(guò)BL指令來(lái)調(diào)用子程序。同時(shí),匯編程序可以通過(guò)地址間接訪問(wèn)在C語(yǔ)言程序中聲明的全局變量。通過(guò)使用IMPORT關(guān)鍵詞引入全局變量,并利用LDR和STR指令根據(jù)全局變量的地址可以訪問(wèn)它們。
3.如何在C語(yǔ)言中調(diào)用匯編語(yǔ)言函數(shù),并完成參數(shù)傳遞?
答:為了保證程序調(diào)用時(shí)參數(shù)的正確傳遞,匯編程序設(shè)計(jì)要遵守ATPCS。在匯編程序中需要使用EXPORT偽操作來(lái)聲明,同時(shí),在C程序中調(diào)用該匯編程序之前需要在C語(yǔ)言程序中使用extern關(guān)鍵詞來(lái)聲明該匯編程序。
4.匯編語(yǔ)言函數(shù)中用到的寄存器如何保護(hù)與恢復(fù),為什么要保護(hù)參考程序中的R11?
答:匯編語(yǔ)言函數(shù)中用到的寄存器通過(guò)壓棧來(lái)保護(hù),出棧來(lái)恢復(fù)。根據(jù)ATPCS規(guī)則,R11對(duì)應(yīng)ARM 狀態(tài)局部變量寄存器8,R11中含有循環(huán)次數(shù)的重要參量,因此要保護(hù)R11避免在程序運(yùn)行與調(diào)用過(guò)程中受到影響而導(dǎo)致程序異常。
5.將delay.s中的R11改成R4,并將兩條R11 的保護(hù)與恢復(fù)語(yǔ)句stmfd sp!,{r11} 和ldmfd sp!,{r11}刪掉,在C語(yǔ)言程序中的語(yǔ)句i–處設(shè)置端點(diǎn),觀察運(yùn)行過(guò)程中變量i的變化情況,并解釋其中的原因。
修改程序如下:
答:由上可知R4對(duì)應(yīng)局部變量寄存器1,即變量i,因此在子程序delay.s中,R4的值減為0,若不進(jìn)行保護(hù),則返回C程序后自減-1,導(dǎo)致變量i的值變?yōu)?1,此時(shí)將無(wú)法滿(mǎn)足0的條件,也就無(wú)法執(zhí)行if,導(dǎo)致i會(huì)一直遞減下去,最終無(wú)法停止。
六、總結(jié)文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-735171.html
本次有關(guān)匯編與C語(yǔ)言相互調(diào)用的部分,建立異常矢量入口表的方法,即需要設(shè)置中斷類(lèi)型號(hào),并且要設(shè)置中斷服務(wù)子程序段地址,以根據(jù)異常矢量表進(jìn)入不同模式的中斷程序。此外,還有ARM程序和Thumb程序中子程序調(diào)用的基本規(guī)則ATPCS(ARM-Thumb Produce Call Standard),目的是為了使單獨(dú)編譯的C語(yǔ)言程序和匯編程序之間能夠相互調(diào)用。這些基本規(guī)則包括子程序調(diào)用過(guò)程中寄存器的使用規(guī)則、數(shù)據(jù)棧的使用規(guī)則和參數(shù)的傳遞規(guī)則,為調(diào)用提供了相關(guān)的規(guī)范。其中匯編程序訪問(wèn)全局C變量的方法是:匯編程序可以通過(guò)地址間接訪問(wèn)在C語(yǔ)言程序中聲明的全局變量。通過(guò)使用IMPORT關(guān)鍵詞引入全局變量,并利用LDR和STR指令根據(jù)全局變量的地址可以訪問(wèn)它們。在C語(yǔ)言程序中調(diào)用匯編程序的方法是:在匯編程序中需要使用EXPORT偽操作來(lái)聲明,使得本程序可以被其它程序調(diào)用。同時(shí),在C程序調(diào)用該匯編程序之前需要在C語(yǔ)言程序中使用extern關(guān)鍵詞來(lái)聲明該匯編程序。而在匯編程序中調(diào)用C語(yǔ)言程序的方法是:在C程序中不需要使用任何關(guān)鍵字來(lái)聲明將被匯編語(yǔ)言調(diào)用的C程序,但是在匯編程序調(diào)用該C程序之前需要在匯編語(yǔ)言程序中使用IMPORT偽操作來(lái)聲明該C程序。在匯編程序中通過(guò)BL指令來(lái)調(diào)用子程序。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-735171.html
到了這里,關(guān)于嵌入式ARM設(shè)計(jì)編程(四) ARM啟動(dòng)過(guò)程控制的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!