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代码。

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

相关推荐
La Pulga8 小时前
【FreeRTOS源码学习笔记】任务切换
单片机·mcu·学习·嵌入式·freertos·实时操作系统
女神下凡12 小时前
芯参谋(85):Linux_PPI_NAND_驱动开发指南
linux·运维·arm开发·驱动开发·单片机·嵌入式硬件·设计规范
Zw-awa13 小时前
从 CH340 到 HC-05 和 HC-06:让小车脱离电脑
stm32
硅基手札14 小时前
【Linux 内核专栏 19】20 · 嵌入式子系统 — GPIO·pinctrl·clock·regulator
linux·运维·单片机·linux内核·嵌入式开发·调试定位
何粥学16 小时前
Vivado 2024.2 开发记录(AC820 Zynq-7020)——软件使用,点亮led灯
单片机·嵌入式硬件·zynq
Sakura_j_h_16 小时前
51 单片机驱动四位数码管:动态扫描、限流电阻与消影的取舍
单片机·嵌入式硬件·51单片机·嵌入式·数码管·动态扫描·限流电阻
HANDY0920018 小时前
从“不照人”到“剂量达标”:扇叶遮挡式UV-C空气消毒的工程边界与可验证评估框架
开发语言·人工智能·嵌入式硬件·智能家居
飞凌嵌入式20 小时前
千次静电放电试炼,守住飞凌嵌入式硬件可靠底线
嵌入式硬件
蹊黎1 天前
Linux 下用 C 语言实现进度条
linux·c语言·单片机
Zw-awa1 天前
从 CPU 搬运到自动搬运:DMA、空闲中断和两块缓冲
stm32