Linux驅動簡介和開發流程--Linux驅動學習(1)

Linux驅動簡介和開發流程

【學習筆記】linux

Linux 驅動的分類

Linux三大設備驅動shell

一、字符設備驅動

IO的傳輸過程是以字符爲單位的,沒有緩衝。好比I2C,SPI都是字符設備ubuntu

二、塊設備驅動

IO傳輸過程當中是以塊爲單位的。跟存儲相關的,都屬於塊設備,好比:tf卡bash

三、網絡設備驅動

與前兩個不同,是以socket套接字來訪問的。網絡

其中,理解和掌握字符設備驅動的概念最重要,由於在工做中咱們遇到大部分都是字符設備socket

驅動的組成

驅動分爲四個部分

(1)頭文件ide

(2)驅動模塊的入口和出口學習

(3)聲明信息命令行

(4)功能實現code

具體成分

第一步,包含頭文件

include <linux/init.h> 包含了宏定義的頭文件

include <linux/module.h> 包含了初始化加載模塊的頭文件

第二步,驅動模塊的入口和出口

module_init();
module_exit();

第三步,生命模塊具備開源許可證

MODULE_LICENSE("GPL");

第四步,功能的實現

實例

簡單的helloworld驅動程序編寫

/兩個必要的頭文件
#include <linux/init.h>
#include <linux/module.h>

//內核加載的時候打印hello world,內核模塊卸載的時候打印bye bye
static int hello_init(void){
	printk("hello world\n");  //內核裏不能使用c語言庫,因此不能用printf
	return 0;
}
static void hello_exit(void){
	printk("bye bye\n");
}

//入口和出口
module_init(hello_init);
module_exit(hello_exit);

//聲明許可證
MODULE_LICENSE("GPL");

Linux驅動編譯成模塊

方法一

把驅動編譯成模塊,而後使用命令把驅動加載到內核裏面。

步驟

一、編譯成模塊

(1)先寫一個makefile

在linux下

touch Makefile #建立Makefile文件
obj-m +=HelloWorld.o #obj-m 意爲把驅動編譯爲模塊
KDIR:={core_path} #PATH根據開發板內核路徑來填寫
PWD?=$(shell pwd) #自動獲取當前位置路徑
all:
	make -C $(KDIR) M=$(PWD) modules #切換到內核路徑,用make把代碼編譯成模塊

(2)編譯驅動

編譯驅動以前須要注意的問題:

  • 內核源碼必定要編譯經過

  • 編譯驅動用的內核源碼必定要和開發板上運行的內核鏡像是同一套

  • 看一下開發代碼的ubuntu環境是否是arm,若是不是,要改爲arm環境

查看環境的 方法

在內核源碼的目錄下輸入

make menuconfig #顯示系統環境
#左上角若是顯示是X86,而不是arm,則輸入
export ARCH=arm #改成arm環境

爲了以防萬一,編譯前,先命令行輸入兩行代碼,設置環境和編譯器

export ARCH=arm
export CROSS_COMPILE={編譯器名稱} #能夠直接輸入arm查看
#若是查看到:arm-linux-gnueabihf-gcc-4.9.4

編譯成功後就能夠看到 ko 文件了,這個 ko 文件就是編譯好的驅動。

image

在開發板上加載驅動用insmod

insmod HelloWorld.ko

查看加載的模塊,使用lsmod命令

lsmod

卸載驅動模塊

rmmod HelloWorld #注意這裏沒有後綴

卸載時,若是提示沒有相應的目錄,直接在對應的目錄下建立就能夠了

方法二

直接把驅動編譯到內核。

在下面有實際的例子。

移植

若是芯片的內核不支持設備的驅動,那麼就須要把這個驅動移植到內核。

移植驅動須要驅動源碼和makefile。

移植需求分析

(1)先去內核源碼搜索,若是有的話,能夠直接選擇這個驅動,而後直接使用。

(2)假如沒有這個驅動,則許喲啊本身編譯一個驅動,而後加載到內核裏邊去運行。

make menuconfig 圖形化配置

一、如何進入make menuconfig圖形化配置

首先進入到內核源碼的路徑下,而後輸入make menuconfig 便可打開這個界面。

