【linux專案】lichee nano linux燒寫

李柱明發表於2021-12-27


前言

lichee_nano 主控晶片為全志 FC1001S。

本筆記暫時以 lichee nano 為例子,以後可能會直接適配各類 FC1001S 的板子。

注意:使用 lichee nano 板子和 lichee 提供的映象時,需要注意這個板子的 flash 晶片型號,必要時需要修改驅動。

李柱明部落格:https://www.cnblogs.com/lizhuming/p/15487208.html

參考:

安裝交叉編譯鏈

arm-linux-gnueabi

  • 可以自己安裝需要的版本。
  • 也可以參考下面例子:
# 此處為獲取7.2.1版本,您可獲取其他版本或者通過連結直接下載
wget http://releases.linaro.org/components/toolchain/binaries/7.2-2017.11/arm-linux-gnueabi/gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi.tar.xz

tar -vxJf gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi.tar.xz
sudo cp -r ./gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi /opt/

sudo vim /etc/bash.bashrc

# 在檔案末尾 新增以下內容
PATH="$PATH:/opt/gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi/bin"
# 新增完畢

# 使路徑生效
source /etc/bash.bashrc

安裝好交叉編譯鏈後可用命令 arm-linux-gnueabi-gcc -v 測試是否安裝成功。注意自己的安裝使用者。

搭建 SPI FLASH 燒錄環境

安裝好編譯根據鏈後還需要安裝燒錄韌體工具。這裡使用 sunxi-tools

# 0. 如果無安裝git 首先安裝git
sudo apt-get install git

# 1. 拉取 sunxi-tools 這個庫
git clone -b f1c100s-spiflash https://github.com/Icenowy/sunxi-tools.git

# 2.進行安裝
cd sunxi-tools
make && sudo make install

# 3. 錯誤處理
# 3.1 如果出現 fatal error: libusb.h: No such file or directory 錯誤
sudo apt-get install libusb-1.0-0-dev
# 3.2 fel.c:32:18: fatal error: zlib.h: 沒有那個檔案或目錄
sudo apt-get install  zlib-devel


# 4. 不出意外 現在已經安裝成功, 可以使用這個軟體進行燒寫。常用的命令有如下幾個
# 4.1 檢視晶片是否開啟了下載模式, 如果出現晶片資訊既可以燒錄
sudo sunxi-fel ver

# 4.2 燒錄到 flash
sudo xunxi-fel -p spiflash-write [燒錄的地址] [燒錄的檔案]

# 4.3 燒錄到 記憶體中
sudo xunxi-fel -p write [燒錄的記憶體地址] [燒錄的檔案]

讓晶片進入燒寫模式

為了讓晶片能接收燒寫韌體,可讓晶片進入 fel 模式。

  • 原理:當 flash 中無 引導資料或者無法找到 flash 晶片時, 便自動進入 fel 模式
  • 有一下兩種方法:
    1. 短接 flash 的 1、4 兩腳,重新上電,讓晶片找不到 flash,上電後鬆開短接,即可重新進入 fel 模式。
    2. 使用 U-boot 刪除 flash 中的引導資料:
# 在 u-boot 中使用如下指令進行刪除資料
# 1. 切換到 flash, 其中 0 為選擇的flash,50000000 為速度。官方文件這裡有錯誤。注意!
sf probe 0 50000000

# 2. 擦除flash, 為什麼擦除這段地址,請檢視spiflash編譯章節
sf erase 0 0x10000

# 3. 重啟
reset

# 4. 使用 sunxi-fel ver 即可找到晶片
sudo sunxi-fel ver
AWUSBFEX soc=00001663(F1C100s) 00000001 ver=0001 44 08 scratchpad=00007e00 00000000 00000000

sunxi 燒寫命令

  1. 確認是否進入 fel 模式命令:sudo sunxi-fel ver
  2. 燒錄命令:sudo sunxi-fel -p spiflash-write [燒錄的地址] [燒錄的檔案]

u-boot 裁剪

拉取 u-boot 原始碼

# 1.  使用git 拉取 u-boot, 這裡可以使用加速
git clone https://github.com/Lichee-Pi/u-boot.git

# 2. 檢視分支,並切換到對應分支
git branch -a
git checkout nano-v2018.01

# 3. 進行配置
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- licheepi_nano_spiflash_defconfig

配置 u-boot

按需裁剪,一下為參考:

  • 瞭解下下面的 bootcmd 引數。就是驅動核心前執行的命令。一般主要做資料拷貝&執行啟動,如把裝置樹、kernel 拷貝到記憶體控制器 RAM 中。
