ARM Coretex-A的不同模式
為了盡可能的保護(hù)計(jì)算機(jī)資源(CPU、內(nèi)存、IO等),不同的CPU架構(gòu)實(shí)現(xiàn)了不同的權(quán)限等級(jí),等級(jí)越高可訪問的系統(tǒng)資源越多(包括執(zhí)行一些特權(quán)指令),這是因?yàn)槠胀ㄓ脩艏?jí)別的程序代碼質(zhì)量不能得到完全的保障,為了更好的保護(hù)計(jì)算機(jī)資源會(huì)讓用戶級(jí)別的代碼工作在盡可能少的訪問系統(tǒng)資源的模式下,而像操作系統(tǒng)這樣經(jīng)過千錘百煉的程序質(zhì)量有保障,CPU可以放心的把計(jì)算機(jī)資源交出來讓操作系統(tǒng)可以隨意訪問。
在當(dāng)前的實(shí)驗(yàn)中,由于我們是工作在祼機(jī)狀態(tài)下的程序,可以簡單的認(rèn)為我們的代碼與操作系統(tǒng)代碼是一個(gè)級(jí)別的,就算代碼有問題那從CPU的角度來講我們的祼機(jī)代碼也是高質(zhì)量的,也就是說可以工作在高等級(jí)權(quán)限的模式下。
ARM Coretex-A
系列處理器有以下幾種工作模式:其中,
SVC
是超級(jí)管理員模式,可以訪問所有的計(jì)算機(jī)資源。
設(shè)置CPU工作模式為SVC
Coretex-A
提供了一個(gè)專門的寄存器CPSR
程序狀態(tài)寄存器來控制當(dāng)前CPU的工作模式, CPSR
的每一位的邏輯如下:
其中的低5位M[4:0]用于指定當(dāng)前CPU的工作模式,具體表格如下:
M[4:0] | CPU工作模式 |
---|---|
10000 | User模式 |
10001 | FIQ模式 |
10010 | IRQ模式 |
10011 | Supervisor(SVC)模式 |
10110 | Monitor(MON)模式 |
10111 | Abort(ABT)模式 |
11010 | Hyp(HYP)模式 |
11011 | Undef(UND)模式 |
11111 | System(SYS)模式 |
通過表格可以看出,如果要設(shè)置成SVC
模式,則需要將CPSR
寄存器的低5位M[4:0]設(shè)置成10011
讀寫CRSR
寄存的操作指令與讀取通用寄存器使用的ldr
與str
不要樣,需要使用mrs
讀取CPSR
的數(shù)據(jù),msr
向CPSR
寫入數(shù)據(jù)。
/// 將cpsr寄存器中的數(shù)據(jù)讀取到r0
/// 這是因?yàn)閏psr是不能使用運(yùn)算符指令對(duì)其進(jìn)行直接的操作的,需要使用通用寄存器
mrs r0, cpsr
/// 通過使用bic指令將,r0的低5位都清空,這里使用了0x1f=11111. bic指令后面的操作數(shù)掩碼位的值是1表示將此位清空,否則保持不變
bic r0, r0, #0x1f
/// 通過orr(或)指令將r0寄存器中的低5位設(shè)置成10011
orr r0, r0, #0x13
/// 將r0的數(shù)據(jù)寫入cprs寄存器,完成svc模式切換
msr cprs, r0
設(shè)置C語言運(yùn)行環(huán)境
C語言要工作,需要指定一個(gè)??臻g,通過指定sp
指針就可以給C語言開辟一塊棧空間。
Coretex-A
的棧是向下生長的,也就是從高地址向低地址生成(即棧頂在高地址)。I.MX6ULL
的DDR
的起始地址是0x80000000,這里設(shè)置一個(gè)2MB的空間大小,實(shí)際上也可以設(shè)置成1MB或者512KB也是完全夠用的。所以需要設(shè)置sp
指針的初始位置是0x802000000.
/// 設(shè)置sp指針地址
ldr sp, =0x80200000
/// 跳轉(zhuǎn)到c語言的main函數(shù)開始執(zhí)行
b main
編寫C語言LED驅(qū)動(dòng)程序
- 1.使能CCM_CCGR1
#define CCM_CCGR1 *((volatile unsigned int *)0x020C406C)
CCM_CCGR1 = 0xFFFFFFFF;
- 2.復(fù)用
SW_MUX_CTL_PAD_GPIO1_IO03
為GPIO1_IO03
#define MUX_CTL_PAD_GPIO1_IO03 *((volatile unsigned int *)0x020E0068)
MUX_CTL_PAD_GPIO1_IO03 = 0x5; /// 10011
- 3.配置
SW_PAD_CTL_PAD_GPIO1_IO03
電氣屬性
#define SW_PAD_CTL_PAD_GPIO1_IO03 *((volatile unsigned int *)0x020E02F4)
SW_PAD_CTL_PAD_GPIO1_IO03 = 0x10B0
- 4.設(shè)置GPIO1_GDIR的信號(hào)輸出方向
#define GPIO01_GDIR *((volatile unsigned int *)0x0209C004)
GPIO01_GDIR = 0x08;
- 5.LED閃爍
#define GPIO01_DR *((volatile unsigned int *)0x0209C000)
void delay_ms(volatile unsigned int n) {
while (n--) { }
}
void delay(volatile unsigned int n) {
while (n--) {
delay_ms(0x7FF);
}
}
whilte(1) {
delay(500);
GPIO01_DR = 0x0;
delay(500);
GPIO01_DR = 0x8;
}
編譯代碼
- 編寫Makefile
/// 定義目標(biāo)文件變量
objs := start.o main.o
/// 生成ledc.bin,依賴objs
ledc.bin:${objs}
arm-linux-gnueabihf-ld -Ttext 0x87800000 -o ledc.elf $^ /// 將目標(biāo)文件鏈接生成ledc.elf $^表示所有依賴文件的集合,使用空格分開,去重
arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@ /// 將ledc.elf生成ledc.bin, $@指目標(biāo)集合,這里的目標(biāo)就是上面定義的ledc.bin
arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis /// 將ledc.elf反匯編成ledc.dis,主是要方便查看連接后的代碼段指令是否符合預(yù)期
/// 當(dāng)目標(biāo)文件沒有時(shí)會(huì)使用如下的模式規(guī)則去生成對(duì)應(yīng)的目標(biāo)文件
/// $@指要生成的.o文件, $<指生成.o的源文件,比如start.o:start.s, $@(start.o) $<(start.s)
%.o:%.s
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
%.o:%.S
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
%.o:%.c
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
/// 定義清楚方法
clean:
rm -rf *.o ledc.bin ledc.elf ledc.dis
編譯
make clean && make
編譯完成之后燒寫到SD卡,選擇SD卡啟動(dòng)觀察LED燈閃爍
-
cpu
+關(guān)注
關(guān)注
68文章
11080瀏覽量
217099 -
計(jì)算機(jī)
+關(guān)注
關(guān)注
19文章
7663瀏覽量
90809 -
操作系統(tǒng)
+關(guān)注
關(guān)注
37文章
7152瀏覽量
125592
發(fā)布評(píng)論請(qǐng)先 登錄
C語言:標(biāo)準(zhǔn)和實(shí)現(xiàn)
CRC算法原理及C語言實(shí)現(xiàn)
C語言教程之不使用strcpy()函數(shù)實(shí)現(xiàn)
C語言標(biāo)準(zhǔn)與實(shí)現(xiàn)
使用單片機(jī)實(shí)現(xiàn)1602字符液晶工作于8位模式直接驅(qū)動(dòng)顯示的C語言程序
使用單片機(jī)實(shí)現(xiàn)ULN2803驅(qū)動(dòng)點(diǎn)陣屏仿電梯數(shù)字滾動(dòng)顯示的C語言實(shí)例
EE-188:在ADSP-219x DSP上用C語言實(shí)現(xiàn)中斷驅(qū)動(dòng)系統(tǒng)

怎么用C語言實(shí)現(xiàn)多態(tài)
用C語言實(shí)現(xiàn)簡單工廠模式

EE-188:使用C語言在ADSP-219x DSP上實(shí)現(xiàn)中斷驅(qū)動(dòng)系統(tǒng)

評(píng)論