嵌入式Linux中的LED驱动控制(续)

news/2024/10/5 3:20:00

前面的实例实现了在野火STM32MP157开发板上对三个LED灯的控制,这里来讨论一下该驱动程序的具体实现方式。由于实例使用的是STM32MP157这款芯片,所以先来看一下与该芯片端口操作相关的寄存器。

先看端口模式寄存器MODER,该类型的寄存器在STM32MP157中有11个,即x的值从A到K。它们分别针对11组不同的I/O端口,其结构完全相同(下同)。下面是该寄存器的全部位结构。它的偏移地址为:0x00。

第31~0位分别配置第15~第0引脚的具体模式,每两位配置一个引脚。当值为00时,引脚为输入模式,值为01时,引脚为通用输出模式,值为10时,引脚为多功能模式,值为11时,引脚为模拟模式。默认为模拟模式。

接着看端口输出类型寄存器OTYPER,下面是该寄存器的全部位结构。它的偏移地址为:0x04。

第15~0位分别配置第15~第0引脚的输出类型,每一位配置一个引脚,第31~16位未使用。当值为0时,引脚为推挽模式,值为1时,引脚为开漏模式。默认为推挽模式。

接下来是端口输出速度寄存器OSPEEDR,下面是该寄存器的全部位结构。它的偏移地址为:0x08。

第31~0位分别配置第15~第0引脚的具体模式,每两位配置一个引脚。当值为00时,引脚为低速模式,值为01时,引脚为中速模式,值为10时,引脚为高速模式,值为11时,引脚为超高速模式。默认为低速模式。

然后看端口上/下拉寄存器PUPDR,下面是该寄存器的全部位结构。它的偏移地址为:0x0C。

第31~0位分别配置第15~第0引脚的具体模式,每两位配置一个引脚。当值为00时,引脚为无上下拉(浮空)模式,值为01时,引脚为上拉模式,值为10时,引脚为下拉模式,值为11时保留。默认为浮空模式。

接着看端口输入数据寄存器IDR,下面是该寄存器的全部位结构。它的偏移地址为:0x10。

第15~0位分别提供第15~第0引脚的输入数据,每一位对应一个引脚,第31~16位未使用。当值为0时,引脚输入为低电平,值为1时,引脚输入为高电平。该寄存器为只读。

然后是端口输出数据寄存器ODR,下面是该寄存器的全部位结构。它的偏移地址为:0x14。

第15~0位分别提供第15~第0引脚的输出数据,每一位对应一个引脚,第31~16位未使用。当值为0时,引脚输出低电平,值为1时,引脚输出高电平。默认为低电平。

最后看端口位配置寄存器BSRR,下面是该寄存器的全部位结构。它的偏移地址为:0x18。

第31~16位分别提供第15~第0引脚的清零,每一位对应一个引脚,写1时引脚清零(输出低电平),写0无效。第15~0位分别提供第15~第0引脚的置位,每一位对应一个引脚,写1时引脚置位(输出高电平),写0无效。默认为无效。

在操作端口的输出电平时,可以有ODR和BSRR两个寄存器选择,虽然两者都能实现端口电平的输出,但还是有所区别的。当要求操作某一引脚的电平而不影响其他引脚的电平时,若使用ODR寄存器则要实现“读——改——写”的过程,即先把ODR数据读出,然后通过逻辑与或进行修改,再写入到ODR寄存器中。若使用BSRR寄存器则可直接写入,非常方便。

除了上述对端口控制的寄存器之外,还有一个时钟使能寄存器也需要讨论(只有一个),它寄存器名称为RCC_MP_AHB4ENSETR,下面是该寄存器的全部位结构。它的偏移地址为:0xA28。

第0~10位分别控制第A~第K组端口的时钟,值为1时使能该组端口时钟,值为0时禁止时钟。默认为禁止。

以上就是本例中使用到的寄存器,他们都位于AHB4总线之中,这些寄存器的地址都是以AHB4的基址为偏移的,具体地址如下表所示。

在Linux系统中,并不能直接使用物理地址对寄存器进行操作,必须先把寄存器的物理地址映射到操作系统中来形成虚拟地址,然后才能进行相应地操作。实现映射功能的函数名为ioremap,其原型为:void __iomem *ioremap(phys_addr_t paddr, unsigned long size)。第一个参数为物理地址,第二个参数为长度,返回值是一个指向__iomem类型的指针。__iomem是一个宏,它表示返回的地址是一个IO存储空间的有效地址。相应的解除映射函数iounmap,其原型为:void iounmap(void *addr)。只有一个参数,为前面映射时的返回指针,该函数没有返回值。

下面以映射GPIO_MODER_PA寄存器为例进行说明,先对GPIO_MODER_PA寄存器的物理地址进行一个宏定义,定义采取基址+偏移量的方式,如下。