# 1. 進行視覺化配置, 進入配置頁面
make ARCH=arm menuconfig

# 1.1 如何出現錯誤,安裝如下的包
sudo apt-get install libncurses5-dev libncursesw5-dev

# 2. 如果使用LCD,修改LCD選項
ARM architecture
	Enable graphical uboot console on HDMI, LCD or VGA -> Y
	LCD panel timing details -> x:800,y:480,depth:18,pclk_khz:33000,le:87,ri:40,up:31,lo:13,hs:1,vs:1,sync:3,vmode:0
	# 如果為 480*272 螢幕
	x:480,y:272,depth:18,pclk_khz:10000,le:42,ri:8,up:11,lo:4,hs:1,vs:1,sync:3,vmode:0

	LCD panel backlight pwm pin -> PE6 # 具體看原理圖

# 3. 修改 boot arguments ,傳輸到linux的引數
Enable boot arguments -> y
	Boot arguments ->  console=ttyS0,115200 panic=5 rootwait root=/dev/mtdblock3 rw rootfstype=jffs2
  
# 4. 修改bootcmd,啟動linux命令。可以具體瞭解一下 bootcmd 程式碼的含義,其中拷貝資料啟動linux 
Enable a default value for bootcmd -y
	bootcmd -> sf probe 0 50000000; sf read 0x80c00000 0x100000 0x4000; sf read 0x80008000 0x110000 0x400000; bootz 0x80008000 - 0x80C00000

# 5. 儲存退出

檢查 flash 驅動

  • 新增自己的 FLASH 晶片驅動。
# 1. 在程式碼編輯器中 開啟 ./drivers/mtd/spi/spi_flash_ids.c

# 2. 在 170 行左右新增如下程式碼
{"xt25f128b",	   INFO(0x0b4018, 0x0,	64 * 1024,   256, RD_FULL | WR_QPP | SECT_4K) },

# 3. 儲存退出

編譯、燒寫 u-boot

編譯:

# 編譯程式碼
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j11

# 如果最後出現下面語句,編譯成功
 BINMAN  u-boot-sunxi-with-spl.bin

# 錯誤處理,scripts/Makefile.build:425: recipe for target 'scripts/dtc/pylibfdt' failed
sudo  apt-get install swig python-dev python3-dev

編譯成功的檔案在 u-boot 目錄下的,u-boot-sunxi-with-spl.bin 。 把他們燒寫到記憶體或者 flash:

# 燒寫到flash中
sudo sunxi-fel -p spiflash-write 0 u-boot-sunxi-with-spl.bin

# 燒寫到 sram 中,在測試的時候使用(掉電不保護)
sudo sunxi-fel uboot u-boot-sunxi-with-spl.bin

驗證:

# 測試 flash 是否成功,如果出現下面程式碼既成功
sf probe 0 50000000
SF: Detected xt25f128b with page size 256 Bytes, erase size 4 KiB, total 16 MiB

# 測試 讀取 
boot

linux 裁剪

獲取 linux 原始碼

目前獲取 uboot 和 linux 原始碼都是獲取 lichee 或者全志官方推薦的。

# 1. 因為 linux太大了,建議只拉取單個分支. 可以使用加速
git clone --depth=1 -b f1c100s-480272lcd-test https://github.com/Icenowy/linux.git

# 2. 下載 .config 檔案,放到原始碼的目錄下,如果檔名稱有變化。改為 .config

替換 .config 檔案:.config

git 拉取有時速度很慢,建議做如下配置:

sudo vim /etc/hosts
# 新增下面兩行
192.30.253.112  github.com
151.101.73.194 github.global.ssl.fastly.net
# 新增完成
# 可自行通過dns檢測網站檢測github.global.ssl.fastly.net,更換為更快的ip地址

配置 linux

# 1. 圖形化配置
make ARCH=arm menuconfig

# 2. 配置 spiflash
Device Drivers
	SPI support
		Allwinner A10 SoCs SPI controller ->n # 不選擇
		Allwinner A31 SPI Controller -> y

# 3. 配置 MTD
Device Drivers
	Memory Technology Device (MTD) support
		Command line partitioning table parsing -> y
		Caching block device access to MTD devices  -> y

# 4.新增 File systems
File systems
	Miscellaneous filesystems
		Journalling Flash File System v2 (JFFS2) support -> y
		# 下面全選

# 5. 儲存退出


