koi77u头像
关注

嵌入式学习——ARM(4)

一、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.oTARGET = 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技术社区

原文链接:https://blog.csdn.net/koi77u/article/details/166252707

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--