文章目录
常用接口
request_mem_region函数
release_mem_region函数
ioremap函数
iounmap函数
在驱动中的使用
点击下方阅读原文可访问文中超链接
对于linux中的驱动来说,在操作硬件这个部分其实和在单片机中操作硬件几乎是一样的,不同的只是在linux中使用的是虚拟地址(如果开启了MMU),而在单片机中都是直接操作物理地址;在linux中驱动有一套比较规范的流程而已。
MMU是一个硬件,主要功能是实现虚拟地址到物理地址之间的转换和内存保护(比如权限管控、进程隔离)。
还是像学单片机一样,前面铺垫一大堆,但任然从点亮第一颗led灯开始。
常用接口
位于头文件:include\linux\ioport.h
request_mem_region函数
此函数用以在映射物理地址之前向内核发出申请,这样可以防止这个资源在其它地方再次被占用而造成访问冲突。
#define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0)
release_mem_region函数
此函数用以释放使用request_mem_region申请的资源。
#define release_mem_region(start,n) __release_region(&iomem_resource, (start), (n))
ioremap函数
位于头文件:include\asm-generic\io.h
此函数用以映射一段物理地址到虚拟地址。
void __iomem *ioremap(phys_addr_t addr, size_t size)
iounmap函数
此函数用以取消ioremap所做的映射。
void iounmap(volatile void __iomem *addr)
在驱动中的使用
为了测试简便,所以将硬件操作放在了open
和release
接口里面,在应用程序中open
和close
函数之间加一段延时就可以看到对应的led灯亮一段时间后熄灭。
typedef struct {
unsigned int con;
unsigned int dat;
unsigned int pud;
unsigned int drv;
unsigned int conpdn;
unsigned int pudpdn;
}gpio_regTypeDef;
#define GPJ0_BASE 0xe0200240
void __iomem *io_va;
struct resource *data_req;
static int test_open (struct inode *inode, struct file *file)
{
int ret = 0;
unsigned int tmp;
data_req = request_mem_region(GPJ0_BASE,sizeof(gpio_regTypeDef),"gpj0_reg");
if(!data_req)
{
ret = -EIO;
return ret;
}
io_va = ioremap(GPJ0_BASE,sizeof(gpio_regTypeDef));
if(!io_va)
{
ret = -EINVAL;
goto failed_ioremap;
}
/*配置引脚gpj0_3为输出*/
tmp = readl(&((gpio_regTypeDef *)io_va)->con);
tmp |= (0x1 << 3);
writel(tmp,&((gpio_regTypeDef *)io_va)->con);
/*配置gpj0_3输出低电平*/
tmp = readl(&((gpio_regTypeDef *)io_va)->dat);
tmp &= ~(0x1 << 3);
writel(tmp,&((gpio_regTypeDef *)io_va)->dat);
return ret;
failed_ioremap:
release_mem_region(GPJ0_BASE,sizeof(gpio_regTypeDef));
return ret;
}
static int test_close (struct inode *inode, struct file *file)
{
unsigned int tmp;
/*配置gpj0_3输出低电平*/
tmp = readl(&((gpio_regTypeDef *)io_va)->dat);
tmp |= (0x1 << 3);
writel(tmp,&((gpio_regTypeDef *)io_va)->dat);
iounmap(io_va);
release_mem_region(GPJ0_BASE,sizeof(gpio_regTypeDef));
return 0;
}
测试源码获取:点我