裸机实现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工作模式: