mem 设备控制 GPIO - C程序通过sysfs文件系统使用GPIO中断

提示:通过 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
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

野火少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值