目录
[1.1 IMX6ULL-Mini 开发板介绍](#1.1 IMX6ULL-Mini 开发板介绍)
[1.2.1 编译工具:gcc-linaro 交叉编译器](#1.2.1 编译工具:gcc-linaro 交叉编译器)
[1.2.2 代码编辑:Visual Studio Code](#1.2.2 代码编辑:Visual Studio Code)
[1.2.3 辅助工具](#1.2.3 辅助工具)
[二、LED 点亮的底层逻辑](#二、LED 点亮的底层逻辑)
[2.1 引脚配置三步骤](#2.1 引脚配置三步骤)
[2.1.1 复用功能配置(IOMUXC)](#2.1.1 复用功能配置(IOMUXC))
[2.1.2 电气特性配置(IOMUXC)](#2.1.2 电气特性配置(IOMUXC))
[2.1.3 引脚方向配置(GPIO)](#2.1.3 引脚方向配置(GPIO))
[2.2 LED 开关逻辑](#2.2 LED 开关逻辑)
[2.3 LDR 与 STR 详解](#2.3 LDR 与 STR 详解)
[三、汇编代码实现 LED 闪烁](#三、汇编代码实现 LED 闪烁)
[4.1 手动编译步骤](#4.1 手动编译步骤)
[4.2 Makefile 简化编译](#4.2 Makefile 简化编译)
[4.3 程序烧写与测试](#4.3 程序烧写与测试)
[4.3.1 SD 卡烧写](#4.3.1 SD 卡烧写)
[4.3.2 开发板测试](#4.3.2 开发板测试)
一、开发环境与硬件基础
1.1 IMX6ULL-Mini 开发板介绍
IMX6ULL-Mini 开发板是由正点原子提供的, 搭载NXP生产i.MX6ULL的SOC, 主打高性能、低功耗与紧凑体积。整个开发板由核心板与底板组成,核心板通过双列直插方式与底板连接。
IMX6ULL-Mini 开发板
- 核心板:六层板
- **CPU:**NXP i.MX 6ULL Cortex-A7 单核处理器,主频 528MHz(工业级) 或 800MHz(商业级)467, BGA 封装
- **内存:**512MB DDR3L RAM,支持高速数据存取。
- **存储:**8GB eMMC,支持多种启动模式(SD卡、NAND、eMMC)
- **屏幕:**4.3寸屏 800*480分辨率
- 底板
- 红色 led 灯提供用户可控的的 led 灯
- 蓝色 led 灯是电源指示灯
- 510 欧姆限流电阻作用防止电流过大保护灯珠。
1.2.1 编译工具:gcc-linaro 交叉编译器
- 拷贝 gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz 到 /usr/local/arm
- 解压 sudo tar -xvf gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz
- 删除 sudo rm gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz
- 配置回家目录, 修改环境变量配置文件 vi .bashrc
- export PATH=$PATH:/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/
- 重启虚拟机:reboot
- 检查编译器版本:arm-linux-gnueabihf-gcc -v
1.2.2 代码编辑:Visual Studio Code
- 安装Visual Studio Code
- 汇编高亮插件:Arm Assembly
- 创建工程文件夹 \IMX6ULL\led_asm
- 创建启动代码 start.S(注意大写S后缀,会进行预处理,后期用到一些宏)
1.2.3 辅助工具
- 烧写工具:imxdownload(IMX6ULL 专用 SD 卡烧写工具)
- 串口工具(可选):用于调试输出,本次实验暂不涉及
二、LED 点亮的底层逻辑
IMX6ULL 的 LED 控制本质是GPIO 外设寄存器操作,需完成 3 步初始化 + 1 步运行时控制,核心依赖汇编的 LDR(读取寄存器)和 STR(写入寄存器)指令。
2.1 引脚配置三步骤

参考 IMX6ULL 参考手册和底板原理图,本次控制GPIO1_IO03 引脚(对应红色 LED):
2.1.1 复用功能配置(IOMUXC)
GPIO 引脚默认可能不是 GPIO 功能,需通过复用寄存器配置为 GPIO 模式:
- 寄存器地址:IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 = 0x020C4068
- 配置值:低 4 位设为 0101(对应 GPIO 功能)
2.1.2 电气特性配置(IOMUXC)
设置引脚的驱动能力、上下拉等电气参数,避免信号不稳定:
- 寄存器地址:IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03(需查阅手册确认具体地址)
- 核心配置:根据 LED 驱动需求设置(如默认配置可满足基础点灯)
2.1.3 引脚方向配置(GPIO)
设置 GPIO 为输出模式(LED 需要主动输出高低电平):
- 寄存器地址:GPIO1_GDIR(GPIO1 端口方向寄存器)
- 配置逻辑:对应位设为 1(输出),0 为输入;GPIO1_IO03 对应第 3 位,故设置GPIO1_GDIR |= (1<<3)
2.2 LED 开关逻辑
LED 灯珠采用低电平点亮(原理图设计),通过 GPIO 数据寄存器控制:
- 寄存器地址:GPIO1_DR(GPIO1 端口数据寄存器)
- 点亮:对应位设为 0(GPIO1_DR &= ~(1<<3))
- 熄灭:对应位设为 1(GPIO1_DR |= (1<<3))
2.3 LDR 与 STR 详解
| 指令 | 功能 | 示例 |
|---|---|---|
| LDR <Rt>, =<addr> | 将寄存器地址加载到目标寄存器 Rt | ldr r0, =0x020C4068(r0 = 复用寄存器地址) |
| STR <Rt>, [<Rn>] | 将 Rt 的值写入 Rn 指向的内存地址(寄存器) | str r1, [r0](将 r1 的值写入 r0 指向的复用寄存器) |
三、汇编代码实现 LED 闪烁
要实现闪烁,需在 "点亮 - 延时 - 熄灭 - 延时" 之间循环,延时通过汇编空指令实现(利用 CPU 执行指令的时间差):
.global _start
; ==============================================
; ARM异常向量表 (Exception Vector Table)
; ARM架构规定从0x00000000开始的32字节为异常向量表
; 每个异常占4字节,依次对应8种异常类型
; ==============================================
_start:
ldr pc, =_reset_handler
ldr pc, =_undef_handler
ldr pc, =_software_handler
ldr pc, =_prefect_handler
ldr pc, =_data_abort_handler
nop
ldr pc, =_irq_handler
ldr pc, =_fiq_handler
; ==============================================
; 异常处理函数(默认原地死循环,防止异常逃逸)
; 新手阶段暂不处理具体异常,仅做兜底
; ==============================================
_undef_handler:
b _undef_handler
_software_handler:
b _software_handler
_prefect_handler:
b _prefect_handler
_data_abort_handler:
b _data_abort_handler
_irq_handler:
b _irq_handler
_fiq_handler:
b _fiq_handler
; ==============================================
; 复位处理函数(系统上电/复位后第一个执行的核心函数)
; ==============================================
_reset_handler:
cpsid i ; 失能irq
cps #0x12
ldr sp, =0x82000000
cps #0x1F
ldr sp, =0x84000000
cpsie i ; 使能irq
bl led_init
; ==============================================
; 主循环:LED闪烁逻辑
; ==============================================
finish:
bl led_on
bl led_delay
bl led_off
bl led_delay
b finish
; ==============================================
; LED初始化函数:配置GPIO引脚(以IMX6ULL为例)
; 步骤:1.复用功能 2.配置电气特性 3.设置引脚为输出
; ==============================================
led_init:
; 复用功能
ldr r0, =0x020E0068
ldr r1, [r0]
bic r1, r1, #0x1F
orr r1, r1, #0x05
str r1, [r0]
; 电气特性
ldr r0, =0x020E02F4
ldr r2, =0x10B0
str r2, [r0]
; 引脚方向
ldr r0, =0x0209C004
ldr r1, [r0]
orr r1, r1, #(1 << 3)
str r1, [r0]
bx lr
; ==============================================
; LED点亮函数:拉低GPIO1_IO03引脚(低电平点亮)
; ==============================================
led_on:
ldr r0, =0x0209C000
ldr r1, [r0]
bic r1, r1, #(1 << 3)
str r1, [r0]
bx lr
; ==============================================
; LED熄灭函数:拉高GPIO1_IO03引脚(高电平熄灭)
; ==============================================
led_off:
ldr r0, =0x0209C000
ldr r1, [r0]
orr r1, r1, #(1 << 3)
str r1, [r0]
bx lr
; ==============================================
; 简单延时函数:通过循环递减实现延时
; ==============================================
led_delay:
ldr r0, =0x7FFFF
loop:
cmp r0, #0
ble fin
sub r0, r0, #1
b loop
fin:
bx lr
四、编译与烧写
4.1 手动编译步骤
执行以下命令:
(1)汇编:将.S 文件转为目标文件(.o)
bash
arm-linux-gnueabihf-gcc -c start.S -o start.o -g
- -c:只汇编不链接
- -o:指定输出文件
- -g:保留调试信息
**(2)链接:**将目标文件链接到指定地址(IMX6ULL 的 SD 卡启动地址为 0x87800000)
bash
arm-linux-gnueabihf-ld -Ttext 0x87800000 start.o -o start.elf
- -Ttext:指定代码段起始地址
(3)格式转换:将 ELF 文件转为开发板可执行的二进制文件(.bin)
bash
arm-linux-gnueabihf-objcopy -O binary -S -g start.elf start.bin
- -O binary:输出二进制格式
- -S:去除符号信息
- -g:去除调试信息
(4)反汇编(可选):将 ELF 文件转为汇编代码(用于调试)
bash
arm-linux-gnueabihf-objdump -D start.elf > start.dis
4.2 Makefile 简化编译
bash
# 定义工具链变量,简化后续命令
COMPILER = arm-linux-gnueabihf-
CC = $(COMPILER)gcc
LD = $(COMPILER)ld
OBJCOPY = $(COMPILER)objcopy
OBJDUMP = $(COMPILER)objdump
# 目标:最终生成的二进制文件
start.bin : start.S
$(CC) -c start.S -o start.o -g # 汇编
$(LD) -Ttext 0x87800000 start.o -o start.elf # 链接
$(OBJCOPY) -O binary -S -g start.elf start.bin # 格式转换
$(OBJDUMP) -D start.elf > start.dis # 反汇编(可选)
# 伪目标:清理编译产物
clean:
rm -f start.o start.elf start.bin start.dis
# 伪目标:烧写程序到SD卡
load:
./imxdownload start.bin /dev/sdb
使用方法:
- 编译:make(一键生成 start.bin)
- 清理:make clean(删除所有编译产物)
- 烧写:make load(需提前将 imxdownload 工具拷贝到工程目录并添加执行权限:chmod +777 imxdownload)
4.3 程序烧写与测试
4.3.1 SD 卡烧写
- 将 SD 卡插入 Ubuntu 虚拟机(通过 USB 读卡器)
- 查看 SD 卡设备名:ls /dev/sdb(通常为 sdb,需确认无其他存储设备冲突)
- 执行烧写命令:./imxdownload start.bin /dev/sdb
**注意:**烧写速率需为 KB 级,若显示 MB 级速率则失败,需拔掉读卡器重启 Ubuntu 后重试
4.3.2 开发板测试
- 选择启动模式:通过开发板上的拨码开关选择 SD 卡启动(参考开发板原理图)
- 插入烧写好的 SD 卡到开发板 TF 卡槽
- 上电测试:
- 确保开发板电源开关弹起,插入电源适配器
- 按下蓝色电源开关,观察蓝色电源灯亮起
- 红色 LED 周期性闪烁
熄灭状态
点亮状态
五、核心概念解答
1. 在 LED 实验中,在对 SOC 引脚配置时都做了哪些工作?
- 复用功能配置:将引脚从默认功能切换为 GPIO 功能;
- 电气特性配置:设置引脚驱动能力、上下拉等,保证信号稳定;
- GPIO 方向配置:设置为输出模式,使引脚能主动输出高低电平。
2. 什么是编译器、连接器、格式转换器和反汇编器?
- 编译器(gcc):将汇编源文件(.S)转为目标文件(.o),进行语法检查和指令翻译;
- 链接器(ld):将目标文件链接到指定内存地址,解决符号引用(如程序入口 _start);
- 格式转换器(objcopy):将 ELF 文件(包含调试 / 符号信息)转为开发板可直接执行的二进制文件(.bin);
- 反汇编器(objdump):将 ELF 文件转回汇编代码,用于调试(验证指令是否正确翻译)。