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


对于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;
}

测试源码获取:点我

欢迎扫码关注我的微信公众号
漫长当下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值