ARM Coretex-A的不同模式
為了盡可能的保護計算機資源(CPU、內存、IO等),不同的CPU架構實現了不同的權限等級,等級越高可訪問的系統資源越多(包括執行一些特權指令),這是因為普通用戶級別的程序代碼質量不能得到完全的保障,為了更好的保護計算機資源會讓用戶級別的代碼工作在盡可能少的訪問系統資源的模式下,而像操作系統這樣經過千錘百煉的程序質量有保障,CPU可以放心的把計算機資源交出來讓操作系統可以隨意訪問。
在當前的實驗中,由于我們是工作在祼機狀態下的程序,可以簡單的認為我們的代碼與操作系統代碼是一個級別的,就算代碼有問題那從CPU的角度來講我們的祼機代碼也是高質量的,也就是說可以工作在高等級權限的模式下。
ARM Coretex-A
系列處理器有以下幾種工作模式:其中,SVC
是超級管理員模式,可以訪問所有的計算機資源。
設置CPU工作模式為SVC
Coretex-A
提供了一個專門的寄存器CPSR
程序狀態寄存器來控制當前CPU的工作模式, CPSR
的每一位的邏輯如下:
其中的低5位M[4:0]用于指定當前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)模式 |
通過表格可以看出,如果要設置成SVC
模式,則需要將CPSR
寄存器的低5位M[4:0]設置成10011
讀寫CRSR
寄存的操作指令與讀取通用寄存器使用的ldr
與str
不要樣,需要使用mrs
讀取CPSR
的數據,msr
向CPSR
寫入數據。
/// 將cpsr寄存器中的數據讀取到r0
/// 這是因為cpsr是不能使用運算符指令對其進行直接的操作的,需要使用通用寄存器
mrs r0, cpsr
/// 通過使用bic指令將,r0的低5位都清空,這里使用了0x1f=11111. bic指令后面的操作數掩碼位的值是1表示將此位清空,否則保持不變
bic r0, r0, #0x1f
/// 通過orr(或)指令將r0寄存器中的低5位設置成10011
orr r0, r0, #0x13
/// 將r0的數據寫入cprs寄存器,完成svc模式切換
msr cprs, r0
設置C語言運行環境
C語言要工作,需要指定一個棧空間,通過指定sp
指針就可以給C語言開辟一塊棧空間。
Coretex-A
的棧是向下生長的,也就是從高地址向低地址生成(即棧頂在高地址)。I.MX6ULL
的DDR
的起始地址是0x80000000,這里設置一個2MB的空間大小,實際上也可以設置成1MB或者512KB也是完全夠用的。所以需要設置sp
指針的初始位置是0x802000000.
/// 設置sp指針地址
ldr sp, =0x80200000
/// 跳轉到c語言的main函數開始執行
b main
編寫C語言LED驅動程序
- 1.使能CCM_CCGR1
#define CCM_CCGR1 *((volatile unsigned int *)0x020C406C)
CCM_CCGR1 = 0xFFFFFFFF;
- 2.復用
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.設置GPIO1_GDIR的信號輸出方向
#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
/// 定義目標文件變量
objs := start.o main.o
/// 生成ledc.bin,依賴objs
ledc.bin:${objs}
arm-linux-gnueabihf-ld -Ttext 0x87800000 -o ledc.elf $^ /// 將目標文件鏈接生成ledc.elf $^表示所有依賴文件的集合,使用空格分開,去重
arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@ /// 將ledc.elf生成ledc.bin, $@指目標集合,這里的目標就是上面定義的ledc.bin
arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis /// 將ledc.elf反匯編成ledc.dis,主是要方便查看連接后的代碼段指令是否符合預期
/// 當目標文件沒有時會使用如下的模式規則去生成對應的目標文件
/// $@指要生成的.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卡啟動觀察LED燈閃爍
-
cpu
+關注
關注
68文章
10826瀏覽量
211160 -
計算機
+關注
關注
19文章
7425瀏覽量
87719 -
操作系統
+關注
關注
37文章
6742瀏覽量
123192
發布評論請先 登錄
相關推薦
評論