使用mmap在用户层访问底层硬件

使用mmap在用户层访问底层硬件,基本原理是通过mmap将底层一块内存映射到用户,在LCD驱动里面应用比较多。

先看Makefile

TARGET  = mmap_tool_simple
ROOTDIR = /home/flinn/bin/rootfs

CROSS_COMPILE   := /home/flinn/tools/4.9.4/bin/arm-linux-gnueabi-
CC              := $(CROSS_COMPILE)gcc
LD              := $(CROSS_COMPILE)ld


CFLAGS          := -Wall -O2

OBJS := $(TARGET).o


$(TARGET): $(OBJS)
        ${CC}  $(CFLAGS) -o $@ $^


%.o:%.c
        ${CC}  $(CFLAGS) -c -o $@ $<

install:
        sudo cp $(TARGET) $(ROOTDIR)

clean:
        rm -f $(TARGET) *.o $(OBJS)

源码mmap_tool_simple.c

/*
* mmap_toos.c
*
* get register of hardware from user-space
*
*/

#include 
#include 

#include 
#include 


#include 
#include 

#include 
#include 

#define DEBUG

#ifdef DEBUG
#define pr_print(...)	printf(##__VA_ARGS__)
#else
#define pr_print(...)	
#endif


#define reg32_read(addr)		(*((volatile unsigned int *)((unsigned int)addr)))
#define reg32_write(addr, val)	(*((volatile unsigned int *)((unsigned int)addr)) = (unsigned int)val)


static int rw = 0;   /* 0: read, 1:write */

#define RW_LFAG_READ		0
#define RW_FLAG_WRITE		1

struct _cmd
{
	unsigned int baseaddr;
	unsigned int length;        /* for read length */
	unsigned int value;         /* for write */
};

static struct _cmd cmd;



static void usage(void)
{
	fprintf(stderr, 
		"usage : mmap_tools [cmd] [args] ... \n\n"
		"options :\n"
		" -r,  --read              open device\n"
		" -w,  --write             close device\n"
		" -h,  --help              show usage information.\n"
		"examples :\n"
		" mmap_tools -r [baseaddr] [len]\n"
		" mmap_tools -w [baseaddr] [value]\n"
	);
}

static int drv_parse_cmds(int argc, char **argv)
{
	int i;
	char *opt;

	if(4 != argc)
		return -1;
		
	if(!strcmp(argv[1], "-r")){
		rw = RW_LFAG_READ;
		
		cmd.baseaddr = strtoll(argv[2], &opt, 16);
		cmd.length = strtol(argv[3], &opt, 16);
	}
	else if(!strcmp(argv[1], "-w"))	{
		rw = RW_FLAG_WRITE;
		
		cmd.baseaddr = strtoll(argv[2], &opt, 16);
		cmd.value = strtol(argv[3], &opt, 16);
	}
	else
	{
		return -1;
	}
	
	return 0;
}



int main(int argc,  char *argv[])
{
	int ret = 0 , i;
	int fd = -1;

	unsigned int *map_base;
	
	unsigned int addr;
	unsigned int offset = 0;

	ret = drv_parse_cmds(argc, argv);
	if(ret != 0){
		usage();
		return -1;
	}

	fd = open("/dev/mem", O_RDWR);
	if(fd < 0){
		printf("open %s fail.\n", "/dev/mem");
		return -1;
	}
	
	addr = cmd.baseaddr & ~(getpagesize() - 1);
	offset = (cmd.baseaddr - addr) & 0xfffffffc;   /* align 4-bytes */

	unsigned int length = 1;

	
	if(RW_LFAG_READ == rw){
		length = cmd.length;
		
		map_base = (unsigned int * )mmap(NULL, length * 4, PROT_READ, MAP_SHARED, fd, addr);

		for(i = 0; i < length; i++)
		{
			printf("addr : %08x value : %08x\n", addr + offset + i*4, reg32_read(map_base + i*4));
		}		
	}
	else if(RW_FLAG_WRITE == rw){
		unsigned int value = cmd.value;

		map_base = (unsigned int * )mmap(NULL, length * 4, PROT_WRITE, MAP_SHARED, fd, addr);

		reg32_write(map_base + offset , value);
	}
	else
	{
	}	

	munmap(map_base, length * 4);

	close(fd);
	
	return 0;
}

编译

make
make install

使用

使用mmap在用户层访问底层硬件_第1张图片

你可能感兴趣的:(嵌入式linux设备驱动)