【linux】驅動-1-環境準備

李柱明發表於2021-03-16


前言

  • 以野火i.M 6U為例

1. 開發環境搭建

驅動執行條件

  • 裝置驅動是具有獨立功能的程式,它可以被單獨編譯,但不能獨立執行, 在執行時它被連結到核心作為核心的一部分在核心空間執行。
  • 因此想要我們寫的核心模組在某個版本的核心上執行, 那麼就必須在該核心版本上編譯它,如果我們編譯的核心與我們執行的核心具備不相同的特性,裝置驅動則可能無法執行。

驅動簡要編譯步驟

  • 首先我們需要知道核心版本,並準備好該版本的核心原始碼,使用交叉編譯工具編譯核心原始碼。
  • 其次,依賴編譯的核心原始碼編譯我們的驅動模組以及裝置樹檔案。
  • 最終將驅動模組和裝置樹拷貝到開發板上執行。

1.1 環境準備

1.1.1 安裝工具

在編譯原始碼前需要準備好交叉編譯環境,安裝必要的依賴和工具,如:

  • gcc-arm-linux-gnueabihf 交叉編譯器
  • bison 語法分析器
  • flex 詞法分析器
  • libssl-dev OpenSSL 通用庫
  • lzop LZO壓縮庫的壓縮軟體

參考命令:

  • sudo apt install make gcc-arm-linux-gnueabihf gcc bison flex libssl-dev dpkg-dev lzop

1.1.2 編譯核心

編譯好核心,有以下兩個用途:

  • 製作系統映象,燒錄至開發板
  • 保留一份在開發環境的系統中,用於輔助驅動開發
1.1.2.1 獲取核心原始碼

