linux 应用程序直接读写寄存器或物理内存

1.程序说明:

调试驱动程序时,经常遇到候需要查看或设置寄存器的情况,但是直接更改内核代码又不方便。

这里提供一个应用程序源码能在应用层访问底层寄存器。(网上找到的,进行过更改)。

这里只提供4字节数据的访问,如果需要其他字节宽度则需要更改代码。

line40 增加了O_DSYNC标志,防止cache导致数据写入不及时。

2.应用程序源码

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <time.h>
 4 #include <unistd.h>
 5 #include <fcntl.h>
 6 #include <unistd.h>
 7 #include <stdint.h>
 8 #include <sys/mman.h>
 9 #include <errno.h>
10 
11 static int dev_fd;
12 int main(int argc, char **argv)
13 {
14     uint32_t addr, value, map_size,base;
15     void *align_addr;
16     int flag = 0;
17     int i;
18     unsigned char *map_base;
19 
20     if (argc != 5) {
21         printf("usage:   m_reg r base address readcount\n");
22         printf("example: m_reg r 0x50008000 20 1\n");
23         printf("usage:   m_reg w base address writevalue\n");
24         printf("example: m_reg w 0x50008000 20 0xffffffff\n");
25         return -1;
26     }
27 
28     if (argv[1][0] == 'r') {
29         flag = 0;
30         value = strtol(argv[4], NULL, 10);
31     }
32     else {
33         flag = 1;
34         value = strtol(argv[4], NULL, 16);
35     }
36 
37     base = strtol(argv[2], NULL, 16);
38     addr = strtol(argv[3], NULL, 16);
39 
40     dev_fd = open("/dev/mem", O_RDWR | O_NDELAY | O_DSYNC);
41 
42     if (dev_fd < 0)
43     {
44         printf("open(/dev/mem) failed.");
45         return 0;
46     }
47 
48     addr &= ~0x3;
49     align_addr = addr & ~0xff;
50 
51     map_size = addr + 0x100;
52     printf("map base:0x%x size:0x%x\n",base,map_size);
53     map_base = (unsigned int * )mmap(NULL, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, base);
54     if(map_base == -1)
55     {
56         printf("map err %d\n",errno);
57         perror("errno:");
58         return -1;
59     }
60     
61     if (flag == 0) {
62 
63         for (i = 0; i < value; i++) {
64             if (i % 4 == 0) {
65                 printf("\n");
66                 printf("0x%08x\t", addr+i*4);
67             }
68             printf("%08x ", *(volatile unsigned int *)(map_base+addr+i*4));
69         }
70         printf("\n");
71 
72     }
73     else {
74         printf("0x%08x\t value:0x%x", addr,value);
75         *(volatile unsigned int *)(map_base + addr) = value;
76     }
77     printf("\n");
78 
79     if(dev_fd)
80         close(dev_fd);
81 
82     munmap((unsigned int *)map_base, map_size);
83 
84     return 0;
85 }

 

3. 内核设备文件实现

内核源码位置:/drivers/char/mem.c

 /dev/mem设备文件mmap函数实现:

static int mmap_mem(struct file *file, struct vm_area_struct *vma)
{
	size_t size = vma->vm_end - vma->vm_start;
	phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT;

	/* It's illegal to wrap around the end of the physical address space. */
	if (offset + (phys_addr_t)size - 1 < offset)
		return -EINVAL;

	if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
		return -EINVAL;

	if (!private_mapping_ok(vma))
		return -ENOSYS;

	if (!range_is_allowed(vma->vm_pgoff, size))
		return -EPERM;

	if (!phys_mem_access_prot_allowed(file, vma->vm_pgoff, size,
						&vma->vm_page_prot))
		return -EINVAL;

	vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
						 size,
						 vma->vm_page_prot);

	vma->vm_ops = &mmap_mem_ops;

	/* Remap-pfn-range will mark the range VM_IO */
	if (remap_pfn_range(vma,
			    vma->vm_start,
			    vma->vm_pgoff,
			    size,
			    vma->vm_page_prot)) {
		return -EAGAIN;
	}
	return 0;
}

 phys_mem_access_prot函数获得映射内存访问权限

static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
				     unsigned long size, pgprot_t vma_prot)
{
#ifdef pgprot_noncached
	phys_addr_t offset = pfn << PAGE_SHIFT;

	if (uncached_access(file, offset))
		return pgprot_noncached(vma_prot);
#endif
	return vma_prot;
}

O_DSYNC标志将会使用不带cache的映射方式,该标志在打开设备文件时指定。

static int uncached_access(struct file *file, phys_addr_t addr)
{
	/*
	 * Accessing memory above the top the kernel knows about or through a
	 * file pointer
	 * that was marked O_DSYNC will be done non-cached.
	 */
	if (file->f_flags & O_DSYNC)
		return 1;
	return addr >= __pa(high_memory);
}

  

 

posted @ 2020-02-08 18:18  反光  阅读(1948)  评论(0编辑  收藏  举报