一、C语言点灯
1. volatile 关键字:告诉编译器该地址的内容可能被硬件随时改变,禁止优化,保证每次都真实读写寄存器/内存。
2. 定义寄存器地址:用宏把寄存器物理地址映射为可读写的指针。
#include <reg51.h>
#define P2 *((volatile unsigned char*)0x80) // 51 单片机示例写法
#define CCM_CCGR0 *((unsigned int *)0x020C4068) // 时钟使能寄存器 0~6
#define CCM_CCGR1 *((unsigned int *)0x020C406C)
...
#define CCM_CCGR6 *((unsigned int *)0x020C4080)
#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 *((unsigned int *)0x020E0068) // 复用功能
#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 *((unsigned int *)0x020E02F4) // 电气特性
#define GPIO1_DR *((unsigned int *)0x0209C000) // 数据寄存器
#define GPIO1_GDIR *((unsigned int *)0x0209C004) // 方向寄存器
3. 驱动代码:
void clock_init(void) // 打开全部外设时钟
{ CCM_CCGR0 = 0xFFFFFFFF; ... CCM_CCGR6 = 0xFFFFFFFF; }
void led_init(void) // 初始化 LED 引脚
{
IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 = 0x05; // 复用为 GPIO
IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 = 0x10B0; // 电气特性
GPIO1_GDIR |= (1 << 3); // bit3 设为输出
}
void led_on(void) { GPIO1_DR &= ~(1 << 3); } // 数据位清 0
void led_off(void) { GPIO1_DR |= (1 << 3); } // 数据位置 1
void led_delay(unsigned int time) { while (time--); } // 软件延时
4. 优化 Makefile:用模式规则替代逐条命令,%.o : %.S / %.o : %.c 自动编译,变量 OBJS = start.o main.o、TARGET = led,配合 clean / load 伪目标。
5. 优化寄存器访问方式:用结构体把一组连续寄存器组织起来,再整体映射到基地址:
struct GPIO_t {
unsigned int DR; // 数据寄存器
unsigned int DGIR; // 方向寄存器
unsigned int PSR; // 状态寄存器
unsigned int ICR1, ICR2; // 中断控制
unsigned int IMR; // 中断屏蔽
unsigned int ISR; // 中断状态
unsigned int EDGE_SEL;
};
#define GPIO1 (*((struct GPIO_t *)0x0209C000))
二、SDK、蜂鸣器、BSP 工程管理与链接脚本
1. SDK 移植:SDK 存放在 IMAX6ULL/SDK/。完整开发工具本质是 IDE(集代码编写、编译、下载于一体,类似 Keil),用它需要额外购买下载器、编程器、仿真器等设备,所以这里只使用它的头文件。
2. 构建新工程 led_sdk:新建文件夹 → 拷贝 led_c 内的 start.S、main.c、Makefile → 拷贝 SDK 目录下所有头文件。头文件中用到 GPIO_Type 等类型定义。
3. 用 SDK 编写点灯程序:用结构体指针和库函数替代裸宏:
void clock_init(void) { CCM->CCGR0 = 0xFFFFFFFF; ... } // CCM 为结构体指针
void led_init(void)
{
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0); // 复用功能
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0x10B0); // 电气特性
GPIO1->GDIR |= (1 << 3);
}
void led_on(void) { GPIO1->DR &= ~(1 << 3); }
void led_off(void) { GPIO1->DR |= (1 << 3); }
void led_flicker(void) { GPIO1->DR ^= (1 << 3); } // 异或翻转,实现闪烁
其中 IOMUXC_SetPinMux / IOMUXC_SetPinConfig 即寄存器(0x05、0x10B0)的 SDK 封装形式。
4. LED 模块化:将 LED 单独提取成独立模块(后续放进 bsp 目录)。
5. BEEP 蜂鸣器裸机驱动:使用 S8550 PNP 型三极管作开关,基极高电平导通,由 GPIO 控制蜂鸣器通断。
6. BSP(板级支持包)工程管理:
project/:存放必要程序(main.c、start.S)imx6ull/:存放 NXP 提供的头文件(cc.h、core_ca7.h、fsl_common.h、fsl_iomuxc.h、MCIMX6Y2.h)bsp/:存放硬件外设相关功能模块(led.c/h、beep.c/h)Makefile:需要遍历目录
7. 链接脚本 imx6ull.lds:
- 链接脚本在链接阶段为连接器提供蓝图;
- 关键点:启动代码需要在进入 C 语言第一条指令前,将 .bss、.COMMON 段初始化清 0;
- 布局(起点 0x87800000):
.text(obj/start.o 最先)→.rodata(ALIGN(4))→.data(ALIGN(4))→.bss(含*(.COMMON)),并用__bss_start/__bss_end两个符号标出待清零区间的起止。
转载自 CSDN-专业IT技术社区



