Linux設備驅動學習一 設備和驅動的註冊

使用iTOP-4412開發板,用的是SCP 1G的板子。

記錄的內容來自於迅爲的視頻學習,主要是對驅動的學習,有些基礎步驟省略沒有記錄。

首先是對外部設備的操作的三部曲:

1.通過原理圖找到設備連接的PIN腳 (處理器的數據手冊)

2.通過PIN腳找到控制這個引腳的相關寄存器,並找到寄存器對應的物理地址

3.編寫程序實現設備的操作

 

1. 設備和驅動的註冊流程

    一般都是先註冊設備,再註冊驅動。現在引入的熱插拔設備是先註冊的驅動。

    1)註冊設備使用結構體platform_device,結構體中有name和id(vim include/linux/platform_device.h)

struct platform_device {
        const char      * name;
        int             id;
        struct device   dev;
        u32             num_resources;
        struct resource * resource;

        const struct platform_device_id *id_entry;

        /* MFD cell pointer */
        struct mfd_cell *mfd_cell;

        /* arch specific additions */
        struct pdev_archdata    archdata;
};

    2)註冊驅動使用結構體platform_driver,結構體中包括probe,suspend,remove,driver等(vim include/linux/platform_device.h)

struct platform_driver {
        int (*probe)(struct platform_device *);
        int (*remove)(struct platform_device *);
        void (*shutdown)(struct platform_device *);
        int (*suspend)(struct platform_device *, pm_message_t state);
        int (*resume)(struct platform_device *);
        struct device_driver driver;
        const struct platform_device_id *id_table;
};

    3)驅動的註冊需要platform_match來判斷設備和驅動name是否相同,不同則註冊失敗。否則probe然後初始化註冊設備節點等。(只有name匹配纔會到probe這一步)

2. 查看設備或驅動的幾個主要命令

    1)insmod,rmmod

    2)lsmod=cat /proc/modules

    3)查看設備節點的命令cat /proc/devices  (0~254)

    4)查看註冊的設備:ls /sys/devices/

    5)查看總線:ls /sys/bus  (platform虛擬總線,上面掛很多驅動和設備,通過兩個結構體)

    6)查看雜項設備號的命令:cat /proc/misc

3. 案例學習的流程

      其中ITOP4412的設備程序在arch/arm/mach-exynos/mach-itop4412.c(mach-itop4412.c爲板級的文件),使用的結構體爲linux/platform_device.h中的兩個。

       通過hello_ctl的案例梳理設備和驅動註冊 

1)首先配置Koncifg,讓menuconfig能夠識別:

選用的是/driver/char/Kconfig,tristate:可編譯成模塊
config HELLO_CTL
    tristate "Enable HELLO config"
    default y
    help
        Enable HELLO config

2)增加註冊設備的結構體調用。

 /* 選用的是/arch/arm/mach-exynos/mach-itop4412.c  */
 #ifdef CONFIG_HELLO_CTL
 struct platform_device s3c_device_hello_ctl = {
     .name = "hello_ctl",
     .id = -1,
 };
 #endif
 //上面幾行註冊設備使用的是函數:platform_add_devices(主要使用platform_device_register)
 
#ifdef CONFIG_HELLO_CTL
  &s3c_device_hello_ctl,
#endif

 3)重新編譯內核

 make menuconfig   # 查找/driver/char下的HELLO_CTL  用/可以直接搜索
 make zImage       #生成的zImage在/arch/arm/boot目錄下

   4)燒寫內核 (我用的燒寫方法是通過SD卡掛載到開發板)

將zImage拷貝到SD卡的update目錄下
在板子的uboot中運行
​​​​​​​# sdfuse flash kernel zImage
# reset

    5)登錄板子查看註冊完成的設備 

# ls /sys/devices/platform
hello_ctl

至此,設備註冊完成。 
驅動註冊
    6)寫一個新的驅動文件probe_linux_module.c,其中包含platform_driver結構體中的probe等 ,頭文件要包含linux/platform_device.h

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#define DEVICE_NAME "hello_ctl"

static int hello_probe(struct platform_device *pdv){
        printk(KERN_EMERG "probe hello_probe\n");
        return 0;
}

static int hello_remove(struct platform_device *pdv){
        return 0;
}
static int hello_suspend(struct platform_device *pdv){
       // 參數不太正確,這個測試主要看probe,不影響
        return 0;
}
static int hello_resume(struct platform_device *pdv){
        return 0;
}
static void hello_shutdown(struct platform_device *pdv){
        ;
}

struct platform_driver hello_driver = {
        .probe = hello_probe,
        .remove = hello_remove,
        .shutdown = hello_shutdown,
        .suspend = hello_suspend,
        .resume = hello_resume,
        .driver = {
                .name = DEVICE_NAME,
                .owner = THIS_MODULE,
        }
};

static int hello_init(void)
{
        int DriverState;
        printk("init!\n");
        DriverState = platform_driver_register(&hello_driver);
        printk(KERN_EMERG "initialized is %d.\n", DriverState);
        return 0;
}

static void hello_exit(void)
{
        printk("exit!\n");
        platform_driver_unregister(&hello_driver);
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("NANZH");
# Makefile
obj-m += probe_linux_module.o

KDIR := /home/topeet/Android/itop4412/iTop4412_Kernel_3.0

PWD ?= $(shell pwd)

all:
  make -C $(KDIR) M=$(PWD) modules

clean:
  rm -rf *.o

注:Makefile中-C調用的庫需要是編譯之後的,否則會找不到某些文件。

    7)編譯,將ko文件拷貝到板子中執行 

依次打印hello_init中的printk,然後probe,然後hello_init中register之後的內容。
如果設備沒有註冊,則probe內容不會被打印。
結果在dmesg中查看。(ismod,rmmod)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章