二、make menuconfig圖形化界面的操做

(1)搜索功能

輸入「/」便可彈出搜索界面

(2)配置驅動狀態

  • 把驅動編譯成模塊(用[ M ]來表示)

  • 把驅動編譯到內核裏(用[ * ]來表示)

  • 不編譯(用[ ]來表示)

可使用「空格」鍵來配置這三種不一樣的狀態

(3)如何退出

分爲保存退出和不保存退出,按照提示選擇便可

(4)和make menuconfig 有關的文件

Makefile:裏邊是編譯規則,高速咱們在make的時候須要如何編譯(至關於菜的作法)

Kconfig:內核配置的選項(至關於服務員給的菜單)

.config:配置完內核之後生成的配置選項(至關於我門勾選的菜單)

(5)make menuconfig會讀取不一樣環境目錄下的Kconfig文件

會讀取Arch/$ARCH/目錄下(目錄下有不少不一樣的環境文件夾)的Kconfig文件(選擇不一樣的環境,和export ARCH=arm效果相似)。

/arch/arm/configs 下面有不少配置文件(至關於特點菜,默認配置,在不知道如何配置的時候能夠按照這個來),若是移植內核的時候,配置文件太多,就能夠把這個文件夾下面的配置複製成.config裏邊(即默認系統的配置)【複製用cp命令】

(6)爲何要複製成.config,而不是其餘名字

由於內核會默認讀取Linux內核根目錄下的.config做爲默認的配置選項,因此不能夠更名字

(7)若是複製的默認配置.config不知足咱們的要求,如何解決

直接輸入make menuconfig,進入Kconfig配置界面,來進行修改配置,保存退出,配置會自動更新到.config裏面。

(8)配置文件選項怎樣和Makefile文件創建聯繫

當make menuconfig保存退出之後,Linux會將全部的配置選項以宏定義的形式保存在include/generated/下面的autoconf.h頭文件中。

把驅動編譯到內核

Kconfig代碼例子

#例子
source "drivers/redled/Kconfig"
config LED_4412
		tristate "Led Support for GPIO Led"
		depends on LEDS_CLASS
		help
		This option enable support for led
#解讀
source "drivers/redled/Kconfig"#會讓config菜單裏邊包含drivers/redled/這個路徑下的驅動文件,方便咱們對菜單進行管理
config LED_4412 #配置選項的名稱,全名是CONFIG_LED_4412,這裏作了一些省略
		tristate "Led Support for GPIO Led"
		#tristate表示驅動的狀態:1.把驅動編譯成模塊 2.把驅動編譯到內核 3.不編譯。與之對用的還有bool關鍵字:表示編譯到內核,和不編譯兩種狀態。
		#"Led Support for GPIO Led"是make menuconfig裏邊的某個菜單的名字
		depends on LEDS_CLASS
        # A depends on B表示只有在選擇B的時候才能夠選擇A,即A依賴於B。
        #好比想要去掉LED相關的驅動,咱們雖然能夠直接改.config文件,可是不推薦這樣作。由於若是有依賴項的話,直接改.config文件是不成功的。
        #select:反向依賴,該選項被選中時,後面的定義也會被選中。
		help
		This option enable support for led   #顯示幫助信息

實例

把HelloWorld驅動編譯到內核。

(1)首先進入到內核源碼的目錄下(內核根目錄)

(2)把HelloWorld.c驅動,複製到drivers/char/hello文件夾【char通常就是放字符設備的文件夾,hello文件夾使用mkdir命令建立】

(3)寫Kconfig文件

mkdir hello #建立hello文件夾
cd hello/ #切換到hello文件夾
cp /home/pyma/HelloWorld.c #把驅動文件複製到hello文件夾中
touch Kconfig #建立一個Kconfig文件
vi Kconfig #打開Kconfig進行編輯

#寫程序
config HELLO	#起個名字叫HELLO
	tristate "hello world"	#選擇三種狀態的方式,並把菜單名字命名爲hello world
	#過於簡單沒有依賴,不用寫
	help
	hello help	#幫助信息爲hello help

保存退出

(4)寫Makefile文件

