第四季-專題11-LED驅動程序設計

專題11-LED驅動程序設計

第1課-字符設備控制

  1. 設備控制理論

(1)做用node

大部分驅動程序除了須要提供讀寫設備的能力外,還須要具有控制設備的能力。好比: 改變波特率。linux

(2)應用程序接口編程

在用戶空間,使用ioctl系統調用來控制設備,原型以下:app

int ioctl(int fd,unsigned long cmd,...)函數

fd: 要控制的設備文件描述符設計

cmd: 發送給設備的控制命令接口

…: 第3個參數是可選的參數,存在與否是依賴於控制命令(第2 個參數)。rem

(3)設備驅動方法cmd

當應用程序使用ioctl系統調用時,驅動程序將由以下函數來響應:原型

1: 2.6.36 以前的內核

long (*ioctl) (struct inode* node ,struct file* filp, unsigned int cmd,unsigned long arg)

2:2.6.36以後的內核

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

參數cmd: 經過應用函數ioctl傳遞下來的命令

 

  1. 設備控制實現

(1)       定義命令

命令從其實質而言就是一個整數, 但爲了讓這個整數具有更好的可讀性,咱們一般會把這個整數分爲幾個段:類型(8位),序號,參數傳送方向,參數長度。

Type(類型/幻數): 代表這是屬於哪一個設備的命令。

Number(序號),用來區分同一設備的不一樣命令

Direction:參數傳送的方向,可能的值是_IOC_NONE(沒有數據傳輸), _IOC_READ, _IOC_WRITE(向設備寫入參數)

Size: 參數長度

Linux系統提供了下面的宏來幫助定義命令:

_IO(type,nr):不帶參數的命令

_IOR(type,nr,datatype):從設備中讀參數的命令

_IOW(type,nr,datatype):向設備寫入參數的命令

例:

#define MEM_MAGIC ‘m’ //定義幻數

#define MEM_SET _IOW(MEM_MAGIC, 0, int)

(2)       實現操做

unlocked_ioctl函數的實現一般是根據命令執行的一個switch語句。可是,當命令號不能匹配任何一個設備所支持的命令時,返回-EINVAL.

編程模型:

Switch cmd

Case 命令A:

//執行A對應的操做

Case 命令B:

//執行B對應的操做

Default:

// return -EINVAL

  1. 本身動手寫驅動

Led.c

#include <linux/module.h>

#include <linux/init.h>

#include <linux/cdev.h>

#include <linux/fs.h>

#include <linux/io.h>

#include <mach/gpio-bank-k.h>

#include "led.h"

 

#define LEDCON 0x7f008800

#define LEDDAT 0x7f008808

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(LEDCON,4);

    writel(0x11110000,led_config);

   

    led_data = ioremap(LEDDAT,4);

   

    return 0;

}

 

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);

 

 

led_app.c

#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 second para!\n");

         return 0;  

     }

    

     cmd = atoi(argv[1]);

    

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

    

     if (cmd == 1)

         ioctl(fd,LED_ON);

     else

         ioctl(fd,LED_OFF);  

        

        

     return 0;

}

相關文章
相關標籤/搜索