使用ioremap实现的简单驱动

这篇博客介绍了如何在Linux驱动程序中使用ioremap函数来映射硬件寄存器,通过设置GPMCON和GPMDAT寄存器的值进行配置。在模块初始化和退出时,进行了相应的寄存器操作,并演示了iounmap的使用,以释放内存资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
void *ioremap(unsigned long phys_addr, unsigned long size)
入口: phys_addr:要映射的起始的IO地址;
size:要映射的空间的大小;
flags:要映射的IO空间的和权限有关的标志;
phys_addr:是要映射的物理地址,
size:是要映射的长度,
S3C2410的long是32位而非64位。
功能:将一个IO 地址空间映射到内核的虚拟地址空间上去,便于访问;
实现:对要映射的IO 地址空间进行判断,低PCI/ISA地址不需要重新映射,也不允许用户将IO地址空间映射到正在使用的RAM中,最后申请一个 vm_area_struct结构,调用remap_area_pages填写 页表,若填写过程不成功则释放申请的vm_area_struct空间;
ioremap 依靠 __ioremap实现,它只是在__ioremap中以第三个参数为0调用来实现.
ioremap是 内核提供的用来映射外设寄存器到主存的函数,我们要映射的地址已经从pci_dev中读了出来(上一步),这样就水到渠成的成功映射了而不会和其他地址有冲突。映射完了有什么效果呢,我举个例子,比如某个网卡有100 个寄存器,他们都是连在一块的,位置是固定的,假如每个寄存器占4个 字节,那么一共400个字节的空间被映射到内存成功后,ioaddr就是这 段地址的开头(注意ioaddr是 虚拟地址,而mmio_start是 物理地址,它是BIOS得到的,肯定是物理地址,而保护模式下CPU不认物理地址,只认虚拟地址),ioaddr+0就是第一个寄存器的地址,ioaddr+4就是第二个寄存器地址(每个寄存器占4个字节),以此类推,我们就能够在内存中访问到所有的寄存器进而操控他们了。

举个简单操作寄存器的例子
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <linux/init.h>  
  2. #include <linux/module.h>  
  3. #include <linux/io.h>  
  4.   
  5. #if 0  
  6. #define GPMCON     *(volatile unsigned long *)0x7F008820  
  7. #define GPMDAT     *(volatile unsigned long *)0x7F008824  
  8. #endif  
  9.   
  10. #define GPMCON     0x7F008820  
  11. #define GPMDAT     0x7F008824  
  12.   
  13. static volatile unsigned long *conf, *data;  
  14.   
  15. static int __init test_init(void)  
  16. {  
  17. #if 0  
  18.     GPMCON = 0x1111;  
  19.     GPMDAT = 0x0;  
  20. #endif  
  21.   
  22.     conf = ioremap(GPMCON, 4);  
  23.     data = ioremap(GPMDAT, 4);  
  24.   
  25.     *conf = 0x1111;  
  26.     *data = 0x0;  
  27.   
  28.     return 0;  
  29. }  
  30.   
  31. static void __exit test_exit(void)  
  32. {  
  33. #if 0  
  34.     GPMDAT = 0xF;  
  35. #endif  
  36.   
  37.     *data = 0xf;  
  38.   
  39.     iounmap(conf);  
  40.     iounmap(data);  
  41. }  
  42.   
  43. module_init(test_init);  
  44. module_exit(test_exit);  
  45.   
  46. MODULE_LICENSE("GPL");  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值