# 注意, 要把配置的選項選擇為 * 而不是 M

配置裝置樹

  • 新增 flash 驅動,需要檢視板子使用的 flash 晶片:

    # 1. 開啟 ./drivers/mtd/spi-nor/spi-nor.c 1186行. 新增如下程式碼. 對flash支援
    { "xt25f128b", INFO(0x0b4018, 0, 64 * 1024, 256, 0) },
    
  • 配置裝置樹,若無顯示器,則顯示部分不用配置:

    # 1. 開啟 /arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dts 檔案
    # 2. 修改 顯示驅動
    
    	panel: panel {
    		# 修改為 800*480 的螢幕
    		compatible = "lg,lb070wv8", "simple-panel";
    		#address-cells = <1>;
    		#size-cells = <0>;
    		enable-gpios = <&pio 4 6 GPIO_ACTIVE_HIGH>;
    
    		port@0 {
    			reg = <0>;
    			#address-cells = <1>;
    			#size-cells = <0>;
    
    			panel_input: endpoint@0 {
    				reg = <0>;
    				remote-endpoint = <&tcon0_out_lcd>;
    			};
    		};
    	};
    
    # 3. 新增對spiflash支援
    &spi0 {
        pinctrl-names = "default";
        pinctrl-0 = <&spi0_pins_a>;
        status = "okay";
        spi-max-frequency = <50000000>;
        flash: xt25f128b@0 {
            #address-cells = <1>;
            #size-cells = <1>;
            compatible = "winbond,xt25f128b", "jedec,spi-nor";
            reg = <0>;
            spi-max-frequency = <50000000>;
            partitions {
                compatible = "fixed-partitions";
                #address-cells = <1>;
                #size-cells = <1>;
    
                partition@0 {
                    label = "u-boot";
                    reg = <0x000000 0x100000>;
                    read-only;
                };
    
                partition@100000 {
                    label = "dtb";
                    reg = <0x100000 0x10000>;
                    read-only;
                };
    
                partition@110000 {
                    label = "kernel";
                    reg = <0x110000 0x400000>;
                    read-only;
                };
    
                partition@510000 {
                    label = "rootfs";
                    reg = <0x510000 0xAF0000>;
                };
            };
        };
    };
    
    

編譯、燒寫 linux

編譯 linux:

  • 映象檔案生成在 arch/arm/boot/zImage
  • 裝置樹檔案在 arch/arm/boot/dts/suniv-f1c100s-licheepi-nano.dtb
  • 編譯步驟:
    # 1. 編譯
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j11
    
    # 錯誤處理 fatal error: openssl/bio.h:
    sudo apt-get install libssl-dev
    
    

單獨編譯裝置樹:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- dtbs -j11

燒寫:

  1. 進入 fel 模式。
  2. 燒寫韌體:sudo sunxi-fel -p spiflash-write [燒錄的地址] [燒錄的檔案]

roofs 裁剪

整理的 rootfs 使用 buildroot 。

獲取 buildroot 原始碼

步驟:

  1. https://buildroot.org/download.html 可以下載到最新的程式碼包。
  2. 解壓這個程式碼包 tar -xzvf buildroot-2021.08.tar.gz1

配置 buildroot

# 1. 開啟圖形化介面
make menuconfig

# 2. 選擇處理器
Target options
	Target Architecture (ARM (little endian))
	Target Variant arm926t

# 3. 啟動軟連結等
System configuration
	Use syslinks to /usr ....  # 啟動 連結
    Enable root login   		# root 登入
    Run a getty after boot 		# 輸入密碼
    remount root filesystem     # 重新掛載根檔案系統到可讀寫

編譯、燒寫 buildroot

編譯:

# 編譯比較慢,可以配老婆/女朋友聊聊天。 如果編譯不成功 make clean 重來
make

編譯完成的根目錄在 output/images/rootfs.tar . 複製出來解壓:

# 複製出來
cp output/images/rootfs.tar ../
# 建立跟目錄資料夾
mkdir rootfs
# 解壓到這個資料夾
tar -xvf rootfs.tar -C rootfs/

# 安裝 jffs2 
sudo apt-get install mtd-utils

# 製作映象, 得到 jffs2.img 可以燒錄到開發板
mkfs.jffs2 -s 0x100 -e 0x10000 --pad=0xAF0000 -d rootfs/ -o jffs2.img

燒寫:

  1. 進入 fel 模式。
  2. 燒寫韌體:sudo sunxi-fel -p spiflash-write [燒錄的地址] [燒錄的檔案]

