混杂设备实现led点灯
一、为了简单方便操作,linux提供了混杂设备驱动编程这一方法,混杂设备驱动程序是指那些简单的字符驱动程序,它们拥有一些相同的特性,内核将这些相同的特性抽象至一个API(drivers/char/misc.c)中。由此可见混杂设备在某种程度上来说也是属于字符驱动的。这能够大大的简化我们字符驱动的编程工作量。
首先来看下我们的字符驱动程序会做什么事情:
1、通过alloc_chrdev_region来注册主次设备号
2、使用device_creat来创建设备结点,当然,如果实验的时候你是可以手动创建设备结点
3、使用cdev_init和cdev_add函数来将自身注册为字符驱动
但是我们使用的混杂设备的功能又是什么呢,具有什么优势呢?
上面三个步骤如果使用混杂设备来做的话,那么将会变得相当简单
1、声明结构体
static struct miscdevice led_dev = {
.minor = MINOR_NUM,
.name = "s3c6410_led", //这个名字含义:挂载驱动后将会自动在/dev目录下面生成s3c6410_led设备文件,这归功于混杂设备。
.fops = &led_fops,
};
直接使用混杂设备注册函数
misc_deregister(&led_dev);
至于混杂设备注册函数里面做了什么,我想大家都能够猜到,必然也是做了上面的事情,只不过我们这里偷了个懒,使用linux内核给我们提供的api罢了。
还是将注册代码贴上来
int misc_register(struct miscdevice * misc)
{
struct miscdevice *c;
dev_t dev;
int err = 0;
INIT_LIST_HEAD(&misc->list);
mutex_lock(&misc_mtx);
list_for_each_entry(c, &misc_list, list) {
if (c->minor == misc->minor) {
mutex_unlock(&misc_mtx);
return -EBUSY;
}
}
if (misc->minor == MISC_DYNAMIC_MINOR) {
int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);
if (i >= DYNAMIC_MINORS) {
mutex_unlock(&misc_mtx);
return -EBUSY;
}
misc->minor = DYNAMIC_MINORS - i - 1;
set_bit(i, misc_minors);
}
dev = MKDEV(MISC_MAJOR, misc->minor);
misc->this_device = device_create(misc_class, misc->parent, dev,
misc, "%s", misc->name);
if (IS_ERR(misc->this_device)) {
int i = DYNAMIC_MINORS - misc->minor - 1;
if (i < DYNAMIC_MINORS && i >= 0)
clear_bit(i, misc_minors);
err = PTR_ERR(misc->this_device);
goto out;
}
/*
* Add it to the front, so that later devices can "override"
* earlier defaults
*/
list_add(&misc->list, &misc_list);
out:
mutex_unlock(&misc_mtx);
return err;
}
上面可以知道混杂设备都使用同一个主设备号10。
二、在接下来就将之前的led点灯驱动变身一下
1、先看驱动代码
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <linux/ioport.h>
#include <linux/miscdevice.h>
#define GPIOM_BASE 0x7F008820
#define MINOR_NUM 1
unsigned long VA;
unsigned long gpmdat,gpmpud,gpmcon;
/* open函数完成的功能:初始化gpio为输出方向 */
int s3c6410_led_open(struct inode *inodep, struct file *filp)
{
unsigned tmp;
tmp = ioread32(gpmcon);
printk("tmp = %x ... \n",tmp);
tmp &= (~0xFFFF);
tmp |= (0x1111);
iowrite32(tmp,gpmcon);
printk("s3c6410_led_open ... \n");
return 0;
}
long s3c6410_led_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
{
unsigned tmp;
switch(cmd){
case 0:
tmp = ioread32(gpmdat);
tmp &= 0x10;
iowrite32(tmp,gpmdat);
break;
case 1:
tmp = ioread32(gpmdat);
tmp |= 0x1f;
iowrite32(tmp,gpmdat);
break;
default:
break;
}
printk("s3c6410_led_ioctl ... \n");
return 0;
}
int s3c6410_led_release(struct inode *inodep,struct file *filp)
{
printk("s3c6410_led_release ... \n");
return 0;
}
static struct file_operations led_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = s3c6410_led_ioctl,
.open = s3c6410_led_open,
.release = s3c6410_led_release,
};
static struct miscdevice led_dev = {
.minor = MINOR_NUM,
.name = "s3c6410_led", //这个名字含义:挂载驱动后将会自动在/dev目录下面生成s3c6410_led设备文件,这归功于混杂设备。
.fops = &led_fops,
};
static int __init led_init(void)
{
int ret = 0;
VA = (unsigned long)ioremap(GPIOM_BASE,0x0c);
gpmcon = VA + 0x00;
gpmdat = VA + 0x04;
gpmpud = VA + 0x08;
ret = misc_register(&led_dev);
printk("led_init ...\n");
return ret;
}
static void __exit led_exit(void)
{
misc_deregister(&led_dev);
printk("led_exit ...\n");
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
其实代码和led1的版本没什么本质的区别,底层操作还是一样的,只是运用了一些小手段使之能够和应用程序打交道ioctl
这里我没有使用魔数的方法来定义CMD。
misc_register和misc_deregister是成对出现的
2、再看测试程序
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
int main(int argc,char **argv)
{
int ret = 0;
int i = 0;
int fd = open("/dev/s3c6410_led",2,777);
if(fd < 0)
{
printf("open led dev failed \n");
}
printf("open led dev success ! \n");
for(i = 0; i < 10; i ++)
{
ioctl(fd,0);
sleep(1);
ioctl(fd,1);
sleep(1);
}
return ret;
}
简单的led闪烁灯就实现了。
分享到:
相关推荐
ok6410开发板 led驱动简要介绍,
linux驱动OK6410系列之03---LED字符
参考ok6410自带的驱动程序,调试成功了第一个linux程序。具体解释参考:http://blog.sina.com.cn/u/6078347489
打印机驱动 LQ-635K打印机驱动 LQ-635K打印机驱动 LQ-635K打印机驱动 LQ-635K打印机驱动 LQ-635K打印机驱动 LQ-635K打印机驱动 LQ-635K打印机驱动 LQ-635K打印机驱动 LQ-635K打印机驱动 LQ-635K打印机驱动 LQ-635K...
ST-LINK V2 驱动程序ST-LINK V2 驱动程序ST-LINK V2 驱动程序ST-LINK V2 驱动程序ST-LINK V2 驱动程序ST-LINK V2 驱动程序ST-LINK V2 驱动程序ST-LINK V2 驱动程序ST-LINK V2 驱动程序ST-LINK V2 驱动程序ST-LINK V2...
嵌入式的学习 linux编程-驱动调用-QT编程.
无痕驱动读写-破虚拟读写无痕驱动读写-破虚拟读写无痕驱动读写-破虚拟读写无痕驱动读写-破虚拟读写无痕驱动读写-破虚拟读写无痕驱动读写-破虚拟读写无痕驱动读写-破虚拟读写无痕驱动读写-破虚拟读写无痕驱动读写-破...
打印机驱动 LQ-630KII打印机驱动 LQ-630KII打印机驱动 LQ-630KII打印机驱动 LQ-630KII打印机驱动 LQ-630KII打印机驱动 LQ-630KII打印机驱动 LQ-630KII打印机驱动 LQ-630KII打印机驱动 LQ-630KII打印机驱动 LQ-630KII...
plc编程电缆驱动本人花几百元买的plc编程电缆并附有驱动程序,注意下载时电缆型号USB-SC-09绝对正版
led驱动 OK6410 嵌入式 linux
打印机驱动 FP-550K_W10打印机驱动 FP-550K_W10打印机驱动 FP-550K_W10打印机驱动 FP-550K_W10打印机驱动 FP-550K_W10打印机驱动 FP-550K_W10打印机驱动 FP-550K_W10打印机驱动 FP-550K_W10打印机驱动 FP-550K_W10...
西门子PLC S7-200 USB-PPI编程电缆 驱动
驱动程序-其它驱动-盟主led控制卡驱动程序.zip
OK6410裸机LED驱动,学ARM的好东西!
流水灯 延时时间比较长 可以自行修改 新手了解6410io的学习程序
打印机驱动 实达Start BP-690KIII 驱动打印机驱动 实达Start BP-690KIII 驱动打印机驱动 实达Start BP-690KIII 驱动打印机驱动 实达Start BP-690KIII 驱动打印机驱动 实达Start BP-690KIII 驱动打印机驱动 实达Start...
打印机驱动 爱普生XP-860打印机驱动打印机驱动 爱普生XP-860打印机驱动打印机驱动 爱普生XP-860打印机驱动打印机驱动 爱普生XP-860打印机驱动打印机驱动 爱普生XP-860打印机驱动打印机驱动 爱普生XP-860打印机驱动...
epson-2500驱动 epson-2500驱动 epson-2500驱动 epson-2500驱动 epson-2500驱动
VK1628-70点阵-串行接口-LED-高压驱动-LED数显驱动IC.docx
打印机驱动 实达Start BP-750KII 驱动打印机驱动 实达Start BP-750KII 驱动打印机驱动 实达Start BP-750KII 驱动打印机驱动 实达Start BP-750KII 驱动打印机驱动 实达Start BP-750KII 驱动打印机驱动 实达Start BP-...