#define AHB4_PERIPH_BASE (0x50000000)
#define GPIOA_BASE (AHB4_PERIPH_BASE + 0x2000)
#define GPIOA_MODER (GPIOA_BASE + 0x0000)

然后定义一个用于接收映射的返回值的指针变量,如下。

volatile void __iomem *GPIO_MODER_PA

变量加上前缀volatile关键字,表示它不接受编译器优化(一般定义寄存器都要如此)。

然后就可以进行地址映射了,如下。

GPIO_MODER_PA = ioremap(GPIOA_MODER, 4);

映射成功后,就可以使用GPIO_MODER_PA来进行赋值了,如下。

tmp = ioread32(GPIO_MODER_PA);
tmp &= ~(0x3 << 26);
tmp |= (0x1 << 26);
iowrite32(tmp, GPIO_MODER_PA);

上面的赋值采用了“读——改——写”的方式,所以只改变寄存器的第26、27两位,其余位不变。经过赋值后,GPIOA的第13引脚就被配置成了通用输出模式。

在Linux中,对端口的读写有专用的函数,一般不推荐直接对指针进行操作。ioread32函数用于读取一个32位的值,iowrite32函数用于写入一个32位的值。(早期可能会使用readl和writel函数,现在不推荐使用)

本例把寄存器的地址映射放在了入口函数(led_init)中,同时也把端口配置放在了入口中。把解除映射函数放在出口函数(led_exit)中进行。对芯片寄存器的读、写等操作放在了文件操作接口里面(file_operations结构体成员函数中)。在使用设备时,应用程序会打开设备节点,并通过设备节点的inode结构体、file结构体最终找到file_operations结构体,然后从file_operations结构体中得到操作设备的具体方法。 这部分的具体内容可参见“嵌入式Linux中字符型驱动程序的基本框架”一文。在函数alloc_chrdev_region(&devno, 0, 3, "led")执行后,字符串led会出现在/proc/devices文件中。函数class_create(THIS_MODULE,  "led_dev")执行后,字符串led_dev会出现在/sys/class目录下。函数device_create(led_chrdev_class, Null, devid, Null, "led%d", i)执行后,字符串ledi会出现在/dev目录下。可在开发板上自行查看。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hjln.cn/news/44236.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

通讯协议转换Modbus转Profinet网关

Modbus转Profinet网关是工业通信转换设备,能够实现Modbus协议与Profinet协议之间的有效转换和稳定传输。通过该网关,工业设备之间可以实现数据交换和通信,提高生产效率和智能化程度。支持Modbus RTU主从站。此外,Modbus转 Profinet网关自带网络和串口,支持485/232接口Modb…

python栈帧沙箱逃逸

python栈帧沙箱逃逸 一、生成器 生成器(Generator)是 Python 中一种特殊的迭代器,它可以通过简单的函数和表达式来创建。生成器的主要特点是能够逐个产生值,并且在每次生成值后保留当前的状态,以便下次调用时可以继续生成值。这使得生成器非常适合处理大型数据集或需要延迟…

spring-1-IOC、创建bean的方式、创建bean的过程

1.背景 IOC(Inversion of Control,控制反转) 控制反转是一种设计原则,它将对象的创建和管理责任从应用代码中移交给容器。 在Spring中,IOC容器负责管理应用中的所有对象,包括它们的生命周期和相互之间的依赖关系。 IOC的主要目的是为了减少代码之间的耦合,使代码更加模块…

11-CSS定位

CSS定位01 CSS定位概念理解 01 标准流布局概念的理解02 position属性02 相对定位 依然在标准流中 应用场景: 在不影响其它元素的情况下,对当前元素进行微调 <!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><met…

Combining Recurrent, Convolutional, and Continuous-time Models with Linear State-Space Layers

目录概符号说明LSSL和其它方法的联系代码Gu A., Johnson I., Goel K., Saab K., Dao T., Rudra A., and Re C. Combining recurrent, convolutional, and continuous-time models with linear state-space layers. NeurIPS, 2021.State space representaion-wiki.概 Mamba 系列…

堆基础知识

arenachunk通俗地说,一块由分配器分配的内存块叫做一个 chunk,包含了元数据和用户数据。具体一点,chunk 完整定义如下: struct malloc_chunk {INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk (if free). */INTERNAL_SIZE_T mchunk_size; …

【Azure Spring Apps】Spring App部署上云遇见 502 Bad Gateway nginx

问题描述 在部署Azure Spring App应用后,访问应用,遇见了502 Bad Gateway Nginx。问题解答 502 Bad Gateway, 并且由Nginx返回。而自己的应用中,并没有定义Nginx相关内容,所以需要查看问题是否出现在Azure Spring App服务的设置上。 根据Spring App的通信模型图判断,502的…

学生管理系统的CRUD

include using namespace std; typedef struct Studnet { //初始化结构体变量 int ID; double math_scores; double english_scores; double computer_scores; double total_scores;}Student; void Input_student_score(int size, Student* stu); //输入所有学生信息 void Out…