【Linux】Petalinux驅動開發基礎

基于Petalinux做Linux驅動開發。

部分圖片和經驗來源于網絡,若有侵權麻煩聯系我刪除,主要是做筆記的時候忘記寫來源了,做完筆記很久才寫博客。

 專欄目錄:記錄自己的嵌入式學習之路-CSDN博客


目錄

1    一個完整的Linux系統(針對Zynq)

1.1    PS部分

1.2    PL部分(若沒用到PL就不需要這個部分):

2    Petalinux的內核源碼獲取

3    系統編譯過程

4    NFS掛載根文件系統(Rootfs)的條件

5    交叉編譯

6    驅動模塊的開發

6.1    驅動的運行方式

6.2    file_operations結構體

6.3    驅動模塊的加載和卸載

6.4    一個驅動程序必須有的東西

6.5    字符設備的注冊和注銷

6.6    一個字符設備驅動必須有的東西

6.7    設備號

6.8    內核空間與用戶空間

7    地址映射

7.1    相關函數

8    設備樹

8.1    是什么

8.2    為什么

8.3    設備樹相關概念

8.4    一個典型的設備樹文件

8.5    設備樹節點的基本格式

8.6    節點屬性

8.7    特殊節點

8.8    如何定位一個節點

8.9    內核啟動過程中設備樹的解析過程

8.10    如何添加一個設備樹節點

8.11    如何引用一個節點

8.12    驅動與設備樹交互的函數

8.13    設備樹使用注意事項

9    內核的內存申請

9.1    常見的作用域

9.2    驅動程序中常使用static的原因

9.3    動態內存申請

9.4    kmalloc函數

9.5    kzalloc函數

9.6    vmalloc函數

9.7    devm_kmalloc/devm_kzalloc函數

9.8    devm_kmalloc_array/kmalloc_array

10    驅動與用戶空間的交互函數

10.1    read函數

10.2    write函數

10.3    unlocked_ioctl

10.4    對比

11    ioctl詳解

11.1    ioctl協議的命令組成

11.2    ioctl的宏

11.3    用于輸入輸出的時候需要注意的點

12    Linux開發常用的頭文件

12.1    驅動開發頭文件

12.2    Linux應用開發頭文件

13    Linux驅動開發常用的宏


1    一個完整的Linux系統(針對Zynq)

1.1    PS部分

        五大要素:

(1)fsbl(First Stage Boot Loader) -> zynq_fsbl.elf

        負責初始化PS部分的硬件并加載第二階段的引導加載程序。

(2)uboot(Universal Boot Loader) -> u-boot.elf、boot.scr(boot引導)

        Bootloader 是在操作系統運行之前執行的一段小程序。通過這段小程序,可以初始化硬件設備、建立內存空間的映射表,從而建立適當的系統軟硬件環境,為最終調用操作系統內核做好準備。
        boot.scr文件則是用于給uboot執行和啟動相關的行為的腳本,其中包含了加載內核、設備樹、根文件系統等操作,我個人感覺和uboot中的bootm、bootz等命令類似。而這個文件整體又和uboot中bootargs、bootcmd這兩個環境變量的作用類似。

(3)設備樹文件 -> system.dtb

        一種描述硬件的數據結構。

(4)linux內核 -> image.ub、(zImage)、(uImage)

        內核是Linux系統的核心,負責管理系統的硬件和軟件資源。其中,image.ub可以直接通過uboot上的bootm命令進行Linux的引導啟動,也是放在SD卡BOOT分區就能自動引導的內核鏡像文件;zImage是一種經過gzip壓縮的Linux內核鏡像格式;uImage是U-Boot引導加載程序專用的內核鏡像格式。它是在zImage或Image(不加壓縮的內核鏡像)的基礎上加上一個U-Boot頭部信息(U-BootHeader),使U-Boot能夠識別并加載內核鏡像。

        注:image.ub其實包含了system.bit,zImage,system.dtb三者。

(5)根文件系統 -> rootfs.tar.gz

        根文件系統提供了操作系統運行所需的文件和程序。

1.2    PL部分(若沒用到PL就不需要這個部分):

(1)比特流(Bitstream)文件 -> system.bit

        FPGA的配置文件,用于初始化PL部分的硬件。


