裸機實現LED閃爍
一、啟動代碼
1. 異常向量表配置
1. .global
? ? ? ? 匯編器指令,全局定義標簽_start,作為匯編程序的默認起點
2. 配置標簽
? ? ? ? 配置標簽時可以前置加_ ,以便和普通標簽或系統標簽做區分
3. 異常向量表
? ? ? ? ARM架構規定異常向量表位置固定,配置對應位置的異常向量
2. start函數
1. 操作CPSR寄存器 搭建運行環境
1. 配置irq模式
????????用于處理中斷,確保各個部分的獨立性
????????1. mrs 指令使cpsr寄存器 備份到r0中
????????2. 修改模式為irq模式
先通過bic指令對后五位清零,便于后續修改模式
手冊Label - ARM processor 查詢模式代碼,通過orr指令進行修改配置????????3. 打開終端I位
通過bic指令對第 I 位置1,打開中斷,確保程序能響應中斷
注:整個程序中斷只用配置一次,后續修改 sys 模式時不用再次配置?? ? ? ? 4.?msr指令將 r0 值 返回置 cpsr ,確保模式轉換
2. 配置sys模式
????????可以使C語言執行,空間大
????????1. mrs 指令使cpsr寄存器 備份到r0中
????????2. 修改模式為sys模式
sys模式代碼為11111,可以省略清零準備步驟? ? ? ? 3. 不用再次配置中斷響應
? ? ? ? 4.?msr指令將 r0 值 返回置 cpsr ,確保模式轉換
2. CPS指令 搭建運行環境
1. 關閉中斷
????????防止初始化過程被中斷打斷,確保原子操作
2. cps
手冊376 CPS指令專用操作cpsr寄存器
配置中斷:????????CPS<effect> <iflags>{, #<mode>}
配置模式:? ? ? ? CPS #<mode>
????????CPS用于ARMv6v7架構,keil默認目標為ARMv5架構無法編譯通過,可以使用操作CPSR寄存器的方式
3.分配空間?
? ? ? ? 硬件ROM(加載域)的起始物理地址為0x8000 0000
為 irq 模式0x12分配 32M = 32 * 1024 * 1024 = 0200 0000 大小的空間,即0x8200 0000
為 sys?模式0x1F再分配 32M大小的空間,即 0x8400 0000
3. 開啟實現目的程序
二、LED燈配置
1. led_init
1.?? 功能復用配置
GPIO引腳初始化
????????手冊C32 - IOMUXV Memory Map... - IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 p1571
引腳的功能復用(MUX)
// IO復用功能配置// 手冊C32 - IOMUXV Memory Map... // - IOMUXV Memory Map... - IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 p1571ldr r0, =0x020E0068ldr r1, =0x05 // 0101 ALT5-GPIO1_IO03str r1, [r0]
1. 加載IOMUX控制寄存器地址
Address:20E_0000h base + 68h offset = 0x20E 0068
2. 將引腳功能從默認模式切換為GPIO
模式GPIO_IO03 gpio1模式代碼為 0101 = 0x05
3. str指令將配置寫回寄存器
將 r1 存放的內容存放在 r0 存放的地址內
即將0x05 模式存放在控制寄存器的地址,實現引腳初始化
2.? ?電氣特性配置
設置引腳的驅動能力、上下拉等電氣參數
GPIO引腳初始化
????????手冊C32 - IOMUXV Memory Map... - IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 p1793
引腳的??電氣特性??(PAD),滯回器、上拉/下拉電阻、開漏/推挽輸出
??
// 引腳電氣特性配置// 手冊C32 - IOMUXV Memory Map... // - IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 p1793ldr r0, =0x020E02F4ldr r1, =0x10B0 str r1, [r0]
1. 加載PAD控制寄存器地址
Address:20E_0000h base + 2F4h offset = 0x20E 02F4
2. 配置電氣參數(驅動強度、壓擺率、上下拉、開漏/推挽)
配置為0x10B0 = 0001 0000 1011 0000
對應部分參數為:12位? :? ? 1:使能上拉
7-6位:??10:中速100MHZ
5-3位:110:中等驅動強度? ? ? ? ......
3. str指令將配置寫回寄存器
將 r1 存放的內容存放在 r0 存放的地址內
即將0x10B0?模式存放在PAD寄存器的地址,實現電氣配置
3. ??方向配置??
????????將引腳設置為輸出模式
手冊C28(外設) - GPIOx - GDIR
// 引腳方向// 手冊C28(外設) - GPIOx - GDIRldr r0, =0x0209C004 ldr r1, [r0] orr r1, r1, #(1 << 3)str r1, [r0]
1. 加載GPIO1的GDIR(方向控制寄存器)地址
Address:Base address + 4h offset?
2. 設置輸出模式
將GPIO_IO03設為輸出,即通過orr指令將第三位置1
3. str指令將配置寫回寄存器
將 r1 存放的內容存放在 r0 存放的地址內
即將結果返回寄存器地址,實現配置輸出模式
2. led_on
? ? ? ? 手冊C28(外設) - GPIOx - DR
通過bic指令將GPIO_IO03位清零,通過硬件電氣特征,此時LED點亮
3. led_off
通過orr指令將GPIO_IO03位置1,通過硬件電氣特征,此時LED熄滅
4. led_delay
????????通過執行一個??空循環??消耗CPU時間,實現??軟件延時??
三、編譯與測試
1. 編譯步驟
1. arm-linux-gnueabihf-gcc 只匯編不鏈接
????????arm-linux-gnueabihf-gcc?-c?start.S?-o?start.o?-g
? ? ? ? -o ????????只編譯不鏈接
-g ????????保留編譯信息
2. arm-linux-gnueabihf-ld 鏈接代碼到特定地址
????????(得到可執行,可連接程序 linux?executable?linkable?file)
????????arm-linux-gnueabihf-ld?-Ttext?0x87800000?start.o?-o?start.elf
? ? ? ? Ttext ????????指定代碼段加載地址
-o? ? ? ????????輸出ELF格式可執行文件
3. arm-linux-gnueabihf-objcopy?格式轉換?
????????arm-linux-gnueabihf-objcopy?-O?binary?-S -g start.elf?start.bin
? ? ? ? -O binary? ? ? ? ? ? ? ? 輸出二進制格式
-S? ? ? ? ? ? ? ? ? ? ? ? ? ?去除符號表
-g? ? ? ? ? ? ? ? ? ? ? ? ? ? 去除調試信息
4. arm-linux-gnueabihf-objdump?反匯編(可省略)
????????arm-linux-gnueabihf-objdump?-D?start.elf??>?start.dis
????????-D? ? ? ? ? ? ? ? ?反匯編所有段
5. imxdownload 燒寫程序到SD卡
./imxdownload?start.bin?/dev/sdb
????????插入SD卡后選擇連接到虛擬機Ubuntu? ? ? ?
使用 chmod?+777?imxdownload 命令賦予 imxdownload 權限
通過 ls/imxdownload /dev/sdb 命令查看dev
剛插入SD卡就執行命令可能會出錯,現象為少燒寫速率以M為單位,此時需要重啟虛擬機
6. 將SD卡插入板子觀察現象
? ? ? ? 注:
修改板子工作模式為SD模式
插入SD卡時不要上電
BOOT工作模式: