1.1 Android 驱动开发-内核驱动

本文介绍如何通过混杂设备实现对IO口的操作来控制LED灯的开关。具体包括在/dev/目录下创建设备节点vled,并使用ioctl()函数控制GPIO口电平,给出驱动程序的实现代码。

目标:利用混杂设备实现对IO口的操作,进而开启或关闭相连的LED

-用混杂设备的原因是因为方便实现,不要陷入太复杂的细节中,把握整个框架才是最重要的

-在 /dev/ 目录下建立设备节点: vled(也就是驱动模块名)

-可以打开关闭节点,利用 ioctl() 函数控制 GPIO 口的电平

代码示例

1. 新建驱动目录 ~/kernel/drivers/vled,分别增加以下文件:
/*
vled.c
*/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "vled.h"



#define     GRF_BASE_ADDR               0x20008000

#define     GPIO0_BASE_ADDR             0x20034000
#define     GPIO1_BASE_ADDR             0x2003E000
#define     GPIO6_BASE_ADDR             0x2000A000

#define     GPIO_SWPORT_DR              0x0000
#define     GPIO_SWPORT_DDR             0x0004
#define     GPIO_EXT_PORT               0x0050


void * pvir = NULL;


int vled_open(struct inode * inode, struct file * file)
{
	return 0;
}
int vled_close(struct inode * inode, struct file * file)
{
	return 0;
}
long vled_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{

	switch (cmd)
	{
		case IOC_VLED_SET:
            iowrite32(ioread32(pvir + GPIO_SWPORT_DDR) | (0x01 << 8), pvir + GPIO_SWPORT_DDR);
            iowrite32(ioread32(pvir + GPIO_SWPORT_DR) | (0x01 << 8), pvir + GPIO_SWPORT_DR);
			break;
		case IOC_VLED_CLR:
            iowrite32(ioread32(pvir + GPIO_SWPORT_DDR) | (0x01 << 8), pvir + GPIO_SWPORT_DDR);
            iowrite32(ioread32(pvir + GPIO_SWPORT_DR) & (~(0x01 << 8)), pvir + GPIO_SWPORT_DR);
			break;			
		default:
			printk("vled drv:invalid nc decoder ioctl cmd[0x%02X]\n", cmd);
			break;
	}

	return 0;
}


static struct file_operations vled_fops = {
	.owner      = THIS_MODULE,
    .unlocked_ioctl	= vled_ioctl,
	.open       = vled_open,
	.release    = vled_close
};
static struct miscdevice vled_dev = {
	.minor		= MISC_DYNAMIC_MINOR,
	.name		= "vled",
	.fops  		= &vled_fops,
};
static int __init vled_module_init(void)
{
	int ret = 0;

	ret = misc_register(&vled_dev);
   	if (ret)
	{
		printk("ERROR: could not register vled devices\n");
	}

    // P6.B.0 = 0;
    printk(KERN_ALERT "Set P6.B.0 = 0\n");
    pvir = ioremap(GPIO6_BASE_ADDR, 0x64);
    if(NULL == pvir) {
        printk(KERN_ALERT "ioremap error!\n");
        return -1;
    }
    printk(KERN_ALERT "Virrual addr: 0x%x\n", (unsigned int)pvir);


    iowrite32(ioread32(pvir + GPIO_SWPORT_DDR) | (0x01 << 8), pvir + GPIO_SWPORT_DDR);
    iowrite32(ioread32(pvir + GPIO_SWPORT_DR) & (~(0x01 << 8)), pvir + GPIO_SWPORT_DR);

    printk(KERN_ALERT "DDR: 0x%x, DR: 0x%x\n", ioread32(pvir + GPIO_SWPORT_DDR), ioread32(pvir + GPIO_SWPORT_DR));
    printk(KERN_ALERT "vled init ok!\n");
   	return ret;
}
static void __exit vled_module_exit(void)
{
    iounmap(pvir);
    misc_deregister(&vled_dev);
}

module_init(vled_module_init);
module_exit(vled_module_exit);
MODULE_LICENSE("GPL");

/*
vled.h
*/
#ifndef		VLED_H
#define		VLED_H

#define		IOC_VLED_SET                    0
#define		IOC_VLED_CLR                    1

#endif
2. 在同样目录下新增 K

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值