2    Petalinux的內核源碼獲取

        進行驅動開發時往往需要Linux的源碼,但在Xilinx的Github中不一定有指定版本(petalinux編譯時的版本)的Linux內核源碼,例petalinux 2023.1的6.1.5版本的內核就沒有打包在那里。

        而petalinux編譯的過程中,默認是會刪除掉其解壓出來的源碼的。要拿到它編譯的源碼,可以修改<plnx_proj>/project-spec/meta-user/conf/petalinuxbsp.conf,加上RM_WORK_EXCLUDE += "linux-xlnx",編譯后可以在<plnx_proj>/build/tmp/work-shared/zynq-generic-7z020/kernel-source中獲取源碼。

        若需要uboot源碼,則加上RM_WORK_EXCLUDE += “u-boot-xlnx”。


3    系統編譯過程

        普通的petalinux開發,最后會將fsbl、比特流文件、uboot、設備樹這四個部分都打包到一個BOOT.BIN的文件中去。常用命令是:

        petalinux-package --boot --fsbl --fpga --u-boot –-force

        若進行Linux驅動開發,設備樹文件、linux內核、根文件系統以及比特流文件都是有可能經常發生改動的,因此要盡量將這些分離出來。

(1)首先,是在編譯時,僅將fsbl和uboot編譯并打包進BOOT.BIN中,因為這兩個文件基本不會變:

petalinux-build -c bootloader        //編譯fsbl
petalinux-build -c u-boot            //編譯uboot
petalinux-package --boot --fsbl --u-boot --dtb no –force//打包兩者進BOOT.BIN,并放過其他成員。

(2)其次,是petalinux-build后修改boot.scr,因為以這樣的方式編譯出來的boot.scr腳本的內容是不對的,具體就是:

        將部分對uImage的操作改為對zImage的操作(這里主要就是不使用image.ub改用zImage了);

        并添加對system.bit的操作(添加關于比特流的內容是因為沒有將比特流打包進BOOT.BIN,過程中生成的boot.sc也因此沒有與其相關的操作,所以要手動添加);

        具體可以看正點原子的教程或看正常用petalinux整合編譯時的boot.scr文件,這里其實就是將其修改為正常boot.scr該有的樣子。最后是將原版改名為boot.cmd.default,并刪掉第一行(包含亂碼的行)再使用以下命令重新生成為boot.scr:

mkimage -c none -A arm -T script -d boot.cmd.default boot.scr

        要重新生成一個boot.scr的理由也很簡單,就是因為boot.scr文件的頭部帶有一些生成的二進制數據,直接修改boot.scr是不行的。

(3)接著,給Linux源碼增加設備樹文件,從上面編譯到的文件中取(路徑為<petalinux項目根目錄>/components/plnx_workspace/device-tree/device-tree),具體需要pcw.dtsi,pl.dtsi,system-top.dts,zynq-7000.dtsi和system-conf.dtsi這五個。將其放置到源碼/arch/arm/boot/dts目錄中并根據需要對system-user.dtsi和該目錄下的MAKEFILE進行修改。

(4)然后,利用make xilinx_zynq_defconfig命令設置內核配置;并使用make -j8編譯內核。該步會在arch/arm/boot中生成所需的內核鏡像文件zImage,在arch/arm/boot/dts生成設備樹二進制文件system-top.dtb。若僅修改了設備樹文件,可以僅編譯它,用命令make dts。

(5)其后,回到petalinux項目中,用petalinux-config -c rootfs命令和petalinux-build -c rootfs命令配置并編譯根文件系統得到rootfs.tar.gz。

(6)最后,在SD卡的BOOT分區,放入文件。用BOOT.BIN,boot.scr,system.bit,zImage,system.dtb五個文件代替普通Petalinux開發的BOOT.BIN,boot.scr和image.ub三個文件的方案:
        BOOT.BIN     :來自步驟(1),是僅包含fsbl和uboot的啟動引導文件;
        boot.scr        :來自步驟(2),是添加比特流操作行為且更改boot內核行為后的boot腳本;
        system.bit    :來自步驟(1),是petalinux項目生成的比特流文件;
        zImage          :來自步驟(4),是Linux內核;
        system.dtb   :來自步驟(4),由system-top.dtb文件改名獲得,是設備樹二進制文件。

(7)最最后,將根文件系統解壓后放入SD卡的rootfs分區:
        rootfs.tar.gz :來自步驟(5),根文件系統的壓縮包。

(附加)使用NFS掛載根文件系統會更好,因為不用經常將SD卡拿出來修改rootfs分區,而boot分區則是進入Linux后隨便改,反正進系統后該分區就沒有實際的用處了。


4    NFS掛載根文件系統(Rootfs)的條件

(1)Ubuntu安裝NFS

sudo apt install nfs-kernel-server

(2)Ubuntu一個創建NFS的掛載路徑

        假設為/home/xxx/workspace/nfs

(3)Ubuntu修改NFS配置文件