touch Makefile #建立Makefile文件夾
vi Makefile #打開Makefile編輯

#寫程序
obj-$(CONFIG_HELLO)+=HelloWorld.o

CONFIG_HELLO這個變量名字來源:是剛剛在Kconfig中命名的,可是Kconfig中至關於省略了CONFIG_,在這裏至關於補上,即:makfile中要寫全名。
$(CONFIG_HELLO)變量做用:會根據咱們選擇的狀態來改變,(1)若是是選擇把它編譯到內核中,那麼表示-y(即:obj-y)(2)若是選擇編譯成模塊,那麼它表示-m(即:obj-m)

到此,全部的文件都準備完成,接下來須要

(5)把hello驅動配置包,包含進去

須要修改上一級目錄的Makefile和Kconfig

cd ..	#返回上一級目錄,即路徑.../char/
vi Makefile #修改Makefile,若是沒有則須要本身建立,本身寫

#寫程序,在首行添加如下代碼
obj-y +=hello/   #這裏注意hello是個文件夾,所以最後要加"/"   
... #原有的makefile代碼
#保存退出

vi Kconfig	#打開Kconfig文件,把剛纔寫的驅動代碼的Konfig包含進config菜單界面中
#在前面相應位置添加好Kconfig的路徑
source "drivers/char/hello/Kconfig" #Kconfig相對路徑
#保存退出

(6)回到內核根目錄下,打開菜單,選擇不一樣狀態

make menuconfig	#進入配置菜單

在界面中選擇Device Drivers選項進入

再進入到Character devices目錄下

就會看到新添加的hello world驅動菜單項(名字是在Kconfig中命名的)

用空格鍵選擇狀態 :編譯成模塊;<*>:編譯進內核;< >:不編譯

(7)編譯進內核,選擇<*>(編譯到內核)

保存退出,而後確保配置正確與否

打開.config文件,搜索

vi .config #打開配置文件
#搜索HELLO
#搜索命令
/HELLO
若是出現CONFIG_HELLO=y是編譯到內核中了,m是編譯成模塊
這裏能夠看出,若是沒有依賴項,也能夠直接改.config文件的CONFIG_HELLO項

(8)編譯前更改

這時還不能立馬編譯,由於編譯會調用默認的的編譯配置,須要作相應修改

這裏爲了理解的透徹,先看一下編譯腳本:vi create.sh

#!/bin/bash

export ARCH=arm
...
make imx_v7_defconfig	#這個就是內核的默認用法,意思是在編譯的時候會本身去找arch/arm/configs下面的imx_v7_defconfig配置文件,做爲.config來編譯內核。
...

雖然前面咱們改了.config文件,但不是直接用它來編譯的,而是使用默認的arch/arm/configs/imx_v7_defconfig文件來編譯的。

所以還要再改一下

  • make distclean,清除全部的編譯文件,也刪掉了.config文件

  • 把缺省配置複製到.config中

cp arch/arm/configs/imx_v7_defconfig .config
  • make menuconfig 配置菜單選項

再進行第(6)步操做(這裏感受有點亂,步驟重複了?(6)、(7)兩步能夠不要)

(9)鍵修改後的.config複製回默認編譯菜單裏

cd arch/arm/configs/	#切換到默認配置目錄
mv imx_v7_defconfig imx_v7_defconfig_noHELLO #更改默認配置的名字
cp ../../../.config imx_v7_defconfig #把修改好的配置,更改成默認的名稱

(10)運行腳本,等待編譯完成

./create.sh

(11)檢驗是否編譯成功

方法一:燒寫到開發板上,運行看看有沒有加載驅動

cp arch/arm/boot/zImage /home/pyma/  #把鏡像複製到好找的位置

方法二:進入到建立的驅動目錄,查看有沒有把.c文件編譯成.o文件

cd drivers/char/hello/
ls

若是沒有相應的.o文件,則說明編譯出錯,檢查Makefile和其餘文件。

修改好,再回到根目錄編譯

.o文件檢查沒有問題後,再回到根目錄檢查是否有zImage鏡像

ls arch/arm/boot/

整理自嵌入式學習之Linux驅動篇

相關文章
相關標籤/搜索