提示:通过 mem 设备控制 GPIO 知识点;使用C程序通过sysfs文件系统使用GPIO中断
前言
通过io 操作实现点亮LED灯操作。 但是IO操作的都是寄存器地址,所以先搞清楚寄存器知识点。
参考资料
GPIO 控制和操作-使用命令通过sysfs文件系统控制GPIO
RK3568驱动指南|第十二篇 GPIO子系统-第129章 GPIO控制和操作实验
使用C程序通过sysfs文件系统控制gpio
rk3588写入寄存器
linux IO指令 读写GPIO口电平实例
操作寄存器来控制GPIO-点亮LED灯
- 这里目标是LED灯点亮实验,在寄存器控制GPIO基础上进一步底层抽象,用mem设备来控制GPIO
- 在C程序控制sysfs文件系统控制GPIO基础上,进一步了解、掌握 C程序通过sysfs文件系统,使用GPIO中断
这本身是两个知识点,但都很重要,有必要进一步理解学习。
一、通过 mem 设备控制 GPIO
/dev/mem 设备 知识点
/dev/mem 是一个特殊的字符设备文件,它提供了对整个物理内存的直接访问。通过这个设备,用户空间程序可以读写任意的物理内存地址。
-
在某些情况下, 我们可能无法直接使用 IO 命令来访问 GPIO 寄存器, 或者希望使用更高级的抽象来控制硬件。 这时, 可以使用/dev/mem 设备来操作物理内存, 以实现对 GPIO
寄存器的访问。 -
通过打开/dev/mem 设备文件, 并将其映射到用户空间的内存中, 我们可以直接读写物理内存地址, 从而实现对 GPIO 寄存器的控制。 这种方法相对于 IO 命令更加灵活, 可以使用更高级的编程语言(如 C/C++) 来编写控制逻辑。
控制源码程序
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#define GPIO_REG_BASE 0xFDD60000 // GPIO base address
#define GPIO_SWPORT_DDR_L_OFFSET 0x0008 // DDR direction mode offset
#define GPIO_SWPORT_DR_L_OFFSET 0x0000 // DR direction mode offset
#define SIZE_MAP 0x1000
// 打开LED灯
void LED_ON(unsigned char *base)
{
// 设置LED灯的方向为输出
*(volatile unsigned int *)(base + GPIO_SWPORT_DDR_L_OFFSET) = 0x80008044;
// 将LED灯打开
*(volatile unsigned int *)(base + GPIO_SWPORT_DR_L_OFFSET) = 0x80008044;
}
// 关闭LED灯
void LED_OFF(unsigned char *base)
{
// 设置LED灯的方向为输出
*(volatile unsigned int *)(base + GPIO_SWPORT_DDR_L_OFFSET) = 0x80008044;
// 将LED灯关闭
*(volatile unsigned int *)(base + GPIO_SWPORT_DR_L_OFFSET) = 0x80000044;
}
int main(int argc, char *argv[])
{
int fd;
unsigned char *map_base;
// 打开/dev/mem设备
fd = open("/dev/mem", O_RDWR);
if (fd < 0)
{
printf("open /dev/mem error \n");
return -1;
}
// 将物理地址映射到用户空间
map_base = (unsigned char *)mmap(NULL, SIZE_MAP, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO_REG_BASE);
if (map_base == MAP_FAILED)
{
printf("map_base error \n");
return -2;
}
while (1)
{
// 打开LED灯
LED_ON(map_base);
// 等待1秒
usleep(1000000);
// 关闭LED灯
LED_OFF(map_base);
// 等待1秒
usleep(1000000);
}
// 解除映射
munmap(map_base, SIZE_MAP);
// 关闭文件描述符
close(fd);
return 0; // 返回0表示程序正常退出
}
将 控制程序编译成可执行文件,然后拷贝到开发板上,执行即可实现LED的亮灭闪烁:
./gpioctrl_by_mem 15
map_base 函数分析
mmap(memory map)函数用于将设备内存或文件映射到进程的地址空间,从而允许应用程序直接通过内存访问来操作硬件寄存器。
参数详解
addr - 映射起始地址
-
建议设为 NULL,由内核自动选择合适地址
-
如果指定地址,通常需要页对齐(sysconf(_SC_PAGE_SIZE))
-
非 NULL 时,内核会将其作为提示,但不保证使用该地址
length - 映射区域长度
-
映射的字节数
-
实际会向上取整到系统的页大小整数倍
-
可以通过 sysconf(_SC_PAGE_SIZE) 获取页大小
prot - 内存保护标志
控制对映射内存的访问权限,可以组合使用:
| 标志 | 说明 | 值 |
|---|---|---|
| PROT_READ |

最低0.47元/天 解锁文章
2804

被折叠的 条评论
为什么被折叠?



