1. 程式人生 > >用一個例項來理解驅動程式編寫流程 (自用)

用一個例項來理解驅動程式編寫流程 (自用)

#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
 

//流水燈程式碼

#define  GPM4CON 0x110002e0
#define  GPM4DAT 0x110002e4


static unsigned long*  ledcon = NULL;
static unsigned long*  leddat = NULL;

//自定義write檔案操作(不自定義的話,核心有預設的一套檔案操作函式)
static  ssize_t  test_write (struct file * filp, const char __user * buff, size_t count, loff_t * offset)
{
    int  value = 0;
    int ret = 0;

    ret = copy_from_user(&value, buff, 4);

       //底層驅動只定義基本操作動作,不定義功能

    if(value == 1)
        {
        *leddat  |=  0x0f;
        *leddat  &=  0xfe;
        }
    if(value == 2)
        {
        *leddat  |=  0x0f;
        *leddat  &=  0xfd;
        }
    if(value == 3)
        {
        *leddat  |=  0x0f;
        *leddat  &=  0xfb;
        }
    if(value == 4)
        {
        *leddat  |=  0x0f;
        *leddat  &=  0xf7;
        }
    return 0;
}
 

//檔案操作結構體初始化

static  struct file_operations  g_tfops = {
                        .owner = THIS_MODULE,
                        .write = test_write,
                        };
        

//雜裝置資訊結構體初始化

static  struct miscdevice  g_tmisc = {
            .minor = MISC_DYNAMIC_MINOR,
            .name = "test_led",
            .fops = &g_tfops,
            };



//驅動入口函式         雜裝置初始化
static  int  __init   test_misc_init(void)

    {

        //IO地址空間對映到核心的虛擬地址空間

        ledcon = ioremap(GPM4CON, 4);

        leddat = ioremap(GPM4DAT, 4);

         //初始化led

        *ledcon  &=  0xffff0000;
        *ledcon  |=  0x00001111;
        *leddat  |=  0x0f;

         //雜設備註冊函式

        misc_register(&g_tmisc);
        return 0;
    }
 

//驅動出口函式

static  void  __exit  test_misc_exit(void)
    {

        //釋放地址對映
        iounmap(ledcon);
        iounmap(leddat);
    }
 

//指定模組的出入口函式

module_init(test_misc_init);
module_exit(test_misc_exit);


MODULE_LICENSE("GPL");