SPI FLASH 編譯燒寫

根據自己的配置進行分割槽

如:

分割槽序號 分割槽大小 分割槽作用 地址空間及分割槽名
mtd0 1MB (0x100000) spl+uboot 0x0000000-0x0100000 : “uboot”
mtd1 64KB (0x10000) dtb 檔案 0x0100000-0x0110000 : “dtb”
mtd2 4MB (0x400000) linux 核心 0x0110000-0x0510000 : “kernel”
mtd3 剩餘 (0xAF0000) 根檔案系統 0x0510000-0x1000000 : “rootfs”

單個燒寫

  • u-boot 燒寫到第一分割槽

    sudo sunxi-fel -p spiflash-write 0 u-boot-sunxi-with-spl.bin
    
  • dtb 檔案燒寫到第二分割槽

    sudo sunxi-fel -p spiflash-write 0x0100000 suniv-f1c100s-licheepi-nano.dtb
    
  • zImage 映象檔案燒寫到第三分割槽

    sudo sunxi-fel -p spiflash-write 0x0110000 zImage
    
  • 我們把 根檔案系統 燒寫到第四分割槽

    sudo sunxi-fel -p spiflash-write 0x0510000 jffs2.img
    

打包成一個檔案

上面是一個一個韌體燒寫,我們可以通過指令碼把其打包成一個韌體進行燒寫:

建立一個專門放韌體的目錄,如 my_bin。在該目錄下按下面格式建立資料夾並存放對應韌體:

  1.  ls
     
     buildroot  linux  u-boot
    
  2. 把下面指令碼檔案放到 my_bin 目錄下,執行,output 為最後輸出的檔案。

    #! /bin/bash
    
    rm -rf ./output
    mkdir ./output
    rm -rf ./rootfs
    mkdir ./rootfs
    
    dd if=/dev/zero of=flashimg.bin bs=1M count=16 &&\
    dd if=./u-boot/u-boot-sunxi-with-spl.bin of=flashimg.bin bs=1K conv=notrunc &&\
    dd if=./linux/suniv-f1c100s-licheepi-nano.dtb of=flashimg.bin bs=1K seek=1024  conv=notrunc &&\
    dd if=./linux/zImage of=flashimg.bin bs=1K seek=1088  conv=notrunc &&\
    
    tar -xf ./buildroot/rootfs.tar -C ./rootfs &&\
    
    mkfs.jffs2 -s 0x100 -e 0x10000 --pad=0xAF0000 -d rootfs/ -o jffs2.img &&\
    
    dd if=jffs2.img of=flashimg.bin bs=1K seek=5184  conv=notrunc
    mv flashimg.bin ./output
    rm -rf jffs2.img
    
  3. 執行命令燒錄到開發板:

    sudo sunxi-fel -p spiflash-write 0 flashimg.bin
    

小知識

uboot sf 命令用法

uboot 中如果支援 spi/qspi flash, 那麼可以使用 sf 的 erase, read, write 命令操作 spi flash。

  • sf read 用來讀取 flash 資料到記憶體。
  • sf write 寫記憶體資料到 flash。
  • sf erase 擦除指定位置,指定長度的 flash 內容, 在進行寫 flash 的時候一定要先進行擦除,否則會失敗,因為 flash 只能從 1 變為 0。

具體參考:

sf - SPI flash sub-system

Usage:
sf probe [[bus:]cs] [hz] [mode] - init flash device on given SPI bus and chip select

sf read addr offset len - read `len' bytes starting at
                                  `offset' to memory at `addr'

sf write addr offset len        - write `len' bytes from memory
                                  at `addr' to flash at `offset'

sf erase offset [+]len          - erase `len' bytes from `offset'
                                  `+len' round up `len' to block size

sf update addr offset len       - erase and write `len' bytes from memory
                                  at `addr' to flash at `offset'

使用注意:

  1. 在使用 sf 的其他命令之前必須先使用 sf probe 操作進行連線 flash。
    1. 如:sf probe 0 50000000,初始化匯流排 0 上的 FLASH,且速度為 50000000 Hz。

uboot bootz 引數

對於 ARM 來講,可以透過 bootz <kernel_addr> <initrd_address> <dtb_address> 的命令來啟動核心。

  • 第一個引數為核心映像的地址。
  • 第二個引數為 initrd 的地址,若不存在 initrd,可以用 - 代替。
  • dtb_address 作為 bootz 或者 bootm 的最後一次引數。

相關文章