安卓驅(qū)動(dòng)開(kāi)發(fā)過(guò)程
機(jī)器介紹
本人是在win10里安裝vmware workstation16軟件,然后在vmware里創(chuàng)建了ubuntu18.04系統(tǒng)的虛擬機(jī)
安卓開(kāi)發(fā)板用的是北京迅為的rk3568開(kāi)發(fā)板
步驟
step1.下載android11源碼
step2.編譯android源碼(make命令)
step3.編寫(xiě)驅(qū)動(dòng)文件
step4.構(gòu)建鏡像(build.sh) (有兩種加載驅(qū)動(dòng)的方式)
step5.鏡像燒寫(xiě)至rk3568開(kāi)發(fā)板
step1:下載android11源碼
源碼非常大,為了確保下載后編譯成功,請(qǐng)確保硬盤(pán)有300g的空間,可以下載谷歌的源碼,也可以下載rk3568提供的源碼
一、谷歌的源碼下載:
1.設(shè)置git
ice@ubuntu:~/Android$ sudo apt-get install git
ice@ubuntu:~/Android$ git config --global user.name "abcd"
ice@ubuntu:~/Android$ git config --global user.email "abcd@xxx.com"
2.下載“源碼的下載管理工具”
ice@ubuntu:~/Android$ git clone https://gerrit-googlesource.lug.ustc.edu.cn/git-repo
ice@ubuntu:~/Android$ mkdir .repo
ice@ubuntu:~/Android$ mv git-repo .repo/repo #將“git-repo”移動(dòng)到剛剛創(chuàng)建的“.repo”文件中,并將其名稱改為“repo”
ice@ubuntu:~/Android$ cp .repo/repo/repo ./
ice@ubuntu:~/Android$ chmod u+x repo
3.開(kāi)始下載
ice@ubuntu:~/Android$ ./repo init -u git://mirrors.ustc.edu.cn/aosp/platform/manifest -b android-security-11.0.0_r55
ice@ubuntu:~/Android$ ./repo sync -j2
二、rk3568提供的源碼下載:
本文用的rk3568開(kāi)發(fā)板,使用的是供應(yīng)商定制改動(dòng)了一些內(nèi)容的android11源代碼,從百度網(wǎng)盤(pán)下載的
解壓后的文件如圖,基本和谷歌原版結(jié)構(gòu)一致
鏈接: https://pan.baidu.com/s/16nucdvOIcBgCWMw7_aCyUQ?pwd=1dae
提取碼: 1dae
step2:編譯android源碼(make命令)
1.編譯的幾個(gè)選項(xiàng)
ice@ubuntu:~/Android$ cd rk_android11.0_sdk
ice@ubuntu:~/Android/rk_android11.0_sdk$ source build/envsetup.sh
ice@ubuntu:~/Android/rk_android11.0_sdk$ lunch
有如下選項(xiàng)
我這里選擇55
成功后提示
解釋一下選擇問(wèn)題,無(wú)論是谷歌下載的源碼還是rk3568提供的源碼,都一樣的解釋
2.開(kāi)始編譯
ice@ubuntu:~/Android/rk_android11.0_sdk$ make -j12
這里的j12就是12個(gè)并行任務(wù),你可以根據(jù)自己的cpu核數(shù)設(shè)定,之后就是等待編譯成功
step3:編寫(xiě)驅(qū)動(dòng)文件
驅(qū)動(dòng)文件是c語(yǔ)言,文件是helloworld.c,內(nèi)容如下
#include <linux/module.h>
#include <linux/kernel.h>
static int helloworld_init(void)
{
printk("helloworld_init\r\n");
return 0;
}
static void helloworld_exit(void)
{
printk("helloworld_exit\r\n");
}
module_init(helloworld_init);
module_exit(helloworld_exit);
step4:開(kāi)始構(gòu)建鏡像(build.sh)
想使驅(qū)動(dòng)在安卓系統(tǒng)中運(yùn)行,有兩種編譯方式。
1.驅(qū)動(dòng)編譯到內(nèi)核
2.驅(qū)動(dòng)編譯成內(nèi)核模塊
兩種驅(qū)動(dòng)編譯方式
1.驅(qū)動(dòng)編譯到內(nèi)核介紹:
構(gòu)建內(nèi)核鏡像時(shí),驅(qū)動(dòng)c文件放在編譯好的安卓源碼里,放在其本身有的驅(qū)動(dòng)一起的位置,本文是~/Android/rk_android11.0_sdk/kernel/drivers
文件夾里,所有驅(qū)動(dòng)一起編譯并構(gòu)建鏡像
2.驅(qū)動(dòng)編譯成內(nèi)核模塊介紹:
這種要先構(gòu)建出不含我們自己寫(xiě)的驅(qū)動(dòng)的鏡像
,把鏡像燒寫(xiě)至開(kāi)發(fā)板,之后才能加載ko文件。
請(qǐng)直接閱讀"驅(qū)動(dòng)編譯到內(nèi)核"部分的s4:構(gòu)建內(nèi)核鏡像
后,再閱讀m2.驅(qū)動(dòng)編譯成內(nèi)核模塊實(shí)戰(zhàn)
部分。
步驟是編譯出我們的驅(qū)動(dòng)ko文件,把此驅(qū)動(dòng)ko文件拷貝至開(kāi)發(fā)板,在運(yùn)行中的開(kāi)發(fā)板里,通過(guò)insmod命令加載驅(qū)動(dòng)。
m1.驅(qū)動(dòng)編譯到內(nèi)核實(shí)戰(zhàn)
s1.drivers文件夾內(nèi)創(chuàng)建自己的驅(qū)動(dòng)文件夾并寫(xiě)入驅(qū)動(dòng)文件。
我是放在了drivers的字符設(shè)備下,即char文件夾下
ice@ubuntu:~/Android/rk_android11.0_sdk/kernel/drivers$ mkdir char/helloworld
寫(xiě)入驅(qū)動(dòng)c文件 helloworld.c
s2.構(gòu)建鏡像時(shí)的各模塊的設(shè)置
構(gòu)建內(nèi)核鏡像時(shí),需要編譯的模塊,是從~/Android/rk_android11.0_sdk/kernel/Kconfig這個(gè)設(shè)置文件讀取的,而這個(gè)Kconfig文件又匯總了,kernel內(nèi)其他模塊的Kconfig文件
所以,對(duì)于我們的hellworld驅(qū)動(dòng),也要加入Kconfig文件
ice@ubuntu:~/Android/rk_android11.0_sdk/kernel/drivers$ cd char/helloworld
ice@ubuntu:~/Android/rk_android11.0_sdk/kernel/drivers/char/helloworld$ touch Kconfig
helloworld文件夾的Kconfig文件中寫(xiě)入如下內(nèi)容
config helloworld
bool "hellworld support"
default y
help
helloworld Kconfig
因?yàn)閔elloworld文件夾,在drivers/char文件夾內(nèi),要在char文件夾的Kconfig中引入helloworld文件夾的Kconfig文件
ice@ubuntu:~/Android/rk_android11.0_sdk/kernel/drivers/char$ vi Kconfig
文件內(nèi)加入一行:
source "drivers/char/helloworld/Kconfig"
即
至此,構(gòu)建內(nèi)核鏡像的所有設(shè)置,都在各級(jí)的Kconfig中寫(xiě)好了,下面使Kconfig生效。
進(jìn)入kernel
文件夾,制作總的config文件
ice@ubuntu:~/Android/rk_android11.0_sdk/kernel$ make menuconfig
出現(xiàn)了以上的圖說(shuō)明我們Kconfig設(shè)置成功了。
此時(shí),會(huì)在kernel文件夾下生成一個(gè)匯總的.config隱藏文件
如圖所示:
文件的內(nèi)容如下:
這里 CONFIG_helloworld=y 是我們hellowold文件夾里的Kconfig里 default y設(shè)置出來(lái)的
s3. 根據(jù)設(shè)置,確定編譯構(gòu)建內(nèi)核的步驟
構(gòu)建內(nèi)核鏡像時(shí),設(shè)置是記錄在各級(jí)Kconfig文件,根據(jù)這些設(shè)置對(duì)應(yīng)的編譯步驟是記錄在各級(jí)的Makefile中的。
helloworld文件夾中插入Makefile
ice@ubuntu:~/Android/rk_android11.0_sdk/kernel/drivers/char/helloworld$ vi Makefile
Makefile插入如下代碼
obj-$(CONFIG_helloworld) += helloworld.o # 此CONFIG_helloworld變量是來(lái)自于上一步中新生成的那個(gè)在kernel文件夾下的.config文件
即:
helloworld是在drivers/char文件夾下的,需要在char文件夾的Makefile中加入編譯helloworld模塊的操作步驟
obj-$(CONFIG_helloworld) += helloworld/
至此Makefile是設(shè)置完成了。
s4:構(gòu)建內(nèi)核鏡像
很簡(jiǎn)單,進(jìn)入android源碼文件夾,根據(jù)自己的需求制作所需的鏡像。
最終構(gòu)建鏡像時(shí),設(shè)置一下屏幕文件的參數(shù),文件在以下文件夾中
rk3568 的屏幕文件是
我需要的是內(nèi)核鏡像,因?yàn)轵?qū)動(dòng)是在內(nèi)核鏡像里的,當(dāng)驅(qū)動(dòng)更新時(shí),需要把內(nèi)核鏡像更新。
安卓系統(tǒng)里不同的鏡像的功能介紹參考一個(gè)短視頻(10min):https://www.bilibili.com/video/BV1pv4y1K71W?p=2
開(kāi)始build 構(gòu)建鏡像
ice@ubuntu:~/Android/rk_android11.0_sdk$ ./build.sh -CKA
內(nèi)核鏡像位置:
build.sh后面的參數(shù)含義
s5小結(jié):
我們先在helloworld文件夾下,創(chuàng)建了3個(gè)文件:
接著我們把char文件加下的Kconfig文件和Makefile文件做了修改,使得helloworld能加入編譯過(guò)程
最后我們是先使用make menuconfig 命令使所有Kconfig設(shè)置生效并生成.config文件
然后我們就開(kāi)始構(gòu)建鏡像了
ice@ubuntu:~/Android/rk_android11.0_sdk$ ./build.sh -CKA # 此命令是內(nèi)核鏡像構(gòu)建
生成的內(nèi)核鏡像路徑在以下路徑中
其他鏡像的構(gòu)建,請(qǐng)使用不同的參數(shù),生成的img鏡像也在別的路徑中
m2.驅(qū)動(dòng)編譯成內(nèi)核模塊實(shí)戰(zhàn)
s1.先建立一個(gè)文件夾放置驅(qū)動(dòng)c文件和Makefile
helloworld2.c:
#include <linux/module.h>
#include <linux/kernel.h>
static int helloworld_init(void)
{
printk("helloworld2_init\r\n");
return 0;
}
static void helloworld_exit(void)
{
printk("helloworld2_exit\r\n");
}
module_init(helloworld_init);
module_exit(helloworld_exit);
Makefile:
obj-m += helloworld2.o
KDIR :=/home/ice/Android/rk_android11.0_sdk/kernel/ # 用的是安卓11源碼的內(nèi)核
PWD ?= $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) ARCH=arm64 $(KDIR).config modules # 注意此處多了ARCH參數(shù)和 ".config"文件參數(shù)
.PHONY:clean
clean:
make -C $(KDIR) M=$(PWD) clean
s2.生成Makefile所需的.config文件
進(jìn)入kernel
文件夾,制作總的config文件
ice@ubuntu:~/Android/rk_android11.0_sdk/kernel$ make menuconfig # 此命令會(huì)在此文件夾下生成.config文件
成功后彈出以下界面:
退出此界面后,我們看看是否生成了我們需要的.config
文件
生成了,下面開(kāi)始編譯ko文件
s3.編譯ko文件(make命令)
s4.把ko文件傳至開(kāi)發(fā)板
此處請(qǐng)先確保開(kāi)發(fā)板的安卓鏡像已經(jīng)燒寫(xiě)成功,否則需要閱讀step5:燒寫(xiě)鏡像至開(kāi)發(fā)板
部分
電腦usb連接 rk3568開(kāi)發(fā)板,用MobaXterm客戶端,通過(guò)com串口訪問(wèn)開(kāi)發(fā)板控制臺(tái)。
我是在開(kāi)發(fā)板里新建了一個(gè)文件夾:
把驅(qū)動(dòng)ko文件傳至此文件夾,這個(gè)過(guò)程有點(diǎn)曲折,步驟如下:
1.我先是把helloworld2.ko文件放到了win10的任意文件夾內(nèi),我的是z:盤(pán)里了
2.通過(guò)adb push
命令把文件傳送至開(kāi)發(fā)板的安卓系統(tǒng)里
傳好的結(jié)果如下圖
s5.加載驅(qū)動(dòng)(insmod命令)
首先要進(jìn)入root權(quán)限
,運(yùn)行 su
命令
其次進(jìn)入ko文件所在文件夾,運(yùn)行insmod
和rmmod
命令加載和卸載驅(qū)動(dòng)
step5:燒寫(xiě)鏡像至開(kāi)發(fā)板
燒寫(xiě)過(guò)程完全參照bilibili教程 (9min):
鏈接:
https://www.bilibili.com/video/BV1pv4y1K71W?p=4
燒寫(xiě)工具下載鏈接:
鏈接: https://pan.baidu.com/s/1m2H_s12ifb3EDIyoPG0hhQ?pwd=gdjh
提取碼: gdjh
step6:查看驅(qū)動(dòng)是否運(yùn)行成功
電腦usb連接 rk3568開(kāi)發(fā)板,用MobaXterm客戶端,通過(guò)com串口訪問(wèn)開(kāi)發(fā)板控制臺(tái),通過(guò)dmesg命令查看開(kāi)發(fā)板啟動(dòng)時(shí),我們的驅(qū)動(dòng)是否運(yùn)行成功。
這個(gè)過(guò)程參考視頻鏈接 (4min):
https://www.bilibili.com/video/BV1744y1u779/?p=11文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-782425.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-782425.html
到了這里,關(guān)于android驅(qū)動(dòng)開(kāi)發(fā)從零到一的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!