文章目录
- 理论知识
- 1、使能了MMU以后有什么好处呢?
- 2、MMU非常复杂,那么我们如何完成物理地址到虚拟地址的转换呢?
- 3、如何查看哪些物理地址被映射过了呢?
- 实例(RK3568)
理论知识
在Linux上面如果想要操作硬件,需要先把物理地址转换成虚拟地址。因为Linux使能了MMU,所以我们在Linux上不能直接操作物理地址。
1、使能了MMU以后有什么好处呢?
- 让虚拟地址成立可能。
- 可以让系统更加安全,因为有了MMU,我们上层应用看到的内存都是虚拟内存,我们的应用就不能直接访问硬件,所以这样就保证了系统安全。
2、MMU非常复杂,那么我们如何完成物理地址到虚拟地址的转换呢?
内核给我们提供了相关的函数。
函数 | 描述 |
---|
ioremap | 把物理地址转换成虚拟地址 |
iounmap | 释放掉ioremap映射的地址 |
函数声明的地方:include/asm-generic/io.h
static inline void __iomem *ioremap(phys_addr_t offset, size_t size);
参数:
phys_addr_t offset
:映射物理地址的起始地址。size_t size
:要映射多大的内存空间。- 返回值:
static inline void iounmap(void __iomem *addr);
参数:
注意:物理地址只能被映射一次,多次映射会失败。
3、如何查看哪些物理地址被映射过了呢?
可以使用命令cat /proc/iomem
来查看。
实例(RK3568)
led.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/kernel.h>
#define GPIO_DR 0xfdd60000
unsigned int *vir_gpio_dr;
ssize_t misc_read (struct file *file, char __user *ubuf, size_t size, loff_t *loff_t)
{
printk("misc_read\n ");
return 0;
}
ssize_t misc_write (struct file *file, const char __user *ubuf, size_t size, loff_t *loff_t)
{
char kbuf[64] = {0};
if(copy_from_user(kbuf,ubuf,size)!= 0)
{
printk("copy_from_user error \n ");
return -1;
}
printk("kbuf is %d\n ",kbuf[0]);
if(kbuf[0]==1)
{
*vir_gpio_dr = 0x80008000;
}
else if(kbuf[0]==0)
*vir_gpio_dr = 0x80000000;
return 0;
}
int misc_release(struct inode *inode,struct file *file){
printk("hello misc_relaease bye bye \n ");
return 0;
}
int misc_open(struct inode *inode,struct file *file){
printk("hello misc_open\n ");
return 0;
}
struct file_operations misc_fops={
.owner = THIS_MODULE,
.open = misc_open,
.release = misc_release,
.read = misc_read,
.write = misc_write,
};
struct miscdevice misc_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "hello_misc",
.fops = &misc_fops,
};
static int misc_init(void)
{
int ret;
ret = misc_register(&misc_dev);
if(ret<0)
{
printk("misc registe is error \n");
}
printk("misc registe is succeed \n");
vir_gpio_dr = ioremap(GPIO_DR,4);
if(vir_gpio_dr == NULL)
{
printk("GPIO_DR ioremap is error \n");
return EBUSY;
}
printk("GPIO_DR ioremap is ok \n");
return 0;
}
static void misc_exit(void){
misc_deregister(&misc_dev);
iounmap(vir_gpio_dr);
printk(" misc gooodbye! \n");
}
module_init(misc_init);
module_exit(misc_exit);
MODULE_LICENSE("GPL");
app.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
int fd;
char buf[64] = {0};
fd = open("/dev/hello_misc",O_RDWR);
if(fd < 0)
{
perror("open error \n");
return fd;
}
buf[0] = atoi(argv[1]);
write(fd,buf,sizeof(buf));
printf("buf is %d\n",buf[0]);
close(fd);
return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)