×
单片机 > 单片机程序设计 > 详情

iny6410 简单的LED字符设备驱动 io驱动

发布时间:2020-06-08 发布时间:
|

Step1:驱动加载函数: ***_init;

该函数内容为驱动硬件时仅执行一次的函数,其作用是硬件初始化。如配置IO端口输出方向,配置IO上拉等;该函数传入在module_init(***_init);函数中以使得在加载驱动时自动执行;


Step2:写open,read,write,release函数;

这三个函数的作用是为了传入file_operations结构体;在应用程序调用驱动时这三个函数作为借口被调用。

其中open的作用是在编写应用程序时加载驱动程序;其原型为pen(strpath, authority )如:fd = open("/dev/led",O_RDWR);//open函数加载驱动,返回值为描述符,返回值为0时则成功加载驱动。

Write函数的原型为: (structfile *filp, const char __user *buf, size_t count,loff_t *f_pos)   


Step3:将step2中的函数赋给operations结构体

struct file_operations led_fops =  

{   

    .owner= THIS_MODULE,   

    .open= led_open,   

    .read= led_read,   

    .write= led_write,   

    .release= led_release,   

};

Step4:在***_init函数中注册字符型设备驱动模块;如以下为注册led驱动函数:

register_chrdev(LED_MAJOR,"led",&led_fops);

int register_chrdev(unsignedintmajor,constchar*name,structfile_operations*fops);

其中参数major如果等于0,则表示采用系统动态分配的主设备号;不为0,则表示静态注册。

注销字符设备可以使用unregister_chrdev函数。


Step5:注销字符型设备驱动模块:

在led_exit(可以任意名字,最后把函数名传给module_exit即可)使用unregister_chrdev(LED_MAJOR,"led"); 函数注销驱动。并赋给module_exit(led_exit);



·一个活生生的例子   


1.查看用户手册


led1、led2、led3、led4 连接的分别是 GPK4、GPK5、GPK6、GPK7

2、查询6410芯片手册





下面还需要3个步骤:

1、设置GPIO为OUTPUT。

   将GPK4、GPK5、GPK6、GPK7设置为输出output=0001

   即GPKCON0的19:28都配置为0001


2、设置GPIO的数据。

   将GPKDATA的4:7位赋值为0


3、设置GPKUP为上拉。

   将GPKUP的4:7位设置为10


3、代码

led_driver.cStep1:驱动加载函数: ***_init;


该函数内容为驱动硬件时仅执行一次的函数,其作用是硬件初始化。如配置IO端口输出方向,配置IO上拉等;该函数传入在module_init(***_init);函数中以使得在加载驱动时自动执行;


Step2:写open,read,write,release函数;

这三个函数的作用是为了传入file_operations结构体;在应用程序调用驱动时这三个函数作为借口被调用。

其中open的作用是在编写应用程序时加载驱动程序;其原型为pen(strpath, authority )如:fd = open("/dev/led",O_RDWR);//open函数加载驱动,返回值为描述符,返回值为0时则成功加载驱动。

Write函数的原型为: (structfile *filp, const char __user *buf, size_t count,loff_t *f_pos)   


Step3:将step2中的函数赋给operations结构体

struct file_operations led_fops =  

{   

    .owner= THIS_MODULE,   

    .open= led_open,   

    .read= led_read,   

    .write= led_write,   

    .release= led_release,   

};

Step4:在***_init函数中注册字符型设备驱动模块;如以下为注册led驱动函数:

register_chrdev(LED_MAJOR,"led",&led_fops);

int register_chrdev(unsignedintmajor,constchar*name,structfile_operations*fops);

其中参数major如果等于0,则表示采用系统动态分配的主设备号;不为0,则表示静态注册。

注销字符设备可以使用unregister_chrdev函数。


Step5:注销字符型设备驱动模块:

在led_exit(可以任意名字,最后把函数名传给module_exit即可)使用unregister_chrdev(LED_MAJOR,"led"); 函数注销驱动。并赋给module_exit(led_exit);



·一个活生生的例子   


1.查看用户手册


led1、led2、led3、led4 连接的分别是 GPK4、GPK5、GPK6、GPK7

2、查询6410芯片手册





下面还需要3个步骤:

1、设置GPIO为OUTPUT。

   将GPK4、GPK5、GPK6、GPK7设置为输出output=0001

   即GPKCON0的19:28都配置为0001


2、设置GPIO的数据。

   将GPKDATA的4:7位赋值为0


3、设置GPKUP为上拉。

   将GPKUP的4:7位设置为10


3、代码

led_driver.c


#include   /*它定义了模块的 API、类型和宏(MODULE_LICENSE、MODULE_AUTHOR等等),所有的内核模块都必须包含这个头文件。*/   

        

    #include   /*使用内核信息优先级时要包含这个文件,一般在使用printk函数时使用到优先级信息*/  

      

    #include     

    #include /* copy_to_user,copy_from_user */     

    #include      /*readl writel*/  

    #include      

    #include       

    #include       

      

        

    #define LED_MAJOR   243  

      

    #define LED_ON      1  

    #define LED_OFF     0  

    #define LED_1_ON    2  

    #define LED_1_OFF   3  

    #define LED_2_ON    4  

    #define LED_2_OFF   5  

    #define LED_3_ON    6  

    #define LED_3_OFF   7  

    #define LED_4_ON    8  

    #define LED_4_OFF   9  

      

       

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

        

    {    

        unsigned tmp;       

      

        tmp = readl(S3C64XX_GPKCON);      

        tmp = (tmp&0x0000ffff)| 0x1111ffff;  

        writel(tmp, S3C64XX_GPKCON);     

      

        printk("#########open######n");    

        return 0;    

    }    

        

    static int led_read (struct file *filp, char __user *buf, size_t count,loff_t *f_pos)    

    {      

        return count;    

    }    

        

        

    static int led_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos)  

      

    {    

        char wbuf[10];    

        unsigned tmp;       

          

        if(copy_from_user(wbuf,buf,count))  

            return -EFAULT;    

      

            switch(wbuf[0])    

            {    

              

            case LED_ON:   

                    tmp = readl(S3C64XX_GPKDAT);       

                tmp &= (0x0f);       

                writel(tmp, S3C64XX_GPKDAT);  

                printk("turn on!n");      

                    break;  

      

            case LED_OFF:    

                tmp  = readl(S3C64XX_GPKDAT);       

                tmp |= (0xf0);       

                writel(tmp, S3C64XX_GPKDAT);   

                printk("turn off!n");     

                break;             

      

            case LED_1_ON:    

                tmp = readl(S3C64XX_GPKDAT);       

                tmp &= (0xef);       

                writel(tmp, S3C64XX_GPKDAT);   

                printk("turn off!n");     

                break;    

      

            case LED_1_OFF:   

tmp = readl(S3C64X


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32单片机的复用端口初始化的步骤及方法