用户态下直接操作GPIO/寄存器(linux应用篇)

CPU:F1C100S
目标系统:linux5.2**

实验目的: 点亮LED灯。

PE4---LED1
PE5---LED2
PE6---LED3

实现方法: 写一个c程序通过mmap方法直接来操作寄存器。

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define GPIO_REG_BASE   0x01C20800      //GPIO物理基地址 (小页4kb)
#define MAP_SIZE        0x400 //MMU页大小
#define GPIO_BASE_OFFSET (GPIO_REG_BASE & 0X00000FFF) //GPIO基地址偏移计算
#define GPIO_PAGE_OFFSET (GPIO_REG_BASE & 0XFFFFF000) //获得页偏移

#define rPE_CFG0 0X90  //PE_CFG0寄存器地址偏移
#define rPE_DAT 0XA0    //PE_DAT寄存器地址偏移
#define rPE_PULL0 0XAC  //PE_PULL0寄存器地址偏移

int GPIOE_456_ON(unsigned char *MAP_BASE);//点亮PE4,PE5,PE6 这3盏LED
int  GPIOE_456_OFF(unsigned char *MAP_BASE);//关闭PE4,PE5,PE6 这3盏LED

int main(int argc, char **argv)
{
 static int dev_fd;
 unsigned char *map_base;
/*参数验证*/
	if(argc!=2 || (strcmp(argv[1],"on") && strcmp(argv[1],"off"))){
   	 printf("argv_error!please input 'on' or 'off'!\n");
 	   exit (0);
	}

    dev_fd = open("/dev/mem", O_RDWR );
    if (dev_fd < 0){
        printf("open(/dev/mem) failed.\n");
        return 0;
    }

map_base = (unsigned char *)mmap(NULL, 0x400,PROT_READ | PROT_WRITE, MAP_SHARED,dev_fd, GPIO_PAGE_OFFSET); //把物理地址映射到虚拟地址
if(*map_base)  printf("mmap_fail!\n"); //是否映射成功

if(!strcmp(argv[1],"on")) GPIOE_456_ON(map_base); //点亮PE4,PE5,PE6 这3盏LED
if(!strcmp(argv[1],"off")) GPIOE_456_OFF(map_base);//关闭PE4,PE5,PE6 这3盏LED
  //usleep(1000000);
    if(dev_fd) close(dev_fd);
    munmap(map_base,MAP_SIZE);//解除映射关系
    return 0;
}


//GPIOE_456_ON
int  GPIOE_456_ON(unsigned char *MAP_BASE)
{
unsigned int PE_CFG0,PE_DAT;
PE_CFG0=*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_CFG0);
PE_DAT=*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_DAT);
*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_CFG0)=((PE_CFG0 & 0XF000FFFF)|0X01110000);
*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_DAT)=((PE_DAT & 0XFFFFFF8F)|0X00000070);
}
//GPIOE_456_OFF
int  GPIOE_456_OFF(unsigned char *MAP_BASE)
{
unsigned int PE_CFG0,PE_DAT;
PE_CFG0=*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_CFG0);
PE_DAT=*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_DAT);
*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_CFG0)=((PE_CFG0 & 0XF000FFFF)|0X01110000);
*(volatile unsigned int *)(MAP_BASE+GPIO_BASE_OFFSET+rPE_DAT)=((PE_DAT & 0XFFFFFF8F));
}



编译代码并测试

# ./led2 on			/*点亮所有LED灯*/
# ./led2 off		/*开闭所有LED灯*/

你可能感兴趣的:(❏【F1C100S学习】,❏【LINUX应用开发】,mmap函数,点亮LED,F1C100S,linux,用户态直接操作寄存器)