韦东山IMX6ULL快速入门路线

韦东山《ARM 架构与编程 · 基于 IMX6ULL》快速入门路线

面向对象:已具备 51 单片机(STC89C52)与 STM32(Cortex-M3,江协科技教程)基础的学习者

核心思路:以旧带新、以寄存器窥全机 ------ 用你已经会的"配寄存器点灯"当船,渡到 ARMv7-A 裸机开发的岸

关键提醒:这门课不是"再学一遍单片机",而是把 STM32 的经验往下拆一层,看清 CPU、总线、地址空间、程序加载的真实面目


目录

  • [0. 这份路线图怎么用](#0. 这份路线图怎么用)
  • [1. 课程全貌:十章知识地图](#1. 课程全貌:十章知识地图)
  • [2. 前置能力盘点:你有的 vs 你缺的](#2. 前置能力盘点:你有的 vs 你缺的)
    • [2.1 迁移对照表(51/STM32 → IMX6ULL)](#2.1 迁移对照表(51/STM32 → IMX6ULL))
    • [2.2 必须补的三个知识缺口](#2.2 必须补的三个知识缺口)
  • [3. 环境准备(半天内搞定)](#3. 环境准备(半天内搞定))
    • [3.1 硬件清单](#3.1 硬件清单)
    • [3.2 软件与工具链](#3.2 软件与工具链)
    • [3.3 与 Keil 时代的思维切换](#3.3 与 Keil 时代的思维切换)
  • [4. 三阶段速通路线(总计 4--6 周)](#4. 三阶段速通路线(总计 4–6 周))
  • [5. 逐章精讲与"快进/必看"标注](#5. 逐章精讲与"快进/必看"标注)
    • [第 2 章 嵌入式概念及硬件组成](#第 2 章 嵌入式概念及硬件组成)
    • [第 3 章 第一个程序(IMX6ULL 点灯)](#第 3 章 第一个程序(IMX6ULL 点灯))
    • [第 4 章 ARM 架构](#第 4 章 ARM 架构)
    • [第 5 章 第 1 个程序深度解析](#第 5 章 第 1 个程序深度解析)
    • [第 6 章 使用按键控制 LED](#第 6 章 使用按键控制 LED)
    • [第 7 章 串口 UART 编程](#第 7 章 串口 UART 编程)
    • [第 8 章 keil_gcc_Makefile](#第 8 章 keil_gcc_Makefile)
    • [第 9 章 代码重定位](#第 9 章 代码重定位)
    • [第 10 章 异常与中断](#第 10 章 异常与中断)
  • [6. 核心难点攻坚](#6. 核心难点攻坚)
    • [6.1 用寄存器点灯"看见"计算机如何工作(本书精华)](#6.1 用寄存器点灯"看见"计算机如何工作(本书精华))
    • [6.2 Cortex-M3 与 ARMv7-A 的本质差异](#6.2 Cortex-M3 与 ARMv7-A 的本质差异)
    • [6.3 汇编与 C 的边界:启动代码](#6.3 汇编与 C 的边界:启动代码)
    • [6.4 代码重定位与链接脚本(全课最难)](#6.4 代码重定位与链接脚本(全课最难))
    • [6.5 异常向量表与 GIC 中断](#6.5 异常向量表与 GIC 中断)
  • [7. 建议时间表(4 周冲刺版 / 6 周稳健版)](#7. 建议时间表(4 周冲刺版 / 6 周稳健版))
  • [8. 调试与验证手段](#8. 调试与验证手段)
  • [9. 与后续课程的衔接](#9. 与后续课程的衔接)
  • [10. 常见问题 FAQ](#10. 常见问题 FAQ)
  • [11. 一页速查:寄存器点灯最小代码](#11. 一页速查:寄存器点灯最小代码)

0. 这份路线图怎么用

三条原则:

原则 含义 具体做法
旧知识加速 讲 GPIO、UART、中断"是什么"的部分直接快进 只精听"IMX6ULL 上怎么做"的差异部分
新概念慢炖 地址空间、重定位、异常向量、GIC 必须逐帧看 每节课后自己复现一遍,不看讲稿敲代码
动手 > 看懂 裸机开发最大的坑都在"想当然" 每个实验必须落地到开发板上出效果

推荐节奏:先用半天通读本文档 → 按 [第 4 节](#先用半天通读本文档 → 按 第 4 节 三阶段推进 → 卡壳时回查 第 6 节) 三阶段推进 → 卡壳时回查 [第 6 节](#先用半天通读本文档 → 按 第 4 节 三阶段推进 → 卡壳时回查 第 6 节)


1. 课程全貌:十章知识地图

课程本质是一条**"从会用到懂原理"**的递进链:

复制代码
外设层(会点灯)
   第2章 概念/硬件组成   →  第3章 寄存器点灯   →  第6章 按键
                                                    ↓
架构层(懂指令)                                    第7章 UART
   第4章 ARM架构与汇编  →  第5章 反汇编/存储布局   ↓
                                                    ↓
工程层(懂编译链接)                                 ↓
   第8章 gcc/Makefile   →  第9章 代码重定位  →  第10章 异常与中断
章节 标题 视频数 难度 定位
1 资料说明与下载 --- 环境搭建
2 嵌入式概念及硬件组成 2 概念铺垫(MCU/MPU/AP 的区别)
3 第一个程序(IMX6ULL 点灯) 5 ★★ 全课基石:GPIO 寄存器操作
4 ARM 架构 7 ★★★★ 分水岭:寄存器组 + 汇编指令集
5 第 1 个程序深度解析 5 ★★★★ 反汇编、字节序、C 与汇编的对应
6 使用按键控制 LED 1 ★★ 输入方向配置(快进)
7 串口 UART 编程 3 ★★★ 第一个"有反馈"的调试通道
8 keil_gcc_Makefile 8 ★★★★ 脱离 IDE,理解编译链接全过程
9 代码重定位 7 ★★★★★ 全课最硬:链接脚本、段、BSS
10 异常与中断 10 ★★★★★ 异常向量表、CPU 模式、GIC

总计约 48 个视频,按 30--40 分钟/集估算,视频净时长 25--30 小时;配合动手实操,总投入约 60--80 小时。


2. 前置能力盘点:你有的 vs 你缺的

2.1 迁移对照表(51/STM32 → IMX6ULL)

能力项 你在 51/STM32 上已掌握 IMX6ULL 上的变化 迁移难度
GPIO 点灯 配 P1 口 / GPIO_InitStruct 多了一步"引脚复用(IOMUX)+ 时钟使能(CCM)" ★★ 需注意
时钟系统 51 无;STM32 RCC 使能 七个 PLL,要查 CCM 寄存器手动配 ★★★
中断 NVIC,IRQHandler 无 NVIC,改用 GIC + 异常向量表 ★★★★
启动流程 硬件自动跳到 0x0000_0000 / 复位向量 手写启动汇编 + 链接脚本 ★★★★★
编译工具 Keil MDK 一键编译 arm-linux-gcc + Makefile 手动链接 ★★★★
下载方式 STC-ISP / ST-Link imxdownload 制作 SD 卡镜像 ★★
C 语言运行环境 自动完成 必须自己清 BSS、重定位、设栈 ★★★★★
汇编 基本没用过 指令集 + 寻址方式 + 现场保存 ★★★★★

2.2 必须补的三个知识缺口

  1. ARMv7-A 寄存器组:Cortex-A7 有 37 个寄存器、9 种 CPU 模式,而 Cortex-M3 只有 R0--R15 + PSR。这是理解异常/中断与现场保存的前提。
  2. 存储器的"段"概念.text / .rodata / .data / .bss 各自的运行位置与加载位置不同------这是第 9 章重定位的全部理由。
  3. 编译---汇编---链接---加载"四步链" :搞不清 gcc → as → ld → objcopy 各产出什么文件,后面必崩。

好消息 :你学过的 51 直接操作寄存器(P1 = 0xFE)、STM32 的位带操作/寄存器宏定义,都是这门课的直系前置。韦东山讲"寄存器就是内存里某个固定地址上的一个可读写单元",你其实早就用过,只是没上升为世界观。


3. 环境准备(半天内搞定)

3.1 硬件清单

项目 建议 说明
开发板 韦东山 IMX6ULL Pro / Mini(100ASK_IMX6ULL) 课程代码与之严格对应,建议直接买同款
存储卡 8--16 GB Class10 microSD 裸机程序从 SD 卡启动
读卡器 USB 读卡器 烧写镜像
串口模块 CH340 / CP2102 USB-TTL 三线接法:TX↔RX、RX↔TX、GND↔GND
网线 可选 后续 NFS 挂载内核时必需
电源 5V/2A DC 别用电脑 USB 口带不动

3.2 软件与工具链

类别 工具 备注
交叉编译 arm-linux-gnueabihf-gcc(韦东山提供 Windows 版工具链) 装完把 bin 加入 PATH,arm-linux-gnueabihf-gcc -v 验证
汇编器/链接器 随工具链自带的 as / ld / objcopy / objdump objdump -d 是反汇编主力
编辑器 VS Code(推荐)或 CodeBlocks 第 8-1 讲会讲"Keil 背后的命令"
烧录 imxdownload(韦东山提供) ./imxdownload xxx.bin /dev/sdX
串口终端 MobaXterm / SecureCRT / putty 波特率 115200-8-N-1
调试(进阶) OpenOCD + GDB / J-Link 早期可用"点灯+串口打印"代替

3.3 与 Keil 时代的思维切换

维度 Keil(你熟悉的) 裸机 gcc(本课)
编译入口 点 Build 按钮 make
启动文件 Keil 自带 startup_stm32.s 自己写 start.S
链接地址 图形界面里填 0x0800_0000 自己写 led.lds 链接脚本
下载地址 ST-Link 自动烧 Flash 手动把 .bin 摆放到 SD 卡指定偏移
全局变量初值 自动从 Flash 拷到 RAM 自己写拷贝循环(重定位)
未初始化变量 自动清零 自己清 BSS 段

一句话:STM32 帮你做完的事,IMX6ULL 裸机课要你自己做一遍------这正是这门课的价值所在。


4. 三阶段速通路线(总计 4--6 周)

阶段一:点亮世界(约 1 周)------先跑通,别纠结原理

顺序 章节 目标 必做实验
1 第 1 章 下载资料,装上工具链 编译并烧录官方示例
2 第 2 章 分清 MCU/MPU/AP,认识板子硬件框图 对着原理图找到 LED 与对应引脚
3 第 3 章 3-1~3-5 用寄存器点亮 LED 手写 GPIO 配置代码,改寄存器观察现象
4 第 6 章 按键读入 + 判断 按键控制 LED 亮灭
5 第 7 章 UART 收发 串口打印 "Hello IMX6ULL",形成调试手段

阶段验收 :能脱离 IDE,用命令行编译出 .bin,烧到 SD 卡,板上 LED 按你的代码闪烁,串口能打印自己想打印的话。

阶段二:看懂世界(约 2 周)------最关键的认知跃升

顺序 章节 目标 必做实验
6 第 4 章 4-1~4-7 ARM 寄存器组 + 汇编指令分类 用汇编模拟器单步执行,观察寄存器变化
7 第 5 章 5-1~5-5 C 与汇编的对应关系、反汇编 objdump -d 反汇编自己的 led.c,逐行对照
8 第 5-5 讲 纯汇编点灯 把 LED 代码全部改用汇编写一遍

阶段验收 :给你一段 C 代码,你能说出编译器大概会生成什么样的汇编;能用 objdump 找到 main 函数的入口地址;理解"函数调用就是保存 LR + 跳转"。

阶段三:掌控世界(约 2--3 周)------工程化与系统级

顺序 章节 目标 必做实验
9 第 8 章 8-1~8-8 编译链接全过程 + Makefile 为点灯程序写一个能用的 Makefile,支持 make clean
10 第 9 章 9-1~9-7 段、链接脚本、重定位、清 BSS 写链接脚本,实现带初始值全局变量的正确运行
11 第 10 章 10-1~10-10 异常向量表、CPU 模式、SVC、GIC 实现 GPIO 中断,按键触发中断处理函数

阶段验收:能解释"为什么全局变量初值存在 Flash 里而运行时在 RAM 里";能自己写出异常向量表;按键能通过 GIC 触发中断。


5. 逐章精讲与"快进/必看"标注

第 2 章 嵌入式概念及硬件组成

视频 建议 要点
2-1 处理器的区分 MCU_MPU_AP 必看 你以前玩的 STM32 是 MCU(无 MMU、跑裸机/RTOS);IMX6ULL 是 MPU/AP(有 MMU、跑 Linux)。这是"为什么 STM32 不用重定位而这里要"的根源
2-2 嵌入式系统硬件组成 必看 SoC 内部框图:CPU 核、总线矩阵、外设控制器、DDR 控制器。建立"CPU 通过总线访问所有外设"的模型

第 3 章 第一个程序(IMX6ULL 点灯)

视频 建议 要点
3-1 硬件知识_LED 原理图 必看 学会读原理图:LED 接在哪根 GPIO 上、高电平还是低电平点亮
3-2 GPIO 引脚操作方法概述 快进 通用 GPIO 概念你已在 STM32 学过,2 倍速
3-3 IMX6ULL 的 GPIO 操作方法 必看 三种方法:库函数 / 寄存器 / 汇编。重点看"寄存器三件套"
3-4 IMX6ULL 的 LED 寄存器操作 全课重点 使能时钟 → 配置复用 → 配置电气属性 → 设方向 → 写数据
3-5 IMX6ULL 的 LED 编程 必看 完整代码落地

IMX6ULL GPIO 五步法(务必背下来):

复制代码
① CCM_CCGRx     使能 GPIO 模块时钟(不用就断电,省电设计)
② IOMUXC_SW_MUX_CTL_PAD_x   把物理引脚复用为 GPIO 功能(ALT5)
③ IOMUXC_SW_PAD_CTL_PAD_x   配置驱动能力、上下拉、压摆率
④ GPIOx_GDIR    设方向(1=输出,0=输入)
⑤ GPIOx_DR      写电平(输出)/ 读电平(输入)

对比记忆 :STM32 里 __HAL_RCC_GPIOA_CLK_ENABLE() + GPIO_Init() 帮你做完了 ①②③④,这里全部变成手动写寄存器。你不是在学新东西,是在看 HAL 库的底牌。

第 4 章 ARM 架构

视频 建议 要点
4-1 地址空间_RISC 与 CISC 必看 统一编址 vs 独立编址;ARM 是 RISC(加载/存储架构,运算必须经寄存器)
4-2 ARM 内部寄存器 核心必看 R0--R15、CPSR、SPSR;R13=SP、R14=LR、R15=PC。理解 LR 是理解函数返回与中断现场的关键
4-3 ARM 汇编 慢看+手抄 MOV / LDR / STR / ADD / B / BL / CMP / BEQ 等
4-4 ARM 汇编模拟器 必看 单步执行看寄存器值变化,这是最有性价比的学习工具
4-5 内存访问指令 必看 LDR/STR、多寄存器 LDM/STM、寻址方式
4-6 数据处理指令 必看 算术/逻辑/移位/比较,条件执行是 ARM 特色
4-7 跳转指令 必看 B / BL / BX / BLX,区分"跳过去还回不回来"

这一章的坎 :视频密度大、信息量猛。建议每看一节就打开模拟器敲 5 行汇编单步跑一遍,比看三遍视频都管用。

第 5 章 第 1 个程序深度解析

视频 建议 要点
5-1 编程知识_进制 快进 已掌握
5-2 编程知识_字节序_位操作 必看 小端序(低字节存低地址);位操作是寄存器编程基本功
5-3 汇编_反汇编_机器码 必看 objdump 看机器码,建立"源码 ↔ 机器码"的映射
5-4 C 与汇编深入分析 全课精华 函数调用过程、栈帧、参数传递(R0--R3)、返回值
5-5 纯汇编点灯 必看 把 C 全部换成汇编,理解 C 只是"人写的方便话"

核心收获:C 语言里每一行代码,最终都是"几条 ARM 指令 + 几个内存访问"。

第 6 章 使用按键控制 LED

视频 建议 要点
6-1 使用按键控制 LED 1.5 倍速 只新增"输入方向配置 + 读 DR 寄存器"。注意按键消抖------输入方向、上下拉配置

第 7 章 串口 UART 编程

视频 建议 要点
7-1 硬件知识_UART 硬件介绍 快进 波特率、起始/停止位、奇偶校验------STM32 已学过
7-2 IMX6ULL_UART 操作 必看 时钟源(PLL3 分频)、UCR1--UCR4、UFCR、UBIR/UBMR 定波特率
7-3 IMX6ULL_UART 编程 必看 实现 putchar / puts / printf 重定向

工程价值:串口是裸机阶段唯一的"printf 调试"。做完这章,后面所有调试都轻松一个量级。

第 8 章 keil_gcc_Makefile

视频 建议 要点
8-1 KEIL_IDE 背后的命令 必看 看懂 Keil 输出窗口的那些命令行,你就"脱敏"了
8-2 安装 windows-gcc 工具_CodeBlocks 快进 照做即可
8-3 gcc 编译过程详解 必看 预处理 → 编译 → 汇编 → 链接,四步分别产出 .i / .s / .o / .elf
8-4 Makefile 的引入及规则 必看 目标:依赖 + Tab + 命令
8-5 Makefile 语法 必看 变量、通配符、模式规则 %.o: %.c
8-6 Makefile 函数 了解 wildcardpatsubst,能看懂即可
8-7 Makefile 实例 必看 抄一份改一份
8-8 改造裸机程序的 Makefile 必看 让第 3 章的点灯程序脱离 IDE 编译

推荐的核心 Makefile 骨架(背下来):

makefile 复制代码
CROSS   = arm-linux-gnueabihf-
CC      = $(CROSS)gcc
LD      = $(CROSS)ld
OBJCOPY = $(CROSS)objcopy
OBJDUMP = $(CROSS)objdump

CFLAGS  = -Wall -O2 -nostdlib -ffreestanding
LDFLAGS = -T led.lds

objs := start.o led.o

led.bin: $(objs)
	$(LD) $(LDFLAGS) -o led.elf $^
	$(OBJCOPY) -O binary -S led.elf $@
	$(OBJDUMP) -D -m arm led.elf > led.dis

%.o: %.c
	$(CC) $(CFLAGS) -c -o $@ $<
%.o: %.S
	$(CC) $(CFLAGS) -c -o $@ $<

clean:
	rm -f *.o *.elf *.bin *.dis

第 9 章 代码重定位

视频 建议 要点
9-1 段的概念_重定位的引入 必看 .text / .rodata / .data / .bss 各自性质
9-2 重定位要做的事情 必看 把数据的加载地址 搬到运行地址
9-3 链接脚本使用与分析 核心必看 SECTIONS { . = 0x87800000; .text {...} .data {...} .bss {...} }
9-4 数据段重定位 必看 写汇编循环搬运 .data
9-5 清除 BSS 段 必看 .bss 只占空间不留数据,运行前必须清零
9-6 代码段重定位 必看 理解位置无关码与相对跳转
9-7 重定位的纯 C 函数实现 必看 用 C 完成,但要注意函数本身必须已在正确位置运行

这是全课最抽象的一章,也是最值钱的一章。 参考链接脚本:

lds 复制代码
SECTIONS
{
    . = 0x87800000;
    .text : { *(.text) }
    .rodata : { *(.rodata) }
    .data : { *(.data) }
    __bss_start = .;
    .bss : { *(.bss) *(COMMON) }
    __bss_end = .;
}

第 10 章 异常与中断

视频 建议 要点
10-1 异常与中断概念引入 必看 异常种类、处理流程(保存现场 → 处理 → 恢复现场)
10-2 ARM 架构中异常与中断的处理 必看 异常向量表(8 个入口)、向量地址基址
10-3 异常处理深入分析_保存现场 核心必看 STMFD SP!, {R0-R12, LR} 保存,LDMFD 恢复
10-4 CPU 模式_状态与寄存器 必看 User/FIQ/IRQ/SVC/Abort/Undef/System 模式与各自的 SP/LR
10-5 ARM_Thumb 指令集示例 了解 Thumb 是 16 位编码,省空间
10-6 实战_未定义指令异常 必看 亲手触发异常,看向量表是否生效
10-7 实战_SVC 异常 必看 SVC 是"主动陷入",Linux 系统调用就靠它
10-8 中断的硬件框架 必看 外设 → GIC → CPU,两级控制器
10-9 GIC 介绍与编程 必看 分发器 + CPU 接口;使能、优先级、目标 CPU、确认/结束中断
10-10 实战_GPIO 中断编程 必看 按键触发 GPIO 中断,完整跑通

异常向量表样板:

asm 复制代码
.text
.global _start
_start:
    b   reset          @ 0x00 复位
    b   undef_handler  @ 0x04 未定义指令
    b   svc_handler    @ 0x08 软中断
    b   prefetch_handler
    b   data_handler
    nop                @ 0x14 保留
    b   irq_handler    @ 0x18 IRQ
    b   fiq_handler    @ 0x1C FIQ

6. 核心难点攻坚

6.1 用寄存器点灯"看见"计算机如何工作(本书精华)

韦东山讲这个例子的厉害之处,在于它把整个计算机的工作模型压缩成了 5 行代码

c 复制代码
*(volatile unsigned int *)0x020C406C |= (3 << 26);   /* 使能 GPIO1 时钟 */
*(volatile unsigned int *)0x020E0068  = 0x5;         /* 引脚复用为 GPIO1_IO03 */
*(volatile unsigned int *)0x020E02F4  = 0x10B0;      /* 电气属性配置 */
*(volatile unsigned int *)0x0209C004 |= (1 << 3);    /* 方向:输出 */
*(volatile unsigned int *)0x0209C000 &= ~(1 << 3);   /* 输出低电平 → 点亮 */

它让你"看见"了什么:

现象 揭示的本质
0x020C406C 这个数字 地址空间:整个 SoC 就是一片编了号的"储物柜",外设和内存共用同一套编号(统一编址)
往地址写 1 或 0 总线:CPU 发地址 → 地址译码 → 选中某个外设 → 写数据线 → 寄存器值改变
LED 亮了 外设寄存器不是抽象概念,就是触发器/锁存器的集合,值改变 → 电压改变 → 硬件动作
volatile 不能省 编译器不知道这个"内存"会自己变,会被优化掉
为什么先使能时钟 寄存器本身也要耗电,SoC 把每个模块的时钟做成开关

一句话:"程序"就是"往哪些地址按什么顺序写什么数" 。指令也是被放在某个地址上的数据,CPU 一遍遍地"取指 → 译码 → 执行"。当你理解了 LED 是被一个数字控制的,你就理解了 CPU 是被一堆数字控制的。

建议动手:把上面 5 个地址的数值改成错误的值(比如去掉时钟使能),观察现象;再在串口打印这些寄存器的读回值。"改一个数,看一个现象"是这门课最高效的学习方法。

6.2 Cortex-M3 与 ARMv7-A 的本质差异

维度 STM32(Cortex-M3) IMX6ULL(Cortex-A7)
指令集 Thumb-2 为主 ARM + Thumb,混合
寄存器组 16 个通用寄存器,一套 37 个寄存器,按模式分组
特权/异常 Thread/Handler 两模式 7 种特权模式 + User
中断控制器 NVIC(核内) GIC(核外)
中断入口 向量表自动跳转,硬件压栈 手写向量表 + 手动保存现场
启动 硬件自动完成 手写 start.S
内存管理 无 MMU(可选 MPU) 有 MMU,Linux 必需
编译器 armcc / arm-none-eabi-gcc arm-linux-gnueabihf-gcc

关键结论 :Cortex-M 系列是"对程序员友好的简化版 ARM",Cortex-A 系列是"完整版"。你在 STM32 上"白嫖"的那些自动机制,是 ARM 架构里本来就该程序员做的事。

6.3 汇编与 C 的边界:启动代码

start.S 是裸机程序真正的第一行代码,典型结构:

asm 复制代码
.global _start
_start:
    /* 1. 设置栈指针(不同模式各设一份) */
    ldr sp, =0x80200000
    /* 2. 可选:关看门狗、初始化时钟 */
    /* 3. 重定位 .data(第 9 章内容) */
    /* 4. 清 BSS */
    /* 5. 跳转到 C 的 main */
    bl  main

为什么必须用汇编写这一段? 因为 C 语言的运行前提就是"栈已就绪、全局变量已就位"------而这个前提在 C 代码里没法自己建立(先有鸡还是先有蛋)。

6.4 代码重定位与链接脚本(全课最难)

三个必须想清楚的问题:

问题 答案
为什么需要重定位? 程序运行地址与存储地址不一致:代码存在 SD 卡/Flash 的某处,但必须搬到 RAM 的 0x87800000 才能高速运行
哪些段要搬? .data 要从加载地址搬到运行地址;.bss 不用搬但必须清零;.text 若位置无关可原地或在 NOR 上直接跑
怎么搬? 在链接脚本里定义 __data_load_addr__data_start/__data_end 符号,汇编里循环 LDR/STR 搬运

调试口诀:现象是"全局变量初值全是 0 或乱码" → 十有八九是重定位没做或做错;现象是"未初始化变量有随机值" → BSS 没清。

6.5 异常向量表与 GIC 中断

中断处理四步(一定要形成肌肉记忆):

复制代码
① 硬件:外设产生中断信号 → GIC 分发器记录 → CPU 接口仲裁 → 拉高 IRQ
② CPU:跳转到向量表 0x18 处的 irq_handler(此时自动切到 IRQ 模式,LR 已被设为返回地址)
③ 软件:lr -= 4 → 保存现场(STMFD)→ 读 GIC 的 IAR 得到中断号 → 分发处理 → 写 GIC 的 EOIR 结束中断 → 恢复现场(LDMFD)→ `subs pc, lr, #4` 返回
④ 关键细节:记得清外设自己的中断标志位(GPIOx_ISR),否则中断会反复触发

GIC 编程要点:

  • GICD_ISENABLERn:使能某个中断号
  • GICD_IPRIORITYRn:设置优先级(数值越小优先级越高)
  • GICD_ITARGETSRn:指定目标 CPU
  • GICC_PMR / GICC_CTLR:CPU 接口允许的中断优先级与总开关
  • GICC_IAR 读中断号 → GICC_EOIR 写回同一值表示处理完毕

7. 建议时间表(4 周冲刺版 / 6 周稳健版)

周次 冲刺版(每天 3--4 h) 稳健版(每天 2 h)
第 1 周 第 1--3 章 + 第 6、7 章:点灯、按键、串口全部跑通 第 1--3 章,点灯吃透
第 2 周 第 4 章 + 第 5 章:汇编与反汇编 第 6、7 章 + 第 4 章前半
第 3 周 第 8 章 + 第 9 章:Makefile 与重定位 第 4 章后半 + 第 5 章
第 4 周 第 10 章 + 综合项目 第 8、9 章
第 5--6 周 --- 第 10 章 + 综合项目

综合验收项目(强烈建议做,能串起 90% 的知识点):

用自己写的启动文件 + 链接脚本 + Makefile,实现"按键触发 GPIO 中断 → 中断里通过 UART 打印按键次数 → 同时 LED 闪烁"。全部代码不允许用任何现成库。


8. 调试与验证手段

手段 用途 使用要点
LED 最原始也最可靠 程序"跑没跑到这里"的探针
串口打印 主力调试通道 先保证 putchar 能用
objdump -d 看反汇编 arm-linux-gnueabihf-objdump -d led.elf
readelf -S 看段布局与地址 验证链接脚本是否生效
汇编模拟器 学指令阶段 单步看寄存器/内存变化
OpenOCD + GDB 断点、单步 进阶,重定位调不出来时救命
万用表/示波器 硬件层验证 怀疑原理图或接线时用

排错顺序(黄金流程):先确认程序是否运行(点灯)→ 再确认初始化顺序(时钟→复用→方向)→ 再看地址与位是否正确 → 最后才怀疑硬件。


9. 与后续课程的衔接

本课知识点 后续用途
寄存器操作 + 时钟配置 U-Boot 的 board_init_f、时钟树初始化
链接脚本 + 重定位 U-Boot / Linux 内核的 vmlinux.lds,理解内核启动
异常向量 + GIC Linux 中断子系统、驱动中的 request_irq
Makefile / gcc 内核 Kconfig + Makefile 构建体系
串口驱动 consoleearly_printk

学完这门课,你就拥有了**"从裸机到操作系统"的最后一公里**,之后学 U-Boot 移植、内核裁剪、驱动开发都会顺得多。


10. 常见问题 FAQ

Q1:我没学过汇编,能直接上手吗?

不能跳。第 4、5 章是全课地基。但可以先用 C 写点灯(第 3 章),建立成就感,再回头补汇编。

Q2:能不能不用 Makefile,继续用 IDE?

建议不用。第 8 章的价值不在"会用 Makefile",而在"理解编译链接过程"------这是第 9 章的入场券。

Q3:SD 卡烧录老是没反应?

90% 是这三点:.bin 文件没生成(objcopy 漏了)、烧录偏移不对(韦东山镜像需放在特定扇区)、开发板拨码开关没设成 SD 卡启动。

Q4:重定位看不懂怎么办?

先把链接脚本里的符号用 readelf -s 打印出来,在纸上画出"Flash 里怎么摆、RAM 里怎么摆",再回来看代码。画图比看视频有效十倍。

Q5:只学"快速通道"跳过第 9、10 章行不行?

可以,但会止步于"会点亮外设"。想走 Linux 驱动路线,第 9、10 章省不掉。

Q6:需要同时学 STM32 和 IMX6ULL 吗?

不必。STM32 是你的"已知锚点",用它对照理解差异即可,不需要在这门课上再复习 STM32。


11. 一页速查:寄存器点灯最小代码

start.S

asm 复制代码
.text
.global _start
_start:
    ldr sp, =0x80200000      @ 设置栈
    bl  main                 @ 跳转 C 入口
halt:
    b   halt

led.c

c 复制代码
#define CCM_CCGR1        (*(volatile unsigned int *)0x020C406C)
#define IOMUXC_MUX_IO03  (*(volatile unsigned int *)0x020E0068)
#define IOMUXC_PAD_IO03  (*(volatile unsigned int *)0x020E02F4)
#define GPIO1_GDIR       (*(volatile unsigned int *)0x0209C004)
#define GPIO1_DR         (*(volatile unsigned int *)0x0209C000)

static void led_init(void)
{
    CCM_CCGR1       |=  (3 << 26);   /* 使能 GPIO1 时钟 */
    IOMUXC_MUX_IO03  =  0x5;         /* 复用为 GPIO1_IO03 */
    IOMUXC_PAD_IO03  =  0x10B0;      /* 电气属性 */
    GPIO1_GDIR      |=  (1 << 3);    /* 输出 */
}

static void delay(volatile int n) { while (n--); }

int main(void)
{
    led_init();
    while (1) {
        GPIO1_DR &= ~(1 << 3);       /* 低电平:点亮 */
        delay(1000000);
        GPIO1_DR |=  (1 << 3);       /* 高电平:熄灭 */
        delay(1000000);
    }
    return 0;
}

编译烧录三步

bash 复制代码
make                                   # 生成 led.bin
./imxdownload led.bin /dev/sdX         # 烧到 SD 卡
# 插卡上电,串口 115200 观察,LED 闪烁

附:学习心态提醒

裸机开发的挫败感几乎都来自同一件事:"代码看起来没错,但板上没反应" 。这时候不要重看视频,要用现象反推原因 ------LED 不亮,就先用串口确认程序跑到了哪一句;串口没输出,就先用 LED 确认程序有没有进 main

能"看见"程序在哪一步断掉,比看懂任何一个知识点都重要。 这门课真正的收获不是 10 章知识,而是你从此拥有了"从硅片到代码"的完整视野。


文档版本:v1.0 | 适用课程:韦东山《ARM 架构与编程------基于 IMX6ULL》

相关推荐
糖糖单片机设计1 小时前
基于 STM32 的智能净水器系统
stm32·单片机·嵌入式硬件
zcmodeltech1 小时前
火电厂模型能演示冷态启动和故障处理吗?——基于STM32与Modbus RTU的集控实训控制系统设计
数据结构·stm32·单片机·嵌入式硬件·能源
llilian_161 小时前
标准时间间隔发生器应用解决方案 脉冲发生器 时间测量仪
大数据·网络·人工智能·功能测试·单片机·嵌入式硬件·51单片机
桀人2 小时前
STM32之GPIO四种输出模式——P-MOS和N-MOS管的工作原理——双二极管钳位保护电路——上拉电阻
stm32·单片机·嵌入式硬件
HRTOS2 小时前
HRTOS 4.0 DEBUG:面向 8051 实时系统运行状态的轻量级调试组件
单片机·嵌入式硬件·51单片机
LCG元2 小时前
STM32F407 I2S驱动WM8978音频播放实战:PLLI2S时钟整定、DMA双缓冲防爆音与WAV采样率实测
stm32·嵌入式硬件·音视频
不怕犯错,就怕不做2 小时前
RK linux在buildroot中如何添加linux命令
linux·驱动开发·嵌入式硬件
咖丨喱3 小时前
【MMC驱动分析】
嵌入式硬件
fhq_fn_jgd3 小时前
51单片机(中断,定时器)
stm32·单片机·嵌入式硬件