Linux驅動學習筆記
Linux驅動分類:字符設備驅動、塊設備驅動、網絡設備驅動
- 字符設備驅動:LED、屏幕、麥克風…它是最常見的驅動
- 塊設備驅動:存儲設備如磁盤、U盤…
- 網絡設備:以太網接口、WIFI模塊…
如果需要通過C語言對arm中的硬件進行控制,一般做法如下:
//通過原理圖找到與硬件相關的寄存器
//通過數據手冊獲取寄存器的基地址,例如0x11000103
//1.指針法
//定義一個無符號int類型指針來存放基地址
unsigned int * p;
p = 0x11000103;
//直接使用*p來爲指針賦值
*p = 0;
*p = 1;
//2.強制轉換法
*(unsigned int *)0x11000103 = 0;
Linux驅動是介於文件系統和底層硬件之間的,可以理解爲嵌入到內核中的程序
Linux驅動的上層是系統和應用,中間是Linux內核(驅動依附於Linux內核),其下層則是硬件
- 上層:Linux設備驅動要給上層提供調用的接口
- 中間:Linux設備驅動要註冊到Linux內核中
- 下層:Linux設備驅動要具備操作硬件的能力
最簡單的Linux驅動
功能:加載驅動的時候輸出“Hello World”
Linux頭文件的位置
例如:#include<linux/module.h>,它的位置爲Linux源碼目錄的include/linux/module.h
所有的Linux代碼必須遵循GPL協議,否則你的模塊將無法在Linux中使用
- MODULE_LICENSE(_license):添加遵循GPL協議
- MODULE_AUTHOR(_author):代碼作者
#include<linux/init.h>頭文件是必備的頭文件,因爲其包含初始化宏定以,並且驅動入口函數module_init(x)和出口函數module_exit(x)都在該文件中
最簡單驅動的詳細代碼如下:
//mini_linux_module.c
#include <linux/init.h> //包含初始化宏定義module_init、module_exit的頭文件
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL"); //添加GPL協議,Dual BSD表示沒有版本限制
MODULE_AUTHOR("Wang_Wonk"); //添加作者
static int hello_init(void)
{
printk(KERN_EMERG "Hello World enter!\n"); //內核中打印信息需要使用printk
return 0;
}
static void hello_exit(void)
{
printk(KERN_EMERG "Hello World exit!\n");
}
module_init(hello_init); //初始化函數
module_exit(hello_exit); //加載函數
//Makefile
#!/bin/bash
#指明編譯腳本
obj-m += mini_linux_module.o #指明中間文件
KDIR := /home/Xunwei_work/Driver/linux_source/iTop4412_Kernel_3.0
#源碼目錄,根據用戶實際請況選擇目錄
PWD ?= $(shell pwd)
#當前目錄
#make -C即調用執行的路徑
all:
make -C $(KDIR) M=$(PWD) modules
#表示make clean命令執行的操作
clean:
rm -rf *.o
模塊編譯流程
測試
- insmod:加載模塊命令
- lsmod:查看模塊命令
- rmmod:卸載模塊命令
使用U盤或nfs將文件拷貝到開發板上,進入mini_linux_module.ko所在的路徑,終端輸入
insmod mini_linux_module.ko
如果在實驗中遇到各種問題,請參照一下鏈接編譯相關kernel文件
https://www.bilibili.com/video/BV1vJ411d7jD?from=search&seid=10555628828748654695
如果編譯好文件之後,如果在卸載驅動的時候提示
rmmod: can't change directory to '/lib/modules': No such file or director
請參照該鏈接操作即可解決問題
https://www.cnblogs.com/lialong1st/p/7763531.html