sudo vi /etc/exports

        在文件末添加如下內容:

/home/xxx/workspace/nfs *(rw,sync,no_root_squash)

(4)Ubuntu重啟rpcbind服務和NFS服務(其實重啟系統最好)

sudo /etc/init.d/rpcbind restart
sudo systemctl start nfs-kernel-server.service

(5)網絡硬件設置

        Zynq開發板(用網線PS口)與Ubuntu(用網絡橋接)連接到同一路由器上。

(6)Ubuntu網絡軟件設置

        通過ifconfig命令查看Ubuntu的局域網IP地址、網關地址、掩碼等。

(7)Zynq網絡軟件設置

        開機并在倒計時前回車進入uboot,使用dhcp命令自動獲取IP,依次使用以下命令將相關配置寫入開發板,具體IP要根據實際情況更改:

setenv ipaddr 192.168.100.10         //開發板 ip 地址
setenv gatewayip 192.168.100.1       //開發板網關
setenv netmask 255.255.255.0         //開發板 ip 地址掩碼
setenv serverip 192.168.100.2        //ubuntu ip地址

最后使用saveenv命令將其保存。

(8)Zynq boot命令參數設置

        使用以下命令設置boot要執行的參數:

setenv bootargs 'console=ttyPS0,115200 root=/dev/nfs rw nfsroot=192.168.100.2:/home/XXX/RootFS_NFS,nfsvers=3 ip=192.168.100.10:192.168.100.2:192.168.100.1:255.255.255.0::eth0:off'

        最后使用saveenv命令保存。

        至此,設置完畢。后續調試時,只有boot分區需要提前放好在SD卡中,rootfs直接解壓在Ubuntu的/home/xxx/workspace/nfs/rootfs目錄后,打開Zynq開發板就能自動掛載根文件系統。


5    交叉編譯

        當主機平臺(運行編譯器的平臺)和目標平臺(產生的程序將在其上運行的平臺)不兼容時,該過程就叫做交叉編譯。

        petalinux裝好后的編譯環境:

        由none可以看出,這些編譯器是沒有編譯linux的能力的。而Petalinux在構建linux系統過程中會編譯生成linux交叉編譯工具鏈,然后使用其構建 linux 系統,可以在Petalinux工程下使用“find . -name "arm-xilinx-linux-gnueabi-gcc"”命令找到相應的痕跡:

        需要拿到交叉編譯的SDK,需要對某一個petalinux項目執行petalinux-build --sdk,編譯好的sdk安裝腳本是/項目/image/linux中的sdk.sh,安裝到某一地方后安裝程序會提示后續需要配置sdk環境的命令,可以寫個別名放到~/.bashrc中方便使用。

        安裝了SDK后的arm包:


6    驅動模塊的開發

6.1    驅動的運行方式

        (1)編譯進內核;

        (2)編譯成模塊,在內核啟動后使用insmod命令加載驅動模塊;

        一般在調試開發時是編譯成模塊,開發完成后就可以在編譯成模塊和編譯進內核中選擇了。

6.2    file_operations結構體

        位于Linux內核/include/linux/fs.h中,其中fs是file system的縮寫。該結構體是Linux內核驅動操作函數集合。

6.3    驅動模塊的加載和卸載

(1)加載

        insmod:加載指定的.ko模塊,但不能解決模塊的依賴關系,比如 drv.ko依賴 first.ko這個模塊,就必須先使用 insmod命令加載 first.ko這個模塊,然后再加載 drv.ko 這個模塊;

        modprobe(推薦):modprobe 會分析模塊的依賴關系,然后將所有依賴的模塊都加載到內核中,因此 modprobe命令相比 insmod 要智能一些。其次modprobe還有錯誤檢查、錯誤報告等功能;

        注意:modprobe命令默認會去/lib/modules/<kernel-version>目錄中查找模塊,如果沒有的話需要自行創建,如petalinux2020.2就需要創建/lib/modules/5.4.0-150-generic目錄。

        注意:使用modprobe命令前,需先運行depmod建立系統的模塊依賴關系。

(2)卸載

        rmmod(推薦):卸載某個模塊;

        modprobe:卸載某個模塊及其依賴的模塊,而因為該模塊依賴的模塊也有可能在被其他模塊所使用,卸載會出問題,所以不推薦使用modprobe來卸載模塊;

