虫虫首页|资源下载|资源专辑|精品软件
登录|注册

您现在的位置是:首页 > 技术阅读 >  linux驱动开发(4、操作硬件)

linux驱动开发(4、操作硬件)

时间:2024-06-01

文章目录

  • 常用接口

    • 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)

在驱动中的使用

为了测试简便,所以将硬件操作放在了openrelease接口里面,在应用程序中openclose函数之间加一段延时就可以看到对应的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;
}

测试源码获取:点我