1. petalinux 指令筆記
包含非國產zynq和國產zynq生成鏡像流程
1.1 鏡像文件構成方式
使用 u-boot 中的 mkimage 工具,可以將 zImage 制作為 uImage。uImage 是 u-boot 專用的鏡像文件,它在 zImage 的前邊加上一個 64 Byte 的“頭”,描述了該內核的版本、加載位置、生成時間、大小等信息,除此以外和 zImage 沒有區別
image.ub文件
1.zImage, 內核鏡像
2.rootfs, 根文件系統
3.system.dtb, 設備樹
BOOT.BIN
1. zynq_fsbl.elf, fsbl鏡像-上電啟動的第一個程序,后面才啟動uboot裸機程序
2. u-boot, 鏡像
3. system.bit, PL端的 bit文件
1.2 常用命令
petalinux-create --type project --template zynqMP --name zynqMP_nvme ## 在當前目錄下生成 zynqMP_nvme 項目
petalinux-config --get-hw-description [./] ## 包含 .hdf 或者是 .dsp的目錄
petalinux-config -c kernel ## 配置內核
petalinux-config -c rootfs #配置文件系統
petalinux-build ## 構建u-boot
## 打包: 參數說明, 可以根據 petalinux-package --boot --help 查看各個參數說明
## --boot意思打包BOOT.BIN, --fsbl 指向zynq_fsbl.elf, --fpga指向bitstream文件system.bit, --u-boot 指向 u-boot.elf, --kernel 指向image.ub, --force意思生成文件覆蓋舊文件
petalinux-package --boot --fsbl --fpga --u-boot --force ##(SD卡啟動)
petalinux-package --boot --fsbl --fpga --u-boot --kernel --force ##(FLASH啟動)
1.3 配置nvme
- 配置內核
petalinux-config -c kernel
Check: Bus options->PCI support should
Check: Bus options->PCI support->Message Signaled Interrupts (MSI and MSI-X)
Check: Bus options->PCI support->Enable PCI resource re-allocation detection
Check: Bus options->PCI support->PCI host controller drivers->Xilinx AXI PCIe host bridge support
Enable: Device Drivers->Block devices->NVM Express block device
- 配置根文件系統
petalinux-config -c rootfs
Filesystem Packages->console/utils->pciutils->pciutils
Filesystem Packages->base->util-linux->util-linux
Packages->base->util-linux->util-linux-blkid
Packages->base->util-linux->util-linux-fdisk
Packages->base->util-linux->util-linux-mkfs
Packages->base->util-linux->util-linux-mount
Packages->base->e2fsprogs->e2fsprogs
Packages->base->e2fsprogs->e2fsprogs-mke2fs
1.4 uboot下 啟動image方式
uboot主要就是用來加載內核鏡像等相關文件, 以下指令都在printenv
中可以查看到相關指令的使用方式
1.4.1 從flash中啟動
flash 通過地址讀取, 這個地址是提前寫入的, 通過網絡或者sd卡將鏡像讀取到內存,然后直接持久化到flash中,不過需要設置相關環境
sf probe #初始化flash
sf read 0x1000000 0x02394a80 0x1600000 #從flash中讀取指定長度的系統文件到內存0x1000000中,這里讀取的是 image.ub
bootm 0x1000000 # 從指定內存中啟動程序
1.4.2 從sd卡的FAT32分區啟動
mmc list #查看mmc設備(會顯示當前sd卡的分區)
mmc dev [mmc序號] [分區] #mmc序號可以通過 mmc list 查看
mmcinfo #查看當前mmc設備詳細信息
fatload mmc 0 0x1000000 image.ub #將某個文件從mmc設備中讀取到內存 0x1000000
md 0x1000000 [長度] #查看內存值是否讀取正確
bootm 0x1000000 #然后通過 bootm從內核加載內核
1.5 tftp 啟動
setenv serverip 192.168.1.15 ##設置ftfp服務器的地址
md 0x1000000 # 查看內存地址 0x1000000 是否有數據,如果有可以換個地址
tftpboot 0x1000000 image.ub # 將image.ub 從服務器加載到地址為0x1000000的內存中
bootm 0x1000000 # 啟動鏡像
1.6 將程序固化到flash中
//將內存地址mem_addr開始起后面 data_len 的數據長度, 寫入flash偏移 flash_offset, flash_offset也可以理解flash的地址
sf write [mem_addr] [flash_offset] [data_len]
1.7 petalinux 免登錄
petalinux-config --get-hw-description [./]
Yocto Settings->Enable Debug Tweaks # 選中該選項
1.8 jtag和串口沖突,導致串口使用不了
petalinux-config -c kernel
CPU Power Management->CPU Idle->CPU idle PM support ##取消該選項
1.9 進口zynq, ARM linux 驅動開發,對設備樹和kernel,rootfs的生成筆記
# 1.使用petalinux 創建工程並編譯配置文件生成BOOT.BIN
petalinux-create -t project --template zynq -n ALIENTEK-ZYNQ
cd ALIENTEK-ZYNQ
petalinux-config --get-hw-description ../hdf/ #選擇以下配置選擇存放 .hdf 的存放目錄
> 1. image storage media(選擇sd) # 配置設備樹從image.ub獨立開來, 從sd卡中啟動
> 2. Root filesystem type (選擇sd) # 配置根文件系統放到sd卡的EXT4分區中
petalinux-build -c u-boot #會重新生成設備樹, 如果生成不了,可以直接用 petalinux-build 全部編譯,在image/linux *.dtsi和*.dts
petalinux-package --boot --fsbl --u-boot --force #生成BOOT.BIN,只包含zynq_fsbl.elf 和 u-boot.elf(平常還會包含system.bit)
# 2. 根據device-tree倉庫生成設備樹文件(和petalinux-build -c uboot相比, 該方法速度快,不需要重新編譯BOOT.BIN)
2.1 下載設備樹倉庫: https://github.com/Xilinx/device-tree-xlnx/releases, 下載 xilinx-v2018.3
2.2 解壓到 /home/hgx/tools/liunx_project/tools/device-tree
2.3 輸入指令 hsi,進入 hsi指令行,並輸入以下指令
open_hw_design /home/hgx/tools/liunx_project/hdf_dir/navigator_7010_wrapper.hdf
set_repo_path /home/hgx/tools/liunx_project/tools/linux-2018.3/linux-xlnx-xilinx-v2018.3
create_sw_design device-tree -os device_tree -proc ps7_cortexa9_0
generate_target -dir /home/hgx/tools/liunx_project/tools/dts #最后生成的設備樹相關文件都在該目錄下,可以自己指定
exit #退出
# 3. 使用官方2018.3版本的linux編譯kernel
3.1 下載源碼: https://github.com/Xilinx/linux-xlnx/tags, 並解壓在linux目錄下
3.2 將前面用設備樹倉庫生成的設備樹: /home/hgx/tools/liunx_project/tools/dts,目錄下的 pcw.dtsi, pl.dtsi, system-top.dts,zynq-7000.dtsi 直接拷貝到 arch/arm/boot/dts下
3.3 對 system-top.dts 修改,修改內容如下有介紹
3.4 在 arch/arm/boot/dts 目錄下的 Makefile, 中修改如下
zynq-zybo.dtb \
system-top.dtb #(新添加的)
3.5 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- xilinx_zynq_defconfig #根據defconfig配置.config,"./arch/arm64/configs/defconfig->./.config"
3.6 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage -j8 #編譯內核zImage,在目錄arch/arm/boot/下
3.7 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- system-top.dtb -j8 #編譯設備樹
# 4.編譯 rootfs
4.1 在1中生成的petalinux 項目中,使用指令 petalinux -c rootfs
>在debug-tweaks 選擇賬號登錄
4.2 petalinux-build -c rootfs
# 5.拷貝SD卡,並啟動
5.1 將SD卡分區,如下,使用指令 sudo fdisk /dev/sdb 制作分區,並將兩個分區掛載
Disk /dev/sdb: 29.1 GiB, 31293702144 bytes, 61120512 sectors
Device Boot Start End Sectors Size Id Type
/dev/sdb1 * 2048 206847 204800 100M c W95 FAT32 (LBA)
/dev/sdb2 206848 61120511 60913664 29G 83 Linux
5.2 將如下文件拷貝到sd卡的FAT分區
arch/arm/boot/zImage
arch/arm/boot/dts/system-top.dtb
images/linux/system.bit
images/linux/BOOT.BIN
5.3 然后將根文件系統解壓到sd卡的 EXT4分區
sudo tar -xvf images/linux/rootfs.tar.gz -C ${掛載的EXT4盤目錄}
5.4 將卡查到開發板上
# 6. 修改 env環境,設置自動啟動
env default -a
setenv bitstream_load_address 0x100000
setenv bitstream_image system.bit
setenv bitstream_size 0x300000
setenv kernel_img zImage
setenv dtbnetstart 0x2000000
setenv netstart 0x2080000
setenv cp_dtb2ram 'mmcinfo && fatload mmc 0:1 ${dtbnetstart} ${dtb_img}'
setenv default_bootcmd 'if mmcinfo; then run uenvboot; echo Copying Linux from SD to RAM... && load mmc 0 ${bitstream_load_address} ${bitstream_image} && fpga loadb 0 ${bitstream_load_address} ${bitstream_size} && run cp_kernel2ram && run cp_dtb2ram && bootz ${netstart} - ${dtbnetstart}; fi'
saveenv #將環境變量保存
boot/reset #啟動開發板,然后會自動進入系統
最后修改的 system-top.dts
/*
* CAUTION: This file is automatically generated by Xilinx.
* Version: HSI
* Today is: Thu Dec 15 17:28:45 2022
*/
/dts-v1/;
#include "zynq-7000.dtsi"
#include "pl.dtsi"
#include "pcw.dtsi"
/ {
model = "Alientek ZYNQ Development Board";
chosen {
bootargs = "console=ttyPS0,115200 earlyprintk root=/dev/mmcblk0p2 rw rootwait";
stdout-path = "serial0:115200n8";
};
aliases {
ethernet0 = &gem0;
i2c0 = &i2c2;
i2c1 = &i2c0;
i2c2 = &i2c1;
serial0 = &uart0;
serial1 = &uart1;
spi0 = &qspi;
};
memory {
device_type = "memory";
reg = <0x0 0x20000000>;
};
};
&gem0 {
local-mac-address = [00 0a 35 00 1e 53];
};
&qspi {
#address-cells = <1>;
#size-cells = <0>;
flash0: flash@0 {
compatible = "n25q512a","micron,m25p80";
reg = <0x0>;
#address-cells = <1>;
#size-cells = <1>;
spi-max-frequency = <50000000>;
partition@0x00000000 {
label = "boot";
reg = <0x00000000 0x00500000>;
};
partition@0x00500000 {
label = "bootenv";
reg = <0x00500000 0x00020000>;
};
partition@0x00520000 {
label = "kernel";
reg = <0x00520000 0x00a80000>;
};
partition@0x00fa0000 {
label = "spare";
reg = <0x00fa0000 0x00000000>;
};
};
};
2 國產zynq 對 FSBL、設備樹、uboot、系統鏡像生成流程
2.1 設備樹 和 FSBL的生成
1.新建 procise 工程
2.點擊 "Create Block Design" -> 輸入新創建名 "system" -> 回車
3.在 tab頁面"system.bd" 處右擊 "Add IP" -> 選中 "processing_system7:1.0" -> 回車添加即可
4.雙擊"IP核"設置對應的外設管腳, 一般有 "flash", "以太網", "uart"等。
5.在 source 標簽欄下右擊 "system_i" -> 選擇 "Generate Output Products" -> 雙擊即可
6.在工具欄中點擊 "PSOC" -> 選中 "Repositories" -> 其中 "Local Repositorie" 中只能有一個倉庫 -> 點擊退出
7.在 source 標簽欄下右擊 "system_i" -> 選擇 "Export Hardware ..." -> 選擇 "FSBL" 和 "DeviceTree"
8.然后打開項目的位置, 打開"../SDK/system_platform"
9.然后雙擊 "system_platform.eww", 然后, 用IAR 編譯"Make", 生成 "FSBL.out" 即可生成 FSBL程序
10.其中DeviceTree就是生成的設備樹, 直接拷貝到linux環境下用於編譯 uboot
補充:
11.如果JTAG的線是在PL連的話, 第一次燒寫使用IAR需要線燒寫bit
12.在步驟3中, 如果是從 vivadio 導入的文件 "system.bd" 和 "system_processing_system7_0_0.xci", 就可以不用去自己設置IP核
2.2 設備樹的編譯 和 uboot 生成
1.將文件 "FMQL-Linux-SDK_20201022.tar.bz2" 拷貝到 具有"petalinux" 環境的linux系統, 然后解壓
2.將生成設備樹的步驟"10"中,將生成的設備樹拷貝到linux中
3.然后 進入"FMQL-Linux-SDK_20201022",輸入"source env.sh"
4.編輯 "SDK_20201022/device-tree/xlnx-dts/openhdf.sh" 文件第"8"行, 添加"petalinux"安裝目錄
5.輸出指令 "./build.sh --hw /home/{user_name}/Downloads/DeviceTree/ --nofpga dtb", 其中 "--nofpga" 是忽略"PL"部分, 如果包含fpga部分,則需要輸入 "./build.sh --hw /home/{user_name}/Downloads/DeviceTree/ --hdf xxx/xxx.hdf dtb"
6.就會生成在"FMQL-Linux-SDK_20201022/images"目錄下生成 "system-top.dtb"
7.然后進入"FMQL-Linux-SDK_20201022/u-boot-2018.07-fmsh"目錄下
8.輸入指令 "make fmql_common_defconfig" 生成 ".config" 配置文件
9.輸入指令 "make EXT_DTB=../images/system-top.dtb -j4" 編譯 "uboot"
10.在 "FMQL-Linux-SDK_20201022/u-boot-2018.07-fmsh"目錄中會出現 "u-boot.bin" 和 "u-boot.elf" 文件, "u-boot.bin" 用於制作 "BOOT.bin"
2.3 根文件系統的生成
1.進入"FMQL-Linux-SDK_20201022/buildroot-2018.02.3" 目錄下
2.輸入"make fmsh_tiny_defconfig" 生成 ".config"文件
3.輸入"make busybox-dirclean" 和 "make initscripts-dirclean" 清除之前編譯的
4.然后輸入 "make" 進行編譯
5.編譯完成后 "FMQL-Linux-SDK/buildroot-2018.02.3/output/images"目錄下將生成多種格式的 "rootfs" 文件
6. 進入目錄 output/images
mkdir rootfs && cd rootfs
sudo cpio -i < ../rootfs.cpio #使用root解壓 rootfs.cpio
sudo find . | sudo cpio -H newc -o| gzip -9 > ../rootfs.cpio.gz #使用root權限打包
cd ../ && sudo cp roofs.cpio.gz ../../../images
7. "rootfs.cpio.gz" 將用於制作 "image.ub"
2.4 uImage 系統鏡像生成
1)Image 內核鏡像文件
2)zImage 壓縮的內核鏡像文件
3)uImage 是 u-boot 專用鏡像, 相比 zImage 多了 64Byte 的頭,用來描述內核版本,加載位置, 生成時間,大小位置等信息
1.進入 "FMQL-Linux-SDK_20201022/ linux-4.14.55-fmsh" 目錄中
2.輸入 "make fmsh_fmql_defconfig" 生成 ".config" 配置文件, 然后輸入 "make -j4" 開始執行編譯
3.生成的鏡像位於 "arch/arm/boot" 目錄下, "ZImage" 格式的鏡像用於制作 "image.ub"
2.5 image.ub 鏡像的生成
1.選擇制作的類型, 編輯"FMQL-Linux-SDK_20201022/env.sh" 中的 "IMAGE_TYPE"為 "ramdisk"
2.需要上述生成的文件"system-top.dtb","zImage","rootfs.cpio.gz","Image" 拷貝到目錄"FMQL-Linux-SDK_20201022/images" 下
3."FMQL-Linux-SDK_20201022" 目錄下, 輸入 "./build.sh image", 開始制作 "image.ub" 鏡像
4."FMQL-Linux-SDK_20201022/image" 目錄下會生成 "image.ub"文件
2.6 BOOT.bin 生成
BOOT.bin
是 FSBL.out
, system.bit
, u-boot
/u-boot.elf
合並而成, 燒進去之后, 直接燒鏡像 "image.ub" 即可
1.打開 "Star Procise", 點擊 工具欄中的 "PSOC" -> "Create Boot Image"
2.點擊add, 添加"FSBL.out", "system.bit"(如果有PL需要加), "u-boot"/"u-boot.elf", 然后點擊 "Create Image" 即可生成
碰見的問題
1. uboot下和liunx環境下, flash 識別不到和分區創建
通過電路圖可知, "flash" 存儲器型號為 XM25QH256CXIQT08S
, 大小為 250Mb
(32MB
),
通過設備樹修改, 將flash 最后的4MB大小創建分區, 用於系統掛載,存放文件
在 "uboot" 源碼下 u-boot-2018.07-fmsh/drivers/mtd/spi/spi_flash_ids.c
中 spi_flash_ids[]
數組中添加對應flash型號
在linux-4.14.55-fmsh/drivers/mtd/spi-nor/spi-nor.c
中spi_nor_ids[]
數組中添加對應flash id
eg: { "n25q256abcd", INFO(0x204019, 0, 64*1024, 512, SECT_4K) },
, 其中 0x204019
需要在手冊中查看
2. 自啟動腳本設置
在 buildroot-2018.02.3/package/initscripts/init.d
目錄下創建腳本
#!/usr/bin/env sh
echo -e "---------------------------\n"
# 掛載盤
# 執行掛載盤中的腳本或者程序
然后在 重新走下 2.3 步驟,生成跟文件系統
petalinux 驅動開發筆記
設備號
- 設備號的類型為 unsigned int, 其中高12bit為主設備號(0~4095), 低20位為 次設備號
#define MINORBITS 20
#define MINORMASK ((1U << MINORBITS) - 1)
#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))
#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))
#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))
宏 MINORBITS 表示次設備號位數,一共是 20 位。
宏 MINORMASK 表示次設備號掩碼。
宏 MAJOR 用於從 dev_t 中獲取主設備號,將 dev_t 右移 20 位即可。
宏 MINOR 用於從 dev_t 中獲取次設備號,取 dev_t 的低 20 位的值即可。
宏 MKDEV 用於將給定的主設備號和次設備號的值組合成 dev_t 類型的設備號。
2. 設備號分配, 靜態分配和動態分配
靜態設備容易起沖突, 在注冊前可以動態申請設備號
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name); //申請動態設備號
void unregister_chrdev_region(dev_t from, unsigned count); //釋放設備號
LICENSE 和作者信息
LICENSE 是必須添加的
MODULE_LICENSE("GPL"); //LICENSE 采用 GPL 協議。
MODULE_AUTHOR("alientek");
printk輸出級別
include/linux/kern_levels.h 中包含了 prink輸出的級別
include/linux/printk.h CONSOLE_LOGLEVEL_DEFAULT 默認輸出級別
編譯驅動並加載
1. 設置 Makefile
KERN_DIR:=/home/hgx/tools/liunx_project/tools/linux-2018.3/linux-xlnx-xilinx-v2018.3
obj-m := driver_char.o #要編譯的driver_char.c文件
all:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR)=`pwd` clean
2. 加載 驅動
- 將 xx.ko 直接拷貝到開發板中的linux中
- 然后使用
insmod/modprobe xxx.ko
加載驅動 cat /proc/devices
查看設備號`mknod /dev/chrdevbase c 200 0
根據設備號創建節點文件- 在ubuntu中編寫用戶態代碼對
/dev/chrdevbase
文件進行讀寫測試, 並使用arm-linux-gnueabihf-gcc xxx.c -o xxx
- 然后將編譯完的文件直接拷貝到開發板上直接 運行即可