i.MX6ULL裸机开发今日知识点总结
一、C语言操作寄存器
volatile关键字:防止编译器优化寄存器读写,保证每次都直接读硬件寄存器地址,不能缓存到CPU寄存器。- 寄存器两种定义方式
- 方式1:宏直接强转地址:
#define 寄存器名 *((unsigned int *)地址) - 方式2:结构体映射寄存器组,把一组连续寄存器封装成结构体,用指针访问,代码更简洁。
- 方式1:宏直接强转地址:
- LED裸机驱动函数
clock_init():打开CCM时钟门控CCGR0‑CCGR6,全部写0xFFFFFFFF,开启全部外设时钟;i.MX6ULL外设默认时钟关闭,不开启GPIO无法工作。led_init():IO复用配置、电气属性配置、设置GPIO为输出方向。led_on() / led_off():操作GPIO数据寄存器DR控制引脚电平。led_delay():软件空循环延时,缺点:延时不精准,受CPU主频影响。
- 基础Makefile编写
- 定义交叉编译工具链变量;
- 模式规则
%.o:%.S、%.o:%.c,自动把汇编、C文件编译为.o目标文件; - 链接:
-Ttext 地址指定程序运行起始地址; objcopy:把elf转为可烧录的bin二进制文件;objdump:生成反汇编.dis文件,用于调试查看汇编代码;clean伪目标:清理编译产物;load伪目标:烧录bin到SD卡。
二、SDK头文件、BSP工程管理、链接脚本
-
NXP SDK头文件使用
- 不使用完整IDE,只提取SDK的头文件使用;
- 使用SDK提供函数:
IOMUXC_SetPinMux()引脚复用、IOMUXC_SetPinConfig()配置引脚电气参数; - 通过指针方式访问寄存器:
GPIO1->GDIR、GPIO1->DR。
-
工程BSP目录规范(板级支持包)
目录 存放内容 project main.c、start.S(启动汇编)imx6ull 芯片SDK头文件 MCIMX6Y2.h、fsl_iomuxc.h等bsp 外设驱动: led.c/h、beep.c/h硬件模块代码 -
蜂鸣器驱动硬件基础
- S8550是PNP三极管做开关;基极高电平导通,蜂鸣器响。
-
链接脚本 imx6ull.lds
- 作用:给链接器规定程序各段在DDR内存的排布蓝图。
. = 0x87800000:设置程序链接起始地址。- 段说明
.text:代码段,存放汇编、C的指令;必须把start.o放在text段最开头,上电最先执行启动汇编。.rodata:只读常量数据段。.data:已经初始化的全局变量。.bss:未初始化全局变量;定义符号__bss_start、__bss_end标记BSS段首尾地址。
-
启动汇编start.S任务(非常重要) 上电不能直接跑main函数,汇编要做三件事:
- 设置栈指针SP(C语言函数调用、局部变量依赖栈);
- 根据
__bss_start、__bss_end把BSS段全部清零; - 跳转执行C语言
main函数。
三、踩坑重点
- Makefile自动扫描源码时,目录名拼写、文件名大小写必须严格匹配 (
start.S大写S,小写.s不会被匹配)。 - 汇编语法:指令和标签之间必须有空格,不能下划线连写,例:
bl main,不能写bl_main。 - 链接脚本的
__bss_start、__bss_end是给汇编使用的符号,缺失会报未定义错误。 - main函数标准写法是
int main(void),void main(void)会报编译器警告。 - 裸机开发顺序:开外设时钟 → 初始化GPIO引脚 → while(1)业务逻辑,时钟不能后开。
- 全部打开CCGR时钟只是实验写法;产品中只开启需要的外设时钟降低功耗。
四、整体程序执行流程
开发板上电 → 执行start.S启动汇编 → 设置栈、清零BSS段 → 跳转到main → 开启外设时钟 → 初始化LED/蜂鸣器GPIO → while死循环实现闪烁鸣叫。