|     在(zai)嵌(qian)入式系統的(de)設計中,LED一(yi)般(ban)(ban)直(zhi)接由(you)(you)CPU的(de)GPIO(通(tong)用可(ke)(ke)編程I/O口)控(kong)(kong)制。GPIO一(yi)般(ban)(ban)由(you)(you)兩組(zu)寄(ji)存器控(kong)(kong)制,即一(yi)組(zu)控(kong)(kong)制寄(ji)存器和一(yi)組(zu)數(shu)據(ju)寄(ji)存器。控(kong)(kong)制寄(ji)存器可(ke)(ke)設置GPIO口的(de)工作方式為輸(shu)入或是輸(shu)出。當引(yin)(yin)腳被設置為輸(shu)出時(shi),向數(shu)據(ju)寄(ji)存器的(de)對(dui)應位(wei)寫入1和0會分別在(zai)引(yin)(yin)腳上產生(sheng)高電(dian)平和低電(dian)平;當引(yin)(yin)腳設置為輸(shu)入時(shi),讀取數(shu)據(ju)寄(ji)存器的(de)對(dui)應位(wei)可(ke)(ke)獲得引(yin)(yin)腳上的(de)電(dian)平為高或低。     LED設備(bei)介于字符設備(bei)和塊設備(bei)之(zhi)間(jian)我們稱之(zhi)為misc(雜設備(bei)),其實按(an)linux下(xia)的(de)驅動位置來(lai)講還是一(yi)種字符設備(bei)。代碼清單1.1給(gei)出了Linux下(xia)LED的(de)驅動。 代碼清單1.1  Linux操作系統(tong)下LED的驅動(dong)     1	#include .../*包含內核中的多個頭文件*/
 2	/*設備結構體*/
 3	struct light_dev {
 4	    struct cdev cdev; /*字符設備cdev結構體*/
 5	    unsigned char vaule; /*LED亮時為1,熄滅時為0,用戶可讀寫此值*/
 6	};
 
 7	struct light_dev *light_devp;
 8	int light_major = LIGHT_MAJOR;
 
 9	MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
 10	MODULE_LICENSE("Dual BSD/GPL");
 11	/*打開和關閉函數*/
 12	int light_open(struct inode *inode, struct file *filp)
 13	{
 14	    struct light_dev *dev;
 15	    /* 獲得設備結構體指針 */
 16	    dev = container_of(inode->i_cdev, struct light_dev, cdev);
 17	    /* 讓設備結構體作為設備的私有信息 */
 18	    filp->private_data = dev;
 19	    return 0;
 20	}
 
 21	int light_release(struct inode *inode, struct file *filp)
 22	{
 23	    return 0;
 24	}
 
 25	/*讀寫設備:可以不需要 */
 26	ssize_t light_read(struct file *filp, char __user *buf, size_t count,
 27	    loff_t *f_pos)
 28	{
 29	    struct light_dev *dev = filp->private_data; /*獲得設備結構體 */
 30	    if (copy_to_user(buf, &(dev->value), 1))
 31	        return  -EFAULT;
 
 32	    return 1;
 33	}
 
 34	ssize_t light_write(struct file *filp, const char __user *buf, size_t count,
 35		loff_t *f_pos)
 36	{
 37	    struct light_dev *dev = filp->private_data;
 
 38	    if (copy_from_user(&(dev->value), buf, 1))
 39	        return  -EFAULT;
 
 40	    /*根據寫入的值點亮和熄滅LED*/
 41	    if (dev->value == 1)
 42	        light_on();
 43	    else
 44	        light_off();
 
 45	    return 1;
 46	}
 
 47	/* ioctl函數 */
 48	int light_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 49	    unsigned long arg)
 50	{
 51	    struct light_dev *dev = filp->private_data;
 
 52	    switch (cmd) {
 53	    case LIGHT_ON:
 54	        dev->value = 1;
 55	        light_on();
 56	        break;
 57	    case LIGHT_OFF:
 58	        dev->value = 0;
 59	        light_off();
 60	        break;
 61	    default:
 62	        /* 不能支持的命令 */
 63	        return  -ENOTTY;
 64	    }
 
 65	    return 0;
 66	}
 
 67	struct file_operations light_fops = {
 68	    .owner = THIS_MODULE,
 69	    .read = light_read,
 70	    .write = light_write,
 71	    .ioctl = light_ioctl,
 72	    .open = light_open,
 73	    .release = light_release,
 74	};
 
 75	/*設置字符設備cdev結構體*/
 76	static void light_setup_cdev(struct light_dev *dev, int index)
 77	{
 78	    int err, devno = MKDEV(light_major, index);
 79	    cdev_init(&dev->cdev, &light_fops);
 80	    dev->cdev.owner = THIS_MODULE;
 81	    dev->cdev.ops = &light_fops;
 82	    err = cdev_add(&dev->cdev, devno, 1);
 83	    if (err)
 84	        printk(KERN_NOTICE "Error %d adding LED%d", err, index);
 85	}
 
 86	/*模塊加載函數*/
 87	int light_init(void)
 88	{
 89	    int result;
 90	    dev_t dev = MKDEV(light_major, 0);
 91	    /* 申請字符設備號*/
 92	    if (light_major)
 93	        result = register_chrdev_region(dev, 1, "LED");
 94	    else {
 95	        result = alloc_chrdev_region(&dev, 0, 1, "LED");
 96	        light_major = MAJOR(dev);
 97	    }
 98	    if (result < 0)
 99	        return result;
 
 100	    /* 分配設備結構體的內存 */
 101	    light_devp = kmalloc(sizeof(struct light_dev), GFP_KERNEL);
 102	    if (!light_devp) {
 103	        result =  -ENOMEM;
 104	        goto fail_malloc;
 105	    }
 106	    memset(light_devp, 0, sizeof(struct light_dev));
 107	    light_setup_cdev(light_devp, 0);
 108	    light_gpio_init();
 109	    return 0;
 
 110	fail_malloc:
 111	    unregister_chrdev_region(dev, light_devp);
 112	    return result;
 113	}
 
 114	/*模塊卸載函數*/
 115	void light_cleanup(void)
 116	{
 117	    cdev_del(&light_devp->cdev); /*刪除字符設備結構體*/
 118	    kfree(light_devp); /*釋放在light_init中分配的內存*/
 119	    unregister_chrdev_region(MKDEV(light_major, 0), 1); /*刪除字符設備*/
 120	}
 
 121	module_init(light_init);
 122	module_exit(light_cleanup);
 
    熱點(dian)鏈(lian)接: 
         1、嵌入式linux驅動要學哪些2、典型嵌入式Linux系統設置
 
 更多新聞>>  |