Led驱动实验之Led灯初始化

发布时间:2023年12月24日

一.? 简介

本文继上一篇文章的学习,上一篇文章初步写好了 Led驱动框架代码的。

文章地址如下:

LED驱动框架代码的实现-CSDN博客

本文继续 Led灯驱动代码的实现,主要学习编写 Led灯 IO的初始化工作。

二.? Led驱动的 IO 初始化

1.? 地址映射

前面进行 Led灯裸机开发实验时,关于 Led的 IO初始化工作包括如下:

1. 使能时钟信号,即设置 Led灯相关的时钟IO口 
2. 复用功能,即设置为 GPIO功能
3. 配置电气属性
4. 设置为输出功能

同理,LED驱动实验中,关于 IO初始化工作也如上。IO初始化工作就是向相关寄存器写入数据。Linux系统有 MMU(memory manage unit)的存在,所以Linux 不能直接访问寄存器的物理地址,MMU会负责将寄存器的物理地址映射为虚拟地址。

所以,Linux驱动开发中,Linux 访问的是 寄存器的虚拟地址值。这里就需要进行地址映射,即将Led灯 IO初始化相关的寄存器物理地址映射为虚拟地址。

参考之前 Led裸机实验,可以找到 Led涉及的寄存器的物理地址,如下:

//寄存器物理地址
#define  CCM_CCGR1_BASE          (0X020C406C)
#define  SW_MUX_GPIO1_IO03_BASE  (0X020E0068)
#define  SW_PAD_GPIO1_IO03_BASE  (0X020E02F4)
#define  GPIO1_GDIR_BASE         (0X0209C004)
#define  GPIO1_DR_BASE           (0X0209C000)

地址映射函数

进行地址映射时,会调用到? ioremap() 函数,定 义 在 内核源码 arch/arm/include/asm/io.h 文件中,定义如下:

#define ioremap(cookie,size) __arm_ioremap((cookie), (size), 
MT_DEVICE)
 
void __iomem * __arm_ioremap(phys_addr_t phys_addr, size_t size, 
unsigned int mtype)
{
 return arch_ioremap_caller(phys_addr, size, mtype,
 __builtin_return_address(0));
}

从上面函数返回值可以看出,这里需要定义一组 __iomem* 类型的指针,存放地址映射后的虚拟地址值:

//地址映射后的虚拟地址指针
static __iomem *  IMX6ULL_CCM_CCGR1;
static __iomem *  IMX6ULL_SW_MUX_GPIO1_IO03;
static __iomem *  IMX6ULL_SW_PAD_GPIO01_IO03;
static __iomem *  IMX6ULL_GDIR;
static __iomem *  IMX6ULL_DR;

关于 ioremap函数的参数传递,之前做过介绍:

Linux系统中的地址映射-CSDN博客

地址映射工作写在 led_init() 函数中,模块卸载接口 led_exit()接口中要进行取消,即取消地址映射。

2.? IO 初始化工作

led灯 IO初始化工作,一般写在 驱动模块加载接口,或者 打开设备接口中。

注意:使用 ioremap 函数将寄存器的物理地址映射到虚拟地址以后,我们就可以直接通过指针访问这些地址,但是 Linux 内核不建议 这么做,而是推荐使用一组操作函数来对映射后的内存进行读写操作。

前面有过介绍:需要调用 readl()函数与 writel()函数。

IO内存访问函数-CSDN博客

这里我写在 加载驱动模块接口中,这里即写在 led_init() 函数中。Led灯 IO 初始化工作包括如下:

(1)使能 Led时钟

参考 Led灯硬件原理图可知, Led灯所使用 IO口是 GPIO01_IO03。结合 IMX6ULL芯片参考手册知道,所以,Led的 使能时钟引脚为 CCM_CCGR1寄存器的 26~27位:

(2)复用为 GPIO功能

(3)配置电气属性

(4)设置为输出功能

文章来源:https://blog.csdn.net/wojiaxiaohuang2014/article/details/135183896
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。