linux下操作gpio寄存器的方法

一、 在驱动中:

  1. 用的时候映射端口:ioremap;

  #define GPIO_OFT(x) ((x) - 0x56000000)
  #define GPFCON (*(volatile unsigned long *)(gpio_va + GPIO_OFT(0x56000050)))
  gpio_va = ioremap(0x56000000, 0x100000); // 物理地址0x56000000, 映射区分配的大小0x100000字节
  这样映射过后,就可以直接操作寄存器了: 
  配置3引脚为输出: GPFCON &= ~(0x3<<(4*2));

  2. 在linux/include/asm-arm/arch-s3c2410/map.h映射, 在linux/include/asm-arm/arch-s3c2410/regs-gpio.h得到各种寄存器的地址,直接对这些地址进行操作即可。
  参考【linux】 linux gpio操作http://www.cnblogs.com/embedded-tzp/p/4450515.html
     gpio映射 http://blog.chinaunix.net/uid-25100840-id-271146.html
      
    misccr = __raw_readl(S3C24XX_MISCCR);
      misccr &= ~clear;
      misccr ^= change;
      __raw_writel(misccr, S3C24XX_MISCCR);
    
    #define __raw_writel(v,a)    (__chk_io_ptr(a), *(volatile unsigned int __force   *)(a) = (v))
  
   下面是内核代码提供的操作gpio寄存器的一些接口:

void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function);

unsigned int s3c2410_gpio_getcfg(unsigned int pin);

void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
unsigned int s3c2410_gpio_getpin(unsigned int pin);
unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change);
int s3c2410_gpio_getirq(unsigned int pin);

linux/include/asm-arm/io.h

#define __raw_writeb(v,a)    (__chk_io_ptr(a), *(volatile unsigned char __force  *)(a) = (v))
#define __raw_writew(v,a)    (__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v))
#define __raw_writel(v,a)    (__chk_io_ptr(a), *(volatile unsigned int __force   *)(a) = (v))

#define __raw_readb(a)        (__chk_io_ptr(a), *(volatile unsigned char __force  *)(a))
#define __raw_readw(a)        (__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
#define __raw_readl(a)        (__chk_io_ptr(a), *(volatile unsigned int __force   *)(a))

二、 在linux应用程序中:  mmap

mmap的实例参考:Linux用户态控制GPIO--基于友善mini2440 http://www.cnblogs.com/cute/archive/2011/05/10/2042399.html

mmap的具体解释参考:Linux 下操作gpio http://www.cnblogs.com/lidabo/p/5319219.html

功能描述: 
mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。munmap执行相反的操作,删除特定地址区域的对象映射。
基 于文件的映射,在mmap和munmap执行过程的任何时刻,被映射文件的st_atime可能被更新。如果st_atime字段在前述的情况下没有得到 更新,首次对映射区的第一个页索引时会更新该字段的值。用PROT_WRITE 和 MAP_SHARED标志建立起来的文件映射,其st_ctime 和 st_mtime
在对映射区写入之后,但在msync()通过MS_SYNC 和 MS_ASYNC两个标志调用之前会被更新。

用法:  
#include <sys/mman.h>
void *mmap(void *start, size_t length, int prot, int flags,
  int fd, off_t offset);

int munmap(void *start, size_t length);

 

============================

gpio linux 实现模型 http://www.cnblogs.com/armlinux/archive/2010/12/30/2396865.html

 

转载于:https://www.cnblogs.com/mylinux/p/5639264.html

### GPIO 寄存器的功能与使用方法 #### 1. GPIO 寄存器概述 GPIO(General Purpose Input Output)寄存器用于配置微控制器中的通用输入输出引脚行为。这些寄存器允许开发者定义引脚的工作模式,例如输入、输出或其他特定功能[^1]。 #### 2. 主要寄存器及其作用 以下是 STM32 中常见的 GPIO 寄存器及其功能: - **MODER(Mode Register)**: MODER 寄存器决定了每个 GPIO 引脚的操作模式。每一位对应一个引脚,可以将其配置为输入模式或输出模式。具体来说,每两位表示一个引脚的模式设置。 - **ODR(Output Data Register)**: ODR 是端口输出数据寄存器,其低 16 位有效,每位控制一个 IO 口的状态。通过向该寄存器写入值,可以直接改变对应的 GPIO 输出状态[^3]。 - **BSRR(Bit Set/Reset Register)**: BSRR 提供了一种更高效的方式来单独置位或复位某个引脚的状态,而无需修改整个 ODR 的内容。它分为两个部分:高 16 位用于复位操作,低 16 位用于置位操作。 - **IDR(Input Data Register)**: IDR 用于读取当前 GPIO 引脚的输入状态。当引脚被配置为输入时,可以通过访问此寄存器获取外部信号电平。 - **AFRL 和 AFRH(Alternate Function Registers Low and High)**: 如果需要将某些 GPIO 引脚映射到其他外设功能,则需使用 AFRL 和 AFRH 来指定具体的复用功能编号[^2]。 #### 3. Linux操作 GPIO 寄存器的方式 在嵌入式 Linux 系统中,通常会利用 `mmap` 函数将设备内存映射到用户空间地址范围,从而实现对硬件寄存器的直接访问。这种方法能够显著提高效率并减少延迟[^4]。 下面是一个简单的 C 语言代码示例展示如何通过 mmap 访问 GPIO 寄存器: ```c #include <stdio.h> #include <sys/mman.h> #include <fcntl.h> #define GPIO_BASE_ADDR 0x40E08000 // 假定的 GPIO 基础地址 #define PAGE_SIZE 4096 // 页面大小 int main() { int fd; void *gpio_reg; fd = open("/dev/mem", O_RDWR | O_SYNC); if (fd == -1) { perror("Failed to open /dev/mem"); return -1; } gpio_reg = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO_BASE_ADDR & ~(PAGE_SIZE - 1)); if (gpio_reg == MAP_FAILED) { perror("Mapping failed"); close(fd); return -1; } *(volatile unsigned long *)(gpio_reg + (GPIO_BASE_ADDR & (PAGE_SIZE - 1))) |= (1 << 5); // 设置第5个引脚为高电平 munmap(gpio_reg, PAGE_SIZE); close(fd); return 0; } ``` #### 4. 总结 通过对上述寄存器的理解以及实际编程实践,开发人员可以根据项目需求灵活调整 GPIO 引脚的行为特性。无论是简单地切换高低电平还是复杂地绑定至特殊外围模块接口,都离不开合理运用这些基础组件.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值