IMX6ULL裸机开发从零开始:VS Code搭建环境+汇编点灯实战

一、开发环境准备

1. 宿主机与工具链

  • Windows端:安装VS Code,装这几个必备扩展:

    • Chinese (Simplified):汉化包,看着舒服

    • C/C++ Extension Pack:C/C++语法支持

    • Arm Assembly:ARM汇编语法高亮、补全

    • Makefile Tools:Makefile工程管理

  • 编译环境:Ubuntu系统(可以是WSL2或者虚拟机),用来交叉编译代码,毕竟最终跑在ARM架构的IMX6ULL上。

2. 核心硬件资源先搞懂

IMX6ULL的外设操作主要和三个模块打交道,先把这几个基础概念记牢:

模块 核心寄存器 作用
IOMUXC(引脚复用) IOMUXC_SW_MUX_CTL_PAD_xxx 配置引脚复用功能,比如把某个IO设为GPIO模式
IOMUXC_SW_PAD_CTL_PAD_xxx 配置引脚电气属性:上下拉、驱动能力、速度等
GPIO GPIOx_DR GPIO数据寄存器,控制引脚输出高低电平
GPIOx_GDIR GPIO方向寄存器,配置引脚是输入还是输出
CCM(时钟控制) CCM_CCGR0 ~ CCM_CCGR6 外设时钟门控,给对应位写0xFFFFFFFF就能打开所有外设时钟

另外要记住一个关键地址:IMX6ULL的DDR起始地址是0x80000000,后面链接脚本会用到。


二、汇编点灯实战(以GPIO1_IO03为例)

点灯是所有嵌入式开发的"Hello World",咱们先从最底层的汇编实现,搞清楚每一步硬件操作的原理。

1. 整体流程

汇编点灯一共4步:

  1. 开启GPIO外设时钟

  2. 配置引脚复用为GPIO功能

  3. 配置引脚电气属性

  4. 设置GPIO为输出模式,并输出低电平点亮LED

2. 完整汇编代码(start.S)

复制代码
.global _start

_start:
    /* 1. 开启GPIO1时钟(CCM_CCGR1控制GPIO1时钟,bit27:26置11即可) */
    ldr r0, =0x20C406C   /* CCM_CCGR1寄存器地址 */
    ldr r1, =0xFFFFFFFF  /* 打开所有外设时钟,偷懒直接全开 */
    str r1, [r0]

    /* 2. 配置引脚复用:将GPIO1_IO03复用为GPIO功能 */
    ldr r0, =0x20E0068   /* IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03寄存器地址 */
    ldr r1, =0x5         /* ALT5模式就是GPIO */
    str r1, [r0]

    /* 3. 配置引脚电气属性 */
    ldr r0, =0x20E02F4   /* IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03寄存器地址 */
    ldr r1, =0x10B0      /* 配置:下拉、100MHz速度、驱动能力R0/6等 */
    str r1, [r0]

    /* 4. 配置GPIO1_IO03为输出模式 */
    ldr r0, =0x209C004   /* GPIO1_GDIR寄存器地址 */
    ldr r1, =0x8         /* bit3置1,对应GPIO1_IO03为输出 */
    str r1, [r0]

    /* 5. 输出低电平,点亮LED(假设LED共阳极接法) */
    ldr r0, =0x209C000   /* GPIO1_DR寄存器地址 */
    ldr r1, =0x0         /* bit3清零,输出低电平 */
    str r1, [r0]

loop:
    b loop               /* 死循环,防止程序跑飞 */

3. 配套Makefile

复制代码
CROSS_COMPILE ?= arm-linux-gnueabihf-
TARGET = led_asm

$(TARGET).bin: $(TARGET).elf
	$(CROSS_COMPILE)objcopy -O binary -S $^ $@

$(TARGET).elf: start.o
	$(CROSS_COMPILE)ld -Ttext 0x80000000 -o $@ $^

start.o: start.S
	$(CROSS_COMPILE)gcc -Wall -nostdlib -c $^ -o $@

clean:
	rm -rf *.o *.elf *.bin

注意链接地址-Ttext 0x80000000,就是我们前面说的DDR起始地址,代码会被加载到这里运行。

4. 编译烧录

  1. 把代码放到Ubuntu里,执行make生成led_asm.bin

  2. 通过imxdownload工具把bin文件烧写到SD卡:

    复制代码
    ./imxdownload led_asm.bin /dev/sdb  # 注意sdb是你的SD卡设备名,别写错!
  3. 把SD卡插到开发板,拨码开关设为SD卡启动,上电就能看到LED亮起来~


三、后续进阶方向

这次只是最基础的汇编点灯,后面还会更新:

  • C语言点灯:用C封装寄存器操作,更符合工程习惯

  • NXP官方固件库点灯:学习工业级代码的写法

  • 中断、定时器、串口等外设的裸机驱动


常见问题Q&A

  1. LED不亮怎么办?

    先检查LED的硬件接法(共阳/共阴),再核对寄存器地址是否正确,最后看SD卡烧录有没有报错。

  2. 为什么要用汇编开头?

    裸机程序没有引导程序帮我们做初始化,汇编负责最底层的CPU初始化、栈设置等,后面C语言运行环境准备好了就可以跳转到C代码。

如果这篇博客对你有帮助,别忘了点赞收藏~ 有问题欢迎在评论区交流!

相关推荐
jianqiang.xue11 分钟前
ESP-IDF保姆级入门02|Ubuntu24.04搭建EIM-GUI开发环境,打通Windows_Linux双平台统一开发
stm32·单片机·物联网
无垠的广袤30 分钟前
【工业树莓派 CM0 Dev Board】扩展板设计
linux·python·嵌入式硬件·pcb设计·模块化·传感器
嵌入式-老费1 小时前
esp32开发与应用(添加数据分区)
单片机·嵌入式硬件
嵌入式-老费2 小时前
esp32开发与应用(OTA升级)
嵌入式硬件
CYLAM20255 小时前
STC32G 单片机0.96“OLED 西历农历可调万年历 (1901-2100)
单片机·嵌入式硬件·stc32g·万年历·西历农历·0.96”oled 12864·4x4 矩阵键盘
Discipline~Hai5 小时前
ARM03-蜂鸣器和中断
c语言·arm开发·单片机·嵌入式硬件·嵌入式
KaifuZeng6 小时前
电源面试问题汇总一
单片机·嵌入式硬件·面试·电路
驱动探索者8 小时前
RISC-V PLIC 深度解析:从 Spec 到 Zephyr 驱动实现
单片机·嵌入式硬件·中断控制器
LCG元8 小时前
STM32 FreeRTOS 实战:任务调度 + 互斥锁 + 消息队列 + 串口命令解析器
stm32·单片机·嵌入式硬件
Hello_Damon_Nikola8 小时前
姿态式饮水量估算从原理到实战
嵌入式硬件