加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

在用户空间(和内核空间)访问内存的绝对地址

发布时间:2020-12-15 06:24:00 所属栏目:百科 来源:网络整理
导读:问题: 开发板中配置,S3C2410+NAND FLASH+SDRAM; 其中,SDRAM的地址为0x3000 0000;另外,由于需要从NAND FLASH启动,在地址0x0000 0000处有一块SRAM作为辅助(stepping stone),大小是4K。 启动原理是,系统上电后,硬件会自动将NAND FLASH的前4k代码拷贝到

问题:

开发板中配置,S3C2410+NAND FLASH+SDRAM;
其中,SDRAM的地址为0x3000 0000;另外,由于需要从NAND FLASH启动,在地址0x0000 0000处有一块SRAM作为辅助(stepping stone),大小是4K。
启动原理是,系统上电后,硬件会自动将NAND FLASH的前4k代码拷贝到SRAM中,从SRAM中启动系统,系统启动后SRAM就不再用了。
现在的问题是,打算系统启动后,利用一下SRAM,但是不知道在linux下如何去访问SRAM。


解决:

想起 ioremap的功能,就从网络上查阅了些资料,很有收获。

1. 在内核空间访问

原来在linux下访问绝对地址时需要“地址映射”,就是需要把物理地址映射到虚拟地址。不过具体的原理我还不清楚,参考了一篇博文
http://blog.csdn.net/do2jiang/article/details/5450839
主要是用ioremap函数。

/*好像需要下面的头文件*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <asm/io.h> /* for virt_to_phys */
#include <linux/slab.h> /* for kmalloc and kfree */

void* v_addr = ioremap(0,1024);

第一个参数是要访问的物理地址;

第二个参数是要访问区域的大小;

函数返回映射后区域的起始虚拟地址;

然后就可以直接对v_addr进行读写了。

注意,这里只是将物理空间映射到内核空间,在用户空间还是不能访问的。


2. 在用户空间访问(1)

使用ioremap映射到内核空间后,可以使用remap_pfn_range将内核空间映射到用户空间,应该就可以访问了,比较复杂,没有尝试……

可以参考:? http://www.scs.ch/~frey/linux/memorymap.html?

On 2.6 things got even simpler. The remap_pfn_range function sets the correct flags in the vm_area. remap_pfn_range can be called for a set of physically contiguous pages. Do map the pages you therefore have to:

??? * Implement a mmap method for your driver
??? * Set the reserved bit on the pages you are mapping into user space
??? * Call remap_pfn_range to map your buffer into user space

Example:

?? ?if (remap_pfn_range(vma,
?? ??? ??? ???? vma->vm_start,
?? ??? ??? ???? virt_to_phys((void *)kmalloc_area) >> PAGE_SHIFT,
?? ??? ??? ???? size,
?? ??? ??? ???? vma->vm_page_prot)) < 0) {
?? ??? ?printk("remap_pfn_range failedn");
?? ??? ?return -EIO;
?? ?}

The arguments of the remap_pfn_range function are:

??? * vma: vm_area_struct has passed to the mmap method
??? * vma->vm_start: start of mapping user address space
??? * virt_to_phys((void *)kmalloc_area) >> PAGE_SHIFT: page frame number of first page
??? * size: length of mapping in bytes
??? * vma->>vm_page_prot: protection bits,here passed along received from application

3. 在用户空间访问(2)

查资料时,在评论里发现了下面的方法。

参考:? http://hi.baidu.com/zengzhaonong/blog/item/369f25295664a1fc98250a70.html?

    int fd;
    void *start;

    fd = open("/dev/mem",O_RDONLY);
    start = mmap(NULL,10,PROT_READ,MAP_PRIVATE,fd,0);

用/dev/mem和mmap,在用户空间访问寄存器用,直接指定访问的物理地址就好了。

这个方法比上面的方法节省了写驱动。

另外,关于函数mmap,

mmap方法是file_operations结构的一部分,用户空间系统调用原型为:

mmap (cadaar_t addr,size_t len,int prot,int flags,int fd,off_t offset)

但是文件操作声明如下:

int (*mmap) (struct file *filp,struct vm_area_struct*vma)

注:vm_area_struct 是描述进程地址空间的基本管理单元。vma中就需要包含用于访问设备虚拟地址的信息,因此大量工作是在内核中完成的。



快乐在于解决一个又一个的问题~

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读