天天看點

Led驅動程式的設計

之前的字元裝置驅動程式的例子是虛拟的一個記憶體,現在以以一個實際的硬體的設計來為例子

首先LED的程式是一種字元裝置程式

字元裝置方法open和 ioctrl

本文部落格位址:http://blog.csdn.net/b2997215859/article/details/47183419

轉載請注明來源:http://blog.csdn.net/b2997215859/article/details/47183419

然後以下是源代碼

首先是子產品的初始化函數

static intled_init()

{        

cdev_init(&cdev,&led_fops);

allo_chrdev_region(&devno, 0 , 1 ,'myled');

cdev_add(&cdev, devno , 1);

return0 ;

}        

我們把硬體的初始化後放到open裡來做,open和ioctl均定義在file_operations裡面

static structfile_operations led_fops =

{

.open = led_open ,

.unlocked_ioctl = led_ioctl,

};

注:分好要加上,不然會報錯;并且之間是用逗号隔開,不是用分号

--------------------

然後順手完成對裝置的登出

static voidled_exit()

{

cdev_del(&cdev);

unregister_chrdev_region(&devno,1);

}

第一個語句是對裝置的登出

第二個語句是對裝置号的登出

-------------------

添加#inlcude<linux/cdev.h>來包括cdev等初始化、登出等操作

添加##include<linux/fs.h>來包括struct file_operation等相關東東

-------------------

然後就開始實作裝置函數

首先是open,在open裡實作硬體的初始化,

#define GPBCON 0x56000010   //定義控制寄存器的宏

unsigned int *led_config ;      //定義存放GPBCON的虛拟位址

led_config = ioremap(GPBCON , 4); //實體位址轉化為虛拟位址

#define GPBDAT 0x56000014   //定義資料寄存器的宏

unsigned int *led_data;        定義存放GPBDAT的虛拟位址

writel(0x400 , led_config); // l表示寫入32位的值

led_data = ioremap(GPBDAT , 4)//同時将led_data初始化

--------------------

然後是led_ioctl的實作

首先在此之前分析led_ioctl的功能有倆個,關閉和點亮,故建立led.h來定義指令

#define LED_MAGIC 'L'    //定義該裝置的幻數

#define LED_ON _IO(LED_MAGIC , 0);   //_Io的作用見之前頁面對字元裝置的介紹,led沒有參數傳入,故使用__IO

#define LED_OFF _IO(LED_MAGIC ,1);  //第一個參數是裝置的幻數,第二是指令的區分符而已

定義好指令之後,便可以通過switch語句進行判别了

如果是LED_ON,則指派0x00,如果是LED_OFF,則指派0x11

longled_ioctl(struct file *filp, unsigned int cmd , unsigned long arg)

{

switch(cmd)

{

caseLED_ON:

writel(0x00 ,led_data);

return0;

caseLED_OFF:        

writel(0xff , led_data);

return0;

default:

return-EINVAL;

}        

}

注:關閉led的時候指派是0xff而不是0x11

-----------------------

#include<linux/io.h>  //writel的使用

#include    "led.h"      //包含頭檔案“led.h”

在編譯的時候會出現很多問題,需要細心去調bug<,比如說這次我在led.h的後面的define語句加了分号,然後在led.c的驅動程式中就會報錯,和符号什麼有關,在led.c中報錯233333

然後編寫驅動程式即可

貼出源碼如下

#include<sys/types.h>

#include<sys/stat.h>

#include<fcntl.h>

#include<sys/ioctl.h>

#include"led.h"

int main(int argc,char *argv[])

{

     int fd;

     int cmd;

     if (argc <2 )

     {

         printf("please enter the secondpara!\n");

         return0;        

     }

     cmd = atoi(argv[1]);

     fd = open("/dev/myled",O_RDWR);

     if (cmd == 1)

         ioctl(fd,LED_ON);

     else

        ioctl(fd,LED_OFF);        

     return 0;

}

----------------------------------------------------------------

Led驅動程式的源代碼如下

#include<linux/module.h>

#include<linux/init.h>

#include<linux/cdev.h>

#include<linux/fs.h>

#include<linux/io.h>

#include "led.h"

#define GPBCON 0x56000010

#define GPBDAT 0x56000014

unsigned int *led_config ;

unsigned int *led_data;

struct cdev cdev ;

dev_t devno;

int led_open(struct inode *node, struct file *filp)

{

led_config = ioremap(GPBCON,4);

writel(0x400,led_config);//l表示寫入的是32位的值

led_data = ioremap(GPBDAT,4);

    return 0;

//mov r1, #0x0

}

long led_ioctl(struct file *filp, unsigned int cmd , unsigned long arg)

{

switch(cmd)

{

case LED_ON:

     writel(0x00,led_data);

     return 0;

case LED_OFF:

             writel(0xff,led_data);

             return 0;

default:

     return -EINVAL;

}

}

static struct file_operations led_fops = 

{

.open = led_open ,

.unlocked_ioctl = led_ioctl,

};

static int led_init()

{

cdev_init(&cdev,&led_fops);

alloc_chrdev_region(&devno , 0 , 1 ,"myled");

cdev_add(&cdev , devno , 1);

return 0 ;

}

static void led_exit()

{

cdev_del(&cdev);

unregister_chrdev_region(devno,1);

}

module_init(led_init);

module_exit(led_exit);