若核心已經燒寫至開發板上,則可以通過命令 uname -a 檢視核心版本。
*
知道核心版本後可在其官網上下載其核心原始碼,如並章節以版本為 Linux npi 4.1.9.71-imx-r1 為例,可在gitee或github上下載(野火官方提供

  • 命令:git clone https://gitee.com/Embedfire/ebf-buster-linux.git
1.1.2.2 編譯核心

編譯核心的步驟過程根據不同官方提供的腳步和Makefile不一樣而不同。以下為野火的i.M 6U編譯linux核心例程。
單獨新建一個工作目錄,將其核心原始碼放在該目錄下,切換到核心原始碼目錄,找到 make_deb.sh 指令碼,修改裡面的配置引數,如核心編譯位置等等。修改好配置引數後,只需要執行指令碼即可編譯核心。(其它核心可以參考該指令碼,也可以自己手寫一個編譯指令碼

deb_distro=bionic
DISTRO=stable
build_opts="-j 6"
build_opts="${build_opts} O=build_image/build"
build_opts="${build_opts} ARCH=arm"
build_opts="${build_opts} KBUILD_DEBARCH=${DEBARCH}"
build_opts="${build_opts} LOCALVERSION=-imx-r1"

build_opts="${build_opts} KDEB_CHANGELOG_DIST=${deb_distro}"
build_opts="${build_opts} KDEB_PKGVERSION=1${DISTRO}"
build_opts="${build_opts} CROSS_COMPILE=arm-linux-gnueabihf-"
build_opts="${build_opts} KDEB_SOURCENAME=linux-upstream"

make ${build_opts}  npi_v7_defconfig
make ${build_opts}
make ${build_opts}  bindeb-pkg
  • O=build_image/build:指定編譯好的核心放置的位置。
  • ARCH=arm:目標是 ARM 體系結構核心。
  • KBUILD_DEBARCH=${DEBARCH}:對於deb-pkg目標,允許覆蓋deb-pkg部署的常規啟發式。
  • LOCALVERSION=-imx-r1:使用核心配置選項 "LOCALVERSION" 為常規核心版本附加一個唯一的字尾。
  • KDEB_CHANGELOG_DIST=${deb_distro}
  • KDEB_PKGVERSION=1${DISTRO}:版本資訊。
  • CROSS_COMPILE=arm-linux-gnueabihf-:指定交叉編譯器。
  • KDEB_SOURCENAME=linux-upstream:KDEB_SOURCENAME make變數僅控制已打包的源tarball的名稱,並不影響bind -pkg和deb-pkg輸出的.deb包名稱。
  • make ${build_opts} npi_v7_defconfig:生成配置檔案。
  • make ${build_opts} bindeb-pkg:編譯檔案進行打包。

1.2 核心驅動模組編譯和載入

hello 例程可以去 李柱明的gitee clone: demo_code_for_mystudy/linux/driverTest/helloModule

1.2.1 hello 例程分析

這只是一個模組例程,不含驅動部分
必須內容可分為以下幾點:

  • 入口函式
  • 出口函式
  • 協議

hello_module.c

/** @file hello_module.c
* @brief 簡要說明
* @details 詳細說明
* @author lzm
* @date 2021-02-21 18:08:07
* @version v1.0
* @copyright Copyright By lizhuming, All Rights Reserved
*
**********************************************************
* @LOG 修改日誌:
**********************************************************
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
// 入口函式:安裝驅動時呼叫的函式
static int __init hello_init(void)
{
printk(KERN_EMERG "[ KERN_EMERG ] Hello Module Init\n");
printk( "[ default ] Hello Module Init\n");
return 0;
}
// 出口函式:解除安裝驅動時呼叫的函式
static void __exit hello_exit(void)
{
printk("[ default ] Hello Module Exit\n");
}
module_init(hello_init);
module_exit(hello_exit);
//MODULE_LICENSE("GPL2");
MODULE_AUTHOR("embedfire ");
MODULE_DESCRIPTION("hello world module");
MODULE_ALIAS("test_module");

1.2.2 和核心原始碼一起編譯

1.2.3 載入核心驅動模組

編譯好得到的核心驅動模組 xx.ko 可以通過多種方式拷貝到 ARM 板上,如NFS網路檔案系統、SCP命令得到。
掛載方法可以參考李柱明部落格園NFS篇章

1.3 裝置樹編譯和載入

裝置樹是在 Linux3.x 才引入的,用於描述一個硬體平臺的板級細節。
本系列筆記的驅動例程如無特殊說明,都是依賴於裝置樹的
下面簡略演示裝置樹的編譯和載入,具體原理由具體篇章說明。

1.3.1 裝置樹編譯

1.3.1.1 使用核心中的dtc根據編譯

編譯後的核心會自動生成 dtc 工具。其路徑是:核心/scripts/dtc/dtc
編譯命令:核心構建目錄/scripts/dtc/dtc -I dts -O dtb -o xxx.dtbo xxx.dts

  • 意為編譯 dts 為 dtb
1.3.1.2 在核心原始碼中編譯(推薦)

編譯核心時都會自動編譯裝置樹,此時,只需要把裝置樹原始檔放到規定位置即可,裝置樹原始檔、編譯生成的裝置樹檔案及我們所用到的裝置樹檔案都會存放在 核心原始碼/arch/arm/boot/dts 裡面。但是,編譯核心耗時長,所以,推薦只編譯裝置樹,方法如下:

  • 兩條命令都在核心原始碼頂層路徑下執行(其實就是利用頂層Makefile):
    • 如果在核心原始碼中執行了 make distclean ,則必須執行第一條命令來生成預設的配置檔案。
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- npi_v7_defconfig
make ARCH=arm -j4 CROSS_COMPILE=arm-linux-gnueabihf- dtbs
1.3.1.3 載入裝置樹

替換裝置樹的方法:

  • 第一種:裝置樹是編譯到核心中的,所以,重新編譯核心,重新制作映象即可。(麻煩,不推薦)
  • 第二種:將編譯好的裝置樹或裝置樹外掛替換到開發板裡面的。(推薦)
  • 第三種:將編譯好的裝置樹放到開發板中,**/boot/dtbs/xxx/,修改boot啟動引數。(推薦)

檢視是否載入成功:

  • 進入 /proc/device-tree 目錄下檢視已載入的裝置節點,看看有沒有改動。

1.4 裝置樹外掛的編譯和載入

Linux4.4 以後引入了動態裝置樹,裝置樹外掛被動態的載入到系統中,供核心識別。
裝置樹外掛一般用於只修改新增部分硬體資訊。如只新增 RGB 燈的硬體資訊,就只需要編譯 RGB 燈的 .dts 檔案為 .dtbo 即可。
編譯裝置樹外掛的時候,無需重新編譯整個裝置樹外掛,只需要編譯修改的部分即可。

1.4.1 單獨使用dtc工具編譯

裝置樹和裝置樹外掛都是使用 DTC 編譯工具編譯。
裝置樹編譯後得到的是 .dtb 檔案;
而裝置樹外掛編譯後得到的是 .dtbo 檔案。
使用野火提供的一鍵式編譯工具:

  • 地址:git clone https://gitee.com/Embedfire/ebf-linux-dtoverlays.git
  • 要編譯的裝置樹外掛原始檔放在 ebf-linux-dtoverlays/overlays/ebf 目錄下, 然後回到編譯工具的根目錄 ebf-linux-dtoverlays/ 執行“make”即可。
  • 生成的.dtbo位於 ~/ebf-linux-dtoverlays/output 目錄下。
  • 需要注意的是,如果你在執行“make”後出現報錯,可以嘗試先解除安裝device-tree-compiler(解除安裝命令為:“sudo apt-get autoremove device-tree-compiler”), 重新安裝,然後在“ebf-linux-dtoverlays/basic/fixdep檔案的許可權, 修改許可權命令為:“chmod 777 scripts/basic/fixdep”。

1.4.2 核心dtc工具編譯裝置樹外掛

編譯裝置樹外掛和編譯裝置樹類似,這裡使用核心中的dtc工具編譯編譯裝置樹外掛。
編譯命令:核心構建目錄/scripts/dtc/dtc -I dts -O dtb -o xxx.dtbo xxx.dts

  • 意為編譯 dts 為 dtbo

1.4.3 載入裝置樹外掛

先拷貝裝置樹外掛檔案到開發板上。

1.4.3.1 使用 echo 命令載入

先在 /sys/kernel/config/device-tree/overlays/下建立一個新目錄,名字自定義。
然後將 dtbo 韌體 echopath 屬性檔案中或將 dtbo 的內容 catdtbo 屬性檔案中。

echo xxx.dtbo >/sys/kernel/config/device-tree/overlays/xxx/path
# 或
cat xxx.dtbo >/sys/kernel/config/device-tree/overlays/xxx/dtbo

刪除裝置外掛:rmdir /sys/kernel/config/device-tree/overlays/xxx

1.4.3.2 uboot 載入

不同的板子可能不支援。
修改環境變數檔案即可,進入/boot目錄下 修改 vim uEnv.txt

參考:

相關文章