6.4    一個驅動程序必須有的東西

        (1)    驅動入口函數:static int __init xxx_init(void)

        (2)    驅動出口函數:static void __exit xxx_exit(void)

        (3)    指定驅動入口函數的語句:module_init(xxx_init);    // 指定后加載模塊就會自動運行驅動入口函數

        (4)    指定驅動出口函數的語句:module_exit(xxx_exit);   // 指定后卸載模塊就會自動運行驅動出口函數

        (5)    開源許可證類型:MODULE_LICENSE(str)              //添加模塊LICENSE信息(必須)

        (6)    作者信息:MODULE_AUTHOR(str

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/79250.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/79250.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/79250.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JAVA刷題記錄: 遞歸,搜索與回溯

專題一 遞歸 面試題 08.06. 漢諾塔問題 - 力扣&#xff08;LeetCode&#xff09; class Solution {public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {dfs(A, B, C, A.size());}public void dfs(List<Integer> a, List<In…

YOLOv11改進:利用RT-DETR主干網絡PPHGNetV2助力輕量化目標檢測

這里寫自定義目錄標題 YOLOv11改進&#xff1a;利用RT-DETR主干網絡PPHGNetV2助力輕量化目標檢測1. 介紹2. 引言3. 技術背景3.1 YOLOv11概述3.2 RT-DETR與PPHGNetV23.3 相關工作 4. 應用使用場景5. 詳細代碼實現5.1 環境準備5.2 PPHGNetV2主干網絡實現5.3 YOLOv11與PPHGNetV2集…

WPF之Button控件詳解

文章目錄 1. 引言2. Button控件基礎Button類定義 3. Button控件的核心屬性3.1 Content屬性3.2 IsDefault屬性3.3 IsCancel屬性3.4 其他常用屬性 4. 按鈕樣式與模板自定義4.1 簡單樣式設置4.2 使用Style對象4.3 觸發器使用4.4 使用ControlTemplate完全自定義4.5 按鈕視覺狀態 5.…

【Java】2025 年 Java 學習路線:從入門到精通

文章目錄 一、Java基礎階段(4-8周)1. 開發環境搭建2. 核心語法基礎3. 面向對象編程(OOP)4. 核心類庫二、Java進階階段(6-10周)1. JVM深度理解2. 并發編程3. 新特性掌握4. 設計模式三、開發框架與中間件(8-12周)1. Spring生態2. 持久層框架3. 常用中間件四、項目實戰階段…

虛幻引擎入門筆記

【虛幻5】UE5新手入門嘗試 虛幻引擎的基礎設置 1.驗證-當文件誤刪的時候&#xff0c;對其進行驗證&#xff0c;可以恢復。 2.虛幻引擎極其強大&#xff0c;可以實現多種復合技能&#xff0c;所在創建項目頁面可以看見不只是創建游戲的項目 3.更改虛幻引擎默認的緩存地址。有些…

【PostgreSQL數據分析實戰:從數據清洗到可視化全流程】1.1 數據庫核心概念與PostgreSQL技術優勢

&#x1f449; 點擊關注不迷路 &#x1f449; 點擊關注不迷路 &#x1f449; 點擊關注不迷路 文章大綱 深度解析PostgreSQL核心架構與技術優勢&#xff1a;從數據庫原理到實戰場景1.1 數據庫核心概念與PostgreSQL技術優勢1.1.1 關系型數據庫核心架構解析1.1.1.1 數據庫系統的底…

詳解SLAM中的李群和李代數(上)

1 概述 最近閱讀高翔大神的《視覺SLAM十四講》這本書&#xff0c;感覺整本書寫的非常的平實&#xff0c;用非常接地氣的語言毫無保留的介紹了視覺SLAM的相關知識&#xff0c;非常值得一讀。不過&#xff0c;在第4章出現的李群和李代數的相關概念就有點令人難以費解了。其實這段…

libevent庫詳解:高性能異步IO的利器

目錄 一、libevent 簡介 主要特點&#xff1a; 二、事件模型原理 1. event_base 2. event 3. evconnlistener&#xff08;TCP監聽器&#xff09; 4. bufferevent 簡化流程如下&#xff1a; 三、libevent 使用示例 1. 創建事件主循環 2. 創建監聽器&#xff08;TCP&a…

從 “零” 做個開源音樂軟件“SteadyBeat”吧!<1> 準備

換換腦子&#xff0c;做個音樂軟件&#xff0c;根據調性、和弦走向&#xff08;情感&#xff09;、節拍、速度等需求&#xff0c;結合AI和一眾工具&#xff0c;自動生成伴奏、Solo等&#xff0c;有點像庫樂隊&#xff01;自己平時也用得著&#xff0c;暫時取名叫《SteadyBeat》…

npm error code CERT_HAS_EXPIRED

npm error code CERT_HAS_EXPIRED 歡迎來到我的主頁&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就職于醫療科技公司&#xff0c;熱衷分享知識&#xff0c;武漢城市開發者社區主理人 擅長.net、C、python開發&#xff0c; 如果遇到技術問題&#xff0c;即可私…

數字世界的“私人車道“:網絡切片如何用Python搭建專屬通信高速路?

數字世界的"私人車道"&#xff1a;網絡切片如何用Python搭建專屬通信高速路&#xff1f; 2024年6月&#xff0c;中國移動宣布在浙江某智能工廠完成全球首個"5G工業網絡切片"規模商用——這條為生產線定制的"數字專屬車道"&#xff0c;將設備控制…

VSCode Verilog編輯仿真環境搭建

VSCode Verilog環境搭建 下載Iverilog安裝Iverilog驗證安裝VS Code安裝插件 下載Iverilog 官網下載Iverilog 安裝Iverilog 一定要勾選這兩項 建議勾選這兩項 驗證安裝 運行Windows PowerShell輸入命令&#xff1a;iverilog輸入命令&#xff1a;Get-Command gtkwave …

C++ - 數據容器之 list(創建與初始化、元素訪問、容量判斷、元素遍歷、添加元素、刪除元素)

一、創建與初始化 引入 <list> 并使用 std 命名空間 #include <list>using namespace std;創建一個空 list list<int> my_list;創建一個包含 5 個元素&#xff0c;每個元素初始化為 0 的 list list<int> my_list(5);創建一個包含 5 個元素&#xf…

自動化測試項目1 --- 嘮嗑星球 [軟件測試實戰 Java 篇]

目錄 項目介紹 項目源碼庫地址 項目功能測試 1.自動化實施步驟 1.1 編寫測試用例 1.2 自動化測試腳本開發 1.2.1 配置相關環境, 添加相關依賴 1.2.2 相關代碼編寫 2. 自動化功能測試總結 2.1 彈窗的解決相關問題 2.2 斷言的使用和說明 2.3 重新登錄問題 項目性能…

Codeforces Round 1022 (Div. 2)(ABC)

A. Permutation Warm-Up 翻譯&#xff1a; 對于長度為 n 的排列 p&#xff0c;我們定義函數&#xff1a; 給你一個數 n。你需要計算函數 f(p) 在考慮從 1 到 n 的所有可能的數字排列時&#xff0c;可以取多少個不同的值。 思路&#xff1a; 按序排列時和為0&…

數據結構------C語言經典題目(6)

1.數據結構都學了些什么&#xff1f; 1.基本數據類型 算數類型&#xff1a; char&#xff08;字符&#xff09;、int&#xff08;整數&#xff09;、float&#xff08;單精度浮點數&#xff09;、double&#xff08;雙精度浮點數&#xff09;等。 枚舉類型&#xff1a; enum…

如何封裝一個線程安全、可復用的 HBase 查詢模板

目錄 一、前言&#xff1a;原生 HBase 查詢的痛點 &#xff08;一&#xff09;連接管理混亂&#xff0c;容易造成資源泄露 &#xff08;二&#xff09;查詢邏輯重復&#xff0c;缺乏統一的模板 &#xff08;三&#xff09;多線程/高并發下的線程安全性隱患 &#xff08;四…

【中間件】bthread_基礎_TaskControl

TaskControl 1 Definition2 Introduce**核心職責** 3 成員解析**3.1 數據結構與線程管理****3.2 任務調度與負載均衡****3.3 線程停放與喚醒&#xff08;ParkingLot&#xff09;****3.4 統計與監控** 4 **工作流程**5 **設計亮點**6 **使用場景示例**7 **總結**8 學習過程中的疑…

win11 終端 安裝ffmpeg 使用終端Scoop

1、安裝scoop (Windows 包管理器) Set-ExecutionPolicy RemoteSigned -Scope CurrentUser iwr -useb get.scoop.sh | iex 2、使用scoop來安裝ffmpeg scoop install ffmpeg 3、測試一下ffmpeg&#xff0c;將Mp3文件轉為Wav文件 ffmpeg -i A.mp3 A.wav 然后我們就看到A.wav生成…

力扣838.推多米諾隨筆

“生活就像海洋&#xff0c;只有意志堅強的人&#xff0c;才能到達彼岸。”—— 馬克思 題目 n 張多米諾骨牌排成一行&#xff0c;將每張多米諾骨牌垂直豎立。在開始時&#xff0c;同時把一些多米諾骨牌向左或向右推。 每過一秒&#xff0c;倒向左邊的多米諾骨牌會推動其左側…