在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Linux U-Boot開發指南

嵌入式Linux那些事 ? 來源:嵌入式Linux那些事 ? 作者:嵌入式Linux那些事 ? 2023-03-06 10:28 ? 次閱讀

Linux U-Boot 開發指南

1 前言

1.1 編寫目的

介紹 U-Boot 的編譯打包、基本配置、常用命令的使用、基本調試方法等, 為 U-BOOT 的移植及應用開發提供了基礎。

1.2 適用范圍

本文檔適用于 brandy2.0, 即 U-Boot-2018 平臺。

1.3 相關人員

U-Boot 開發/維護人員,內核開發人員。

2 LICHEE 類宏關鍵字解釋

請到 longan 目錄下的.buildconfig 查看目前使用了以下 LICHEE 類宏。

LICHEE_IC ——> IC名

LICHEE_CHIP ——> 平臺名

LICHEE_BOARD ——> 板級名

LICHEE_ARCH ——> 所屬架構

LICHEE_BOARD_CONFIG_DIR ——> 板級目錄

LICHEE_BRANDY_OUT_DIR ——> bin文件所在目錄

LICHEE_PLAT_OUT ——> 平臺臨時bin所在目錄

LICHEE_CHIP_CONFIG_DIR ——> IC目錄

3 編譯方法介紹

3.1 準備編譯工具鏈

準備編譯工具鏈接執行步驟如下:

1)cd longan/brandy/brandy-2.0/

2)./build.sh -t

3.2 快速編譯 boot0 及 U-Boot

在longan/brandy/brandy-2.0/目錄下,執行 ./build.sh -p 平臺名稱,可以快速完成整個 boot 編譯動作。這個平臺名稱是指,LICHEE_CHIP。

./build.sh -p {LICHEE_CHIP} //快速編譯spl/U-Boot

./build.sh -o spl-pub -p {LICHEE_CHIP} //快速編譯spl-pub

./build.sh -o uboot -p {LICHEE_CHIP} //快速編譯U-Boot

3.3 編譯 U-Boot

cd longan/brandy/brandy-2.0/u-boot-2018/進入 u-boot-2018 目錄。以{LICHEE_CHIP}為例,依次執行如下操作即可。

1)make {LICHEE_CHIP}_defconfig

2)make -j

3.4 編譯 boot0/fes/sboot

cd longan/brandy/brandy-2.0/spl-pub進入spl-pub目錄,需設置平臺和要編譯的模塊參數。以{LICHEE_CHIP}為例,編譯 nand/emmc 的方法如下:

編譯boot0

make distclean

make p={LICHEE_CHIP} m=nand

make boot0

?

make distclean

make p={LICHEE_CHIP} m=emmc

make boot0

編譯fes

make distclean

make p={LICHEE_CHIP} m=fes

make fes

編譯sboot

make distclean

make p={LICHEE_CHIP} m=sboot

make sboot

4 U-Boot 功能及其配置方法/文件介紹

4.1 U-Boot 功能介紹

嵌入式操作系統中,BootLoader/U-Boot 是在操作系統內核運行之前運行??梢猿跏蓟布O備、建立內存空間映射圖,從而將系統的軟硬件環境帶到一個合適狀態,以便為最終調用操作系統內核準備好正確的環境。在 sunxi 平臺中,除了必須的引導系統啟動功能外,BOOT 系統還提供燒寫、升級等其它功能。

U-Boot 主要功能可以分為以下幾類

引導內核

能從存儲介質(nand/mmc/spinor)上加載內核鏡像到 DRAM 指定位置并運行。

量產 & 升級

包括卡量產,USB 量產,私有數據燒錄,固件升級

開機提示信息

開機能顯示啟動 logo 圖片(BMP 格式)

Fastboot 功能

實現 fastboot 的標準命令,能使用 fastboot 刷機

4.2 U-Boot 功能配置方法介紹

U-Boot 中的各項功能可以通過 defconfig 或配置菜單 menuconfig 進行開啟或關閉, 具體配置

方法如下:

4.2.1 通過 defconfig 方式配置

vim /longan/brandy/brandy-2.0/u-boot-2018/configs/{LICHEE_CHIP}_defconfig

開{LICHEE_CHIP}defconfig或{LICHEE_CHIP}nor_defconfig后,在相應的宏定義前去掉或添加"#"即可將相應功能開啟或關閉。如下圖,只要將CONFIG_SUNXI_NAND前的#去掉即可支持 NAND 相關功能,其他宏定義的開啟關閉也類似。修改后需要運行make xxx_defconfig使修改后的配置生效。

poYBAGQFT7mAWRkKAAFz-Z4R0zY051.png

圖 4-1: defconfig 配置圖

4.2.2 通過 menuconfig 方式配置

通過 menuconfig 方式配置的方法步驟如下:

cd brandy/brandy-2.0/u-boot-2018/

執行make menuconfig命令,會彈出 menuconfig 配置菜單窗口,如下圖所示。此時即可對各模塊功能進行配置,配置方法 menuconfig 配置菜單窗口中有說明。

修改后配置已經生效,直接 make 即可生成對應 bin。如果重新運行make xxx_defconfig,通過menuconfig 方式修改的配置會在運行make xxx_defconfig后被xxx_defconfig中的配置覆蓋。

pYYBAGQFT7qAAeieAABlQ40-WAs219.png

圖 4-2: menuconfig 配置菜單圖

4.3 U-Boot 配置參數文件介紹

U-Boot 自 linux-5.4 以后不再使用 sysconfig 和內核 dts 作為配置文件,而是使用 U-Boot 自帶的 dts 來配置參數。kernel-dts 與 U-Boot-dts 完全獨立。

4.3.1 U-Boot-dts 路徑

U-Boot-dts 路徑為:vim longan/brandy/brandy-2.0/u-boot-2018/arch/arm/dts

4.3.2 U-Boot-dts,defconfig 配置

配置項 配置項含義
CONFIG_OF_SEPARATE 構建 U-Boot 設備樹成為 U-Boot 的一部分
CONFIG_OF_BOARD 關閉使用外部 dts
CONFIG_DEFAULT_DEVICE_TREE 選擇構建的 dts 文件文件名
CONFIG_SUNXI_NECESSARY_REPLACE_FDT 開啟選項, 實現內部 dts 換成外部 dts

配置項 選項
CONFIG_OF_SEPARATE y
CONFIG_OF_BOARD n
CONFIG_DEFAULT_DEVICE_TREE “{LICHEE_CHIP}-soc-system”
CONFIG_SUNXI_NECESSARY_REPLACE_FDT y

4.3.3 U-Boot-dts 注意事項

4.3.3.1 編譯注意事項

1.dts 分為板級 dts,和系統 dts。

?? 系統 dts 由 CONFIG_DEFAULT_DEVICE_TREE 決定,可以在 $(CONFIG_SYS_CONFIG_NAME)_defconfig找到該宏的定義。

?? 系統 dts 最終會 include 板級 dts,文件路徑 {LICHEE_BOARD_CONFIG_DIR},文件名:uboot-board.dts。

我們可以通過編譯時的打印判斷啟動的 dts

OBJCOPY examples/standalone/hello_world.srec

OBJCOPY examples/standalone/hello_world.bin

LD u-boot

OBJCOPY u-boot.srec

OBJCOPY u-boot-nodtb.bin

‘{LICHEE_BOARD_CONFIG_DIR}/uboot-board.dts’ -> ‘~/longan/brandy/brandy-2.0/u-boot-2018/

arch/{LICHEE_ARCH}/dts/.board-uboot.dts’

DTC arch/{LICHEE_ARCH}/dts/{LICHEE_CHIP}-soc-system.dtb

SYM u-boot.sym

SHIPPED dts/dt.dtb

FDTGREP dts/dt-spl.dtb

COPY u-boot.dtb

CAT u-boot-dtb.bin

COPY u-boot.bin

‘u-boot.bin’ -> ‘{LICHEE_CHIP}.bin’ ‘u-boot-g{LICHEE_CHIP}.bin’ -> ‘{LICHEE_BRANDY_OUT_DIR}/bin/u-boot-g{LICHEE_CHIP}.bin’ ‘u-boot-g{LICHEE_CHIP}.bin’ -> ‘{LICHEE_PLAT_OUT}/u-boot-g{LICHEE_CHIP}.bin’

CFGCHK u-boot.cfg

4.3.3.2 語法注意事項

當系統 dts 與板級 dts 存在同路徑下同名節點時,板級 dts 將會覆蓋系統 dts。

4.3.3.3 運行時注意事項

為了在啟動內核前更新參數到內核 dts 和可以在 U-Boot 控制臺查看修改 dts。按階段劃分可以分為使用內部 dts 階段和使用內核 dts 階段,如下圖所示。

poYBAGQFT7qAf2q0AAA4I4R0sCg158.png

圖 4-3: dts 變化圖

可以通過命令set_working_fdt來切換當前生效的 fdt。

[04.562]update bootcmd [04.576]change working_fdt 0x7bebee58 to 0x7be8ee58 [04.587]update dts Hit any key to stop autoboot: 0 => set set_working_fdt setenv setexpr => set_working_fdt 0x7bebee58 change working_fdt 0x7be8ee58 to 0x7bebee58 =>

5 U-Boot 常用命令介紹

5.1 env 命令說明

通過env命令可以對{LICHEE_CHIP_CONFIG_DIR}/configs/default/env.cfg中的環境變量進行查看及更改。在小機啟動過程中按任意鍵進入 U-Boot shell 命令狀態,輸入命令"env"即可查看命令幫助信息。

具體示例如下:

輸入命令"env print",可查看當前所有的環境變量信息,如下:

=> pri ab_partition_list=bootloader,env,boot,vendor_boot,dtbo,vbmeta,vbmeta_system,vbmeta_vendor android_trust_chain=true boot_fastboot=fastboot boot_normal=sunxi_flash read 45000000 boot;bootm 45000000 boot_recovery=sunxi_flash read 45000000 recovery;bootm 45000000 bootcmd=run setargs_mmc boot_normal bootdelay=0 bootreason=charger bt_mac=20:A1:11:12:13:44 cma=8M console=ttyAS0,115200 earlyprintk=sunxi-uart,0x05000000 fdtcontroladdr=7bed0e60 fileaddr=40000000 filesize=15cf6 force_normal_boot=1 init=/init initcall_debug=0 keybox_list=widevine,ec_key,ec_cert1,ec_cert2,ec_cert3,rsa_key,rsa_cert1,rsa_cert2,rsa_cert3 loglevel=8 mac=10:14:15:15:9A:CA mmc_root=/dev/mmcblk0p4 nand_root=/dev/nand0p4 partitions=bootloader_a@mmcblk0p1:bootloader_b@mmcblk0p2:env_a@mmcblk0p3:env_b@mmcblk0p4: boot_a@mmcblk0p5:boot_b@mmcblk0p6:vendor_boot_a@mmcblk0p7:vendor_boot_b@mmcblk0p8: super@mmcblk0p9:misc@mmcblk0p10:vbmeta_a@mmcblk0p11:vbmeta_b@mmcblk0p12: vbmeta_system_a@mmcblk0p13:vbmeta_system_b@mmcblk0p14:vbmeta_vendor_a@mmcblk0p15: vbmeta_vendor_b@mmcblk0p16:frp@mmcblk0p17:empty@mmcblk0p18:metadata@mmcblk0p19: private@mmcblk0p20:dtbo_a@mmcblk0p21:dtbo_b@mmcblk0p22:media_data@mmcblk0p23: UDISK@mmcblk0p24 rotpk_status=0 setargs_mmc=setenv bootargs earlyprintk=${earlyprintk} clk_ignore_unused initcall_debug=${ initcall_debug} console=${console} loglevel=${loglevel} root=${mmc_root} init=${init} cma=${cma} snum=${snum} mac_addr=${mac} wifi_mac=${wifi_mac} bt_mac=${bt_mac} specialstr=${specialstr} gpt=1 androidboot.force_normal_boot=${force_normal_boot} androidboot.slot_suffix=${slot_suffix} setargs_nand=setenv bootargs earlyprintk=${earlyprintk} clk_ignore_unused initcall_debug=${ initcall_debug} console=${console} loglevel=${loglevel} root=${nand_root} init=${init} cma=${cma} snum=${snum} mac_addr=${mac} wifi_mac=${wifi_mac} bt_mac=${bt_mac} specialstr=${specialstr} gpt=1 androidboot.force_normal_boot=${force_normal_boot} androidboot.slot_suffix=${slot_suffix} slot_suffix=_a snum=A100B3N041 wifi_mac=10:A1:11:12:13:44 Environment size: 2078/131068 bytes =>

輸入命令"env set bootdelay 3",可更改環境變量bootdelay(即 boot 啟動時 log 中的倒計時延遲時間)值的大小。

輸入命令"env save",即可將上述更改進行保存,保存后重新上電,或輸入命令"reset",即可看到上述更改bootdelay的延時時間被更改生效。

其他env命令請查看env幫助信息。

5.2 sunxi_flash read 命令說明

5.2.1 使用方法

用以下命令將 flash 指定地址中數據讀到 DRAM 的指定地址處:

sunxi_flash read dram_addr flash_addr

5.2.2 使用示例

sunxi_flash read 0x45000000 env—將env分區數據讀到DRAM的0x45000000地址處 sunxi_flash read 45000000 boot;bootm 45000000—將flash中boot分區數據讀到DRAM的0x45000000地 址,并 從0x45000000處啟動。

5.3 fastboot 命令說明

fastboot 是 Android 平臺上一個通用的刷機工具,也是一個很好的開發調試工具,以下介紹 fastboot 的基本使用方法。

5.3.1 使用前提

fastboot PC 端工具可以從 Google Android SDK(Android-sdk-windows/tools) 中獲得,也可以在 Android 源代碼編譯過后的生成文件獲得 (out/host/linux-x86/bin)。

在 Linux 系統中,使用 fastboot 不需要安裝驅動。但在 Windows 系統中,使用 fastboot 前需安裝 fastboot 相關驅動。adb 的驅動在 fastboot 模式下也可以安裝成功,但是無法使用,請使用我們提供的驅動,并手動安裝。

5.3.2 使用步驟

小機上電啟動,按任意鍵進入 U-Boot 命令狀態;

串口端輸入"fastboot"命令;

打開 PC 端 fastboot 工具,并輸入"fastboot devices"命令,看是否有 fastboot 設備顯示;

在正確獲取 fastboot 設備的前提下,輸入命令"fastboot flash env /path/to/env.fex",將env.fex寫到env分區(/path/to/目錄下的env.fex中bootdelay值應該與 flash 中原有env中bootdelay值不同,這樣可根據bootdelay值不同來確定 fastboot 燒寫是否成功), 同下載env.fex分區一樣, 輸入命令“fastboot flash boot /path/to/boot.img”將內核下載到內存中;

輸入"fastboot reboot"命令重啟,查看啟動倒計時即bootdelay的值是否改變;

5.3.3 fastboot 基本命令使用示例

fastboot 幾個基本命令示例如下:

fastboot devices :顯示 fastboot 的設備。

fastboot erase :擦除分區,例如fastboot erase boot,擦除boot分區。

fastboot flash:舊分區(待寫分區),例如fastboot flash boot/path/to/boot.img,將boot.img寫到boot分區。

注意事項:

fastboot 中使用的分區和sys_partition.fex中分區一致,具體的分區信息可以從小機上電啟動進入 U-Boot shell 命令狀態,輸入命令"part list sunxi_flash 0"中獲取,分區信息如下:

=> part list sunxi_flash 0 Partition Map for UNKNOWN device 0 -- Partition Type: EFI Part Start LBA End LBA Name Attributes Type GUID Partition GUID 1 0x00008000 0x00017fff "bootloader" attrs: 0x8000000000000000 type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7 guid: a0085546-4166-744a-a353-fca9272b8e45 2 0x00018000 0x0001ffff "env" attrs: 0x8000000000000000 type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7 guid: a0085546-4166-744a-a353-fca9272b8e46 3 0x00020000 0x0002ffff "boot" attrs: 0x8000000000000000 type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7 guid: a0085546-4166-744a-a353-fca9272b8e47 4 0x00030000 0x0032ffff "super" attrs: 0x8000000000000000 type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7 guid: a0085546-4166-744a-a353-fca9272b8e48 5 0x00330000 0x00337fff "misc" attrs: 0x8000000000000000 type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7 guid: a0085546-4166-744a-a353-fca9272b8e49 6 0x00338000 0x00347fff "recovery" attrs: 0x8000000000000000 type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7 guid: a0085546-4166-744a-a353-fca9272b8e4a

5.4 fat 命令說明

fat命令可以對 FAT 文件系統的相關存儲設備進行查詢及文件讀寫操作,在打包固件的時候, 我們會制作啟動資源分區鏡像, 把指定的目錄下的文件按照文件系統的格式排布,文件中包括了原來目錄中的所有文件,并完全按照目錄結構排列。當把這個鏡像文件燒寫到存儲設備上的某一個分區的時候,可以看到這個分區和原有目錄的內容一樣。使用fat可以方便地以文件和目錄的方式對小機 flash 進行數據訪問,如顯示 logo。這些指令基本上要和 U 盤或者 SD 卡同時使用,主要用于讀取這些移動存儲器上的 FAT 分區。其相關操作命令如下:

fatls : 列出相應設備目錄上的所有文件,示例如下圖:

pYYBAGQFT7uAB1raAADCC9jRta0131.png

圖 5-1: fatls 命令執行示例圖

說明

補充說明,fatls mmc 2:2 中的第一個 2 表示的是 emmc 設備,2 表示其分區號,其說明如下圖:

poYBAGQFT7uAb3QBAABH2ZbKj78942.png

圖 5-2: fatls 命令參數說明圖

fatinfo: 打印出相應設備目錄的文件系統信息,示例如下圖:

pYYBAGQFT7yAOX6KAAEhNQlJdKI329.png

圖 5-3: fatinfo 命令執行示例圖

fatload: 從 FAT 文件系統中讀取二進制文件到 RAM 存儲中,示例如下:

sunxi#usb start (Re)start USB... USB0: start sunxi ehci1... config usb pin success config usb clk ok sunxi ehci1 init ok... USB EHCI 1.00 scanning bus 0 for devices... 3 USB Device(s) found scanning usb for storage devices... 1 Storage Device(s) found sunxi#fatls usb 0:1 / 16024600 sandisksecureaccessv3_win.exe sandisk secureaccess/ lost.dir/ Android/ test/ video test/ amapauto/ 0 vid_20161017_160818.ts phoenixsuit/ system volume information/ 0 vid_20161017_160919.ts video/ 156672 wifi pro_com su.exe 495 sys.ini 1035 pr_80211g_all.ini config/ 158208 wifi pro_new.exe 158208 wifi pro.exe 0 vid_20161017_164822.ts 0 vid_20161017_164906.ts sunxi-tvd/ 71149 sys_config.fex vga/ 397836884 system.img 14180352 boot.img 13 file(s), 13 dir(s) sunxi#fatload usb 0:1 0x42000000 boot.img reading boot.img 14180352 bytes read in 1149 ms (11.8 MiB/s) sunxi#mmc dev 2 mmc2(part 0) is current device sunxi#mmc write 0x42000000 0x15000 5000 MMC write: dev # 2, block # 86016, count 20480 ... 20480 blocks written: OK

說明:以上操作即將 U 盤的boot.img寫到對應的 mmc 分區地址處。

fatwrite: 從內存中將對應的文件寫到設備文件系統中。

5.5 md 命令說明

md命令可以對指定內存的數據進行查看,方便了解內存的數據情況及調試工作。其使用方法如下:

md 0xF0000000: 即用md命令查看內存DRAM 0xF0000000處內容

5.6 FDT 命令說明

FDT:flattened device tree 的縮寫在 U-Boot 控制臺停下后,輸入fdt,可以查看fdt命令幫助。

sunxi#fdt fdt - flattened device tree utility commands Usage: fdt addr [-c] [] - Set the [control] fdt location to fdt move - Copy the fdt to and make it active fdt resize - Resize fdt to size + padding to 4k addr fdt print [] - Recursive print starting at fdt list [] - Print one level starting at fdt get value - Get and store in fdt get name - Get name of node and store in fdt get addr - Get start address of and store in fdt get size [] - Get size of [] or num nodes and store in fdt set [] - Set [to ] fdt mknode - Create a new node after fdt rm [] - Delete the node or fdt header fdt bootcpu - Set boot cpuid fdt memory - Add/Update memory node fdt rsvmem print - Show current mem reserves fdt rsvmem add - Add a mem reserve fdt rsvmem delete - Delete a mem reserves fdt chosen [] - Add/update the /chosen branch in the tree / - initrd start/end addr NOTE: Dereference aliases by omiting the leading '/', e.g. fdt print ethernet0。 sunxi#

說明

其中常用的命令就是fdt list 和 fdt set,fdt list 用來查詢節點配置,fdt set 用來修改節點配置。

5.6.1 查詢配置

首先確定要查詢的字段在 device tree 的路徑,如果不知道路徑,則需要用fdt命令按以下步驟進

行查詢。1. 在根目錄下查找。

sunxi#fdt list / / { model = "{LICHEE_CHIP}"; compatible = "arm,{LICHEE_CHIP}", "arm,{LICHEE_CHIP}"; interrupt-parent = <0x00000001>; #address-cells = <0x00000002>; #size-cells = <0x00000002>; ...................... cpuscfg { }; ion { }; dram { }; memory@40000000 { }; interrupt-controller@1c81000 { }; sunxi-chipid@1c14200 { }; timer { }; pmu { }; dvfs_table { }; dramfreq { }; gpu@0x01c40000 { }; wlan { }; bt { }; btlpm { }; };

如果找到需要的配置,比如wlan的配置,運行如下命令即可。

sunxi#fdt list /wlan //注意路徑中的 / wlan { compatible = "allwinner,sunxi-wlan"; clocks = <0x00000096>; wlan_power = "vcc-wifi"; wlan_io_regulator = "vcc-wifi-io"; wlan_busnum = <0x00000001>; status = "okay"; device_type = "wlan"; wlan_regon = <0x00000077 0x0000000b 0x00000002 0x00000001 0xffffffff 0xffffffff 0 ? ?x00000000>; wlan_hostwake = <0x00000077 0x0000000b 0x00000003 0x00000006 0xffffffff 0xffffffff ? ?0x00000000>; };

在 soc目錄下找。如果在第一步中沒有發現要找的配置,比如nand0的配置,則該配置可能在soc目錄下。

sunxi#fdt list /soc soc@01c00000 { compatible = "simple-bus"; #address-cells = <0x00000002>; #size-cells = <0x00000002>; ranges; device_type = "soc"; ...................... hdmi@01ee0000 { }; tr@01000000 { }; pwm@01c21400 { }; nand0@01c03000 { }; thermal_sensor { }; cpu_budget_cool { }; ....................... };

然后用如下命令顯示即可:

sunxi#fdt list /soc/nand0 nand0@01c03000 { compatible = "allwinner,sun50i-nand"; device_type = "nand0"; reg = <0x00000000 0x01c03000 0x00000000 0x00001000>; interrupts = <0x00000000 0x00000046 0x00000004>; clocks = <0x00000004 0x0000007e>; pinctrl-names = "default", "sleep"; pinctrl-1 = <0x00000081>; nand0_regulator1 = "vcc-nand"; nand0_regulator2 = "none"; nand0_cache_level = <0x55aaaa55>; nand0_flush_cache_num = <0x55aaaa55>; nand0_capacity_level = <0x55aaaa55>; nand0_id_number_ctl = <0x55aaaa55>; nand0_print_level = <0x55aaaa55>; nand0_p0 = <0x55aaaa55>; nand0_p1 = <0x55aaaa55>; nand0_p2 = <0x55aaaa55>; nand0_p3 = <0x55aaaa55>; status = "disabled"; nand0_support_2ch = <0x00000000>; pinctrl-0 = <0x000000a9 0x000000aa>; };

使用路徑別名查找。別名是 device tree 中完整路徑的一個簡寫,有一個專門的節點 ( /aliases) 來表示別名的相關信息,用如下命令可以查看系統中別名的配置情況:

sunxi#fdt list /aliases aliases { serial0 = "/soc@01c00000/uart@01c28000"; .............. mmc0 = "/soc@01c00000/sdmmc@01c0f000"; mmc2 = "/soc@01c00000/sdmmc@01C11000"; nand0 = "/soc@01c00000/nand0@01c03000"; disp = "/soc@01c00000/disp@01000000"; lcd0 = "/soc@01c00000/lcd0@01c0c000"; hdmi = "/soc@01c00000/hdmi@01ee0000"; pwm = "/soc@01c00000/pwm@01c21400"; boot_disp = "/soc@01c00000/boot_disp"; }; sunxi#

由于配置了nand0節點的路徑別名,因此可以用如下命令來顯示nand0的配置信息。

sunxi#fdt list nand0 nand0@01c03000 { compatible = "allwinner,sun50i-nand"; device_type = "nand0"; reg = <0x00000000 0x01c03000 0x00000000 0x00001000>; .................. pinctrl-names = "default", "sleep"; pinctrl-1 = <0x00000081>; };

注:在fdt的所有命令中,alias 可以用作path參數。

fdt list [] - Print one level starting at fdt set [] - Set [to ]

5.6.2 修改配置

5.6.2.1 修改整數配置

命令格式:fdt set path prop 示例:fdt set /wlan wlan_busnum <0x2>

sunxi#fdt list /wlan wlan { compatible = "allwinner,sunxi-wlan"; clocks = <0x00000096>; wlan_power = "vcc-wifi"; wlan_io_regulator = "vcc-wifi-io"; wlan_busnum = <0x00000001>; status = "disable"; device_type = "wlan"; }; sunxi#fdt set /wlan wlan_busnum <0x2> sunxi#fdt list /wlan wlan { compatible = "allwinner,sunxi-wlan"; clocks = <0x00000096>; wlan_power = "vcc-wifi"; wlan_io_regulator = "vcc-wifi-io"; wlan_busnum = <0x00000002>; //修改后 status = "disable"; device_type = "wlan"; };

注:修改整數時,根據需要也可配置為數組形式,需要用空格來分隔。命令格式:fdt set path prop <0x1 0x2 0x3>

5.6.2.2 修改字符串配置

命令格式:fdt set path prop "xxxxx" 示例:fdt set /wlan status "disable"

sunxi#fdt list /wlan wlan { compatible = "allwinner,sunxi-wlan"; clocks = <0x00000096>; wlan_power = "vcc-wifi"; wlan_io_regulator = "vcc-wifi-io"; wlan_busnum = <0x00000001>; status = "okay"; device_type = "wlan"; }; sunxi#fdt set /wlan status "disable" sunxi#fdt list /wlan wlan { compatible = "allwinner,sunxi-wlan"; clocks = <0x00000096>; wlan_power = "vcc-wifi"; wlan_io_regulator = "vcc-wifi-io"; wlan_busnum = <0x00000001>; status = "disable"; //修改后 device_type = "wlan"; }; sunxi#

注:修改字符串時,根據需要也可配置為數組形式,需要用空格來分隔。命令格式:fdt set path prop "string1" "string2"

5.6.3 GPIO 或者 PIN 配置特殊說明

接口對應的數字編號說明如下:

#define PA 0 #define PB 1 #define PC 2 #define PD 3 #define PE 4 #define PF 5 #define PG 6 #define PH 7 #define PI 8 #define PJ 9 #define PK 10 #define PL 11 #define PM 12 #define PN 13 #define PO 14 #define PP 15 #define default 0xffffffff

Sysconfig 中描述 gpio 的形式如下:Port:端口+組內序號<功能分配><內部電阻狀態><驅動能力><輸出電平狀態>

5.6.3.1 Pin 配置說明

Pinctrl 節點分為 cpux 和 cpus,對應的節點路徑如下:Cpux : /soc/pinctrl@01c20800 Cpus:/soc/pinctrl@01f02c00

5.6.3.2 查看 PIN 配置

PIN 配置屬性字段說明:

屬性字段 含義
allwinner,function 對應于 sysconfig 中的主鍵名
allwinner,pins 對應于 sysconfig 中每個 gpio 配置中的端口名
allwinner,pname 對應于 sysconfig 中主鍵下面子鍵名字
allwinner,muxsel 功能分配
allwinner,pull 內部電阻狀態
allwinner,drive 驅動能力
allwinner,data 輸出電平狀態

說明

其中0xffffffff表示使用默認值。

按以下方法查看cpux的 PIN 配置。

sunxi#fdt list /soc/pinctrl@01c20800/lcd0 lcd0@0 { linux,phandle = <0x000000ab>; phandle = <0x000000ab>; allwinner,pins = "PD12", "PD13", "PD14", "PD15", "PD16", "PD17", "PD18", "PD19", "PD20", "PD21"; allwinner,function = "lcd0"; allwinner,pname = "lcdd0", "lcdd1", "lcdd2", "lcdd3", "lcdd4", "lcdd5", "lcdd6", "lcdd7", "lcdd8", "lcdd9"; allwinner,muxsel = <0x00000003>; allwinner,pull = <0x00000000>; allwinner,drive = <0xffffffff>; allwinner,data = <0xffffffff>; }; sunxi#

按以下方法查看cpus的 PIN 配置。

sunxi# fdt list /soc/pinctrl@01f02c00/s_uart0 s_uart0@0 { linux,phandle = <0x000000b4>; phandle = <0x000000b4>; allwinner,pins = "PL2", "PL3"; allwinner,function = "s_uart0"; allwinner,pname = "s_uart0_tx", "s_uart0_rx"; allwinner,muxsel = <0x00000002>; allwinner,pull = <0xffffffff>; allwinner,drive = <0xffffffff>; allwinner,data = <0xffffffff>; }; sunxi#

5.6.3.3 修改 PIN 配置

使用fdt set命令可以修改 PIN 中相關屬性字段

sunxi#fdt set /soc/pinctrl@01c20800/lcd0 allwinner,drive <0x1> sunxi#fdt list /soc/pinctrl@01c20800/lcd0 lcd0@0 { linux,phandle = <0x000000ab>; phandle = <0x000000ab>; allwinner,pins = "PD12", "PD13", "PD14", "PD15", "PD16", "PD17", "PD18", "PD19", "PD20", "PD21"; allwinner,function = "lcd0"; allwinner,pname = "lcdd0", "lcdd1", "lcdd2", "lcdd3", "lcdd4", "lcdd5", "lcdd6", "lcdd7", "lcdd8", "lcdd9"; allwinner,muxsel = <0x00000003>; allwinner,pull = <0x00000000>; allwinner,drive = <0x00000001>; allwinner,data = <0xffffffff>; };

說明

示例中該處修改會影響allwinner,pins表示的所有端口的驅動能力配置,修改allwinner,muxsel, allwinner,pull,allwinner,data的值也會產生類似效果。

5.6.3.4 GPIO 配置說明

Device tree 中 GPIO 對應關系,以 usb 中usb_id_gpio為例

sunxi#fdt list /soc/usbc0 usbc0@0 { test = <0x00000002 0x00000003 0x12345678>; device_type = "usbc0"; compatible = "allwinner,sun50i-otg-manager"; ........ usb_serial_unique = <0x00000000>; usb_serial_number = "20080411"; rndis_wceis = <0x00000001>; status = "okay"; usb_id_gpio = <0x00000030 0x00000007 0x00000009 0x00000000 0x00000001 0xffffffff 0xffffffff>; };

對應于 device tree 中 usb_id_gpio = <0x00000030 0x00000007 0x00000009 0x00000000 0x00000001 0xffffffff 0xffffffff>,解釋如下:

屬性數值 含義
0x00000030 device tree 內部一個節點相關信息,這里可以略過
0x00000007 端口 PH, 即 #define PH 7
0x00000009 組內序號, 即 PH09
0x00000000 功能分配, 即將 PH09 配為輸入
0x00000001 內部電阻狀態, 即配為上拉
0xffffffff 驅動能力, 默認值
0xffffffff 輸出電平, 默認值

如果需要修改 usb_id_gpio的配置,可按如下方式(示例修改了驅動能力,輸出電平兩項):

sunxi#fdt set /soc/usbc0 usb_id_gpio <0x00000030 0x00000007 0x00000009 0x00000000 0x00000001 0x2 0x1> sunxi#fdt list usbc0@0 { test = <0x00000002 0x00000003 0x12345678>; device_type = "usbc0"; compatible = "allwinner,sun50i-otg-manager"; ........ usb_serial_unique = <0x00000000>; usb_serial_number = "20080411"; rndis_wceis = <0x00000001>; status = "okay"; usb_id_gpio = <0x00000030 0x00000007 0x00000009 0x00000000 0x00000001 0x00000002 0x00000001>; //修改ok }; sunxi#

5.7 其他命令說明(boot, reset, efex)

boot : 啟動內核

reset: 復位重啟系統

efex: 進入燒錄狀態

說明

注:其他更多 U-Boot 命令介紹,請進入 U-Boot shell 命令狀態后輸入"help"進行了解。

6 基本調試方法介紹

debug 調試信息介紹如下:

debug_mode

debug_mode 可以控制 Boot0 的打印等級,打開文件{LICHEE_BOARD_CONFIG_DIR}/sys_config.fex,在主鍵 [platform] 下添加子鍵"debug_mode = 8"即表示開啟所有打印,debug_mode=0 表示關閉啟動時 Boot0 的打印 log,未顯式配置 debug_mode 時,按 debug_mode=8 處理。目前常用的打印等級有 0(關閉所有打?。?、1(只顯示關鍵節點打?。?(打印錯誤信息)、8(打印所有 log 信息)。

debug_mode 可以控制 U-Boot 的打印等級,打開文件{LICHEE_BOARD_CONFIG_DIR}/b3/uboot-board.dts,在 platform 節點下添加子鍵"debug_mode = 8"即表示開啟所有打印,debug_mode=0 表示關閉啟動時 U-Boot 的打印log, 未顯式配置 debug_mode 時,按 debug_mode=8 處理。目前常用的打印等級有 0(關閉所有打?。?、1(只顯示關鍵節點打?。?、4(打印錯誤信息)、8(打印所有 log 信息)。

usb_debug 在燒錄或啟動過程中,若遇到燒錄失敗或啟動失敗大致掛死在 usb 相關模塊,但又不確定具體位置,這時可以打開usb_debug進行調試,開啟usb_debug后有關 usb 相關的運行信息會被較詳細打印出來。打開usb_debug的方式:打開usb_base.h文件,將其中的#defineSUNXI_USB_DEBUG宏定義打開,打開后重新編譯 U-Boot 并打包燒錄即可。

7 進入燒寫的方法

開機時按住 fel 鍵

開機時打開串口按住鍵盤數字’2’

進入 U-Boot 控制臺輸入efex

進入 Android 控制臺輸入 reboot efex

8 常用接口函數

8.1 fdt 相關接口

const void *fdt_getprop(const void *fdt, int nodeoffset, const char *name, int *lenp)

? 作用:檢索指定屬性的值

? 參數:

? fdt: 工作 flattened device tree

? nodeoffset: 待修改節點的偏移

? name: 待檢索的屬性名

? lenp: 檢索屬性值的長度(會被覆蓋)或者為 NULL

? 返回:

? 非空(屬性值的指針):成功

? NULL(lenp 為空):失敗

? 失敗代碼(lenp 非空):失敗

int fdt_set_node_status(void *fdt, int nodeoffset, enum fdt_status status, unsigned int error_code)

? 作用:設置節點狀態

? 參數:

? fdt: 工作 flattened device tree

? nodeoffset: 待修改節點的偏移

? status:FDT_STATUS_OKAY, FDT_STATUS_DISABLED, FDT_STATUS_FAIL, FDT_STATUS_FAIL_ERROR_CODE

? error_code:optional, only used if status is FDT_STATUS_FAIL_ERROR_CODE

? 返回:

? 0: 成功

? 非 0: 失敗

int fdt_path_offset(const void *fdt, const char *path)

? 作用:通過全路徑查找節點的偏移量

? 參數:

? fdt: 工作 fdt

? path: 全路徑名稱

? 返回:

? >=0(節點的偏移量): 成功

? <0: 失敗代碼

static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, uint32_t val)

? 作用:將屬性值設置為一個 32 位整型數值,如果屬性值不存在,則新建該屬性

? 參數:

? fdt: 工作 flattened device tree

? nodeoffset: 待修改節點的偏移

? name: 待修改的屬性名

? val:32 位目標值

? 返回:

? 0: 成功

? <0: 失敗代碼

static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, uint64_t val)

? 作用:與fdt_setprop_u32類似,將屬性值設置為一個 64 位整型數值,如果屬性值不存在,則新建該屬性

? 參數:

? fdt: 工作 flattened device tree

? nodeoffset: 待修改節點的偏移

? name: 待修改的屬性名

? val:64 位目標值

? 返回:

? 0: 成功

? <0: 失敗代碼

#define fdt_setprop_string(fdt, nodeoffset, name, str) fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)

? 作用:將屬性值設置為一個字符串,如果屬性值不存在,則新建該屬性

? 參數:

? fdt: 工作 flattened device tree

? nodeoffset: 待修改節點的偏移

? name: 待修改的屬性名

? str: 目標值

? 返回:

? 0: 成功

? <0: 失敗代碼

注意:在sys_config.fex的配置中,節點的啟用狀態為 0 或 1。轉換到 fdt 中對應的 status 屬性為disable或okay。

int save_fdt_to_flash(void *fdt_buf, size_t fdt_size)

? 作用:保存修改到 flash

? 參數:

? fdt_buf: 當前工作 flattened device tree

? fdt_size: 當前工作 flattened device tree 的大小,可以通過fdt_totalsize(fdt_buf )獲取

? 返回:

? 0: 成功

? <0: 失敗

應用參考

U-Boot 中 fdt 命令行的實現:cmd/fdt.c

8.2 env 相關接口函數

int env_set(const char *varname, const char *varvalue)

? 作用:將環境變量 varname 的值設置為 varvalue,重啟失效

? 參數:

? varname: 待設置環境變量的名稱

? varvalue: 將指定的環境變量修改為該值

? 返回:

? 0: 成功

? 非 0: 失敗

char *env_get(const char *name)

? 作用:獲取指定環境變量的值

? 參數:

? name: 變量名稱

? 返回:

? NULL: 失敗

? 非空(環境變量的值):成功

int env_save(void)

? 作用:保存環境變量,重啟仍保存

? 參數: 無

? 返回:

? 0: 成功

? 非 0: 失敗

應用參考

board/sunxi/sunxi_bootargs.c update_bootargs通過 cmdline 向 kernel 提供信息,主要是通過更新bootargs變量實現env_set("bootargs", cmdline)。

8.3 調用 U-Boot 命令行

int run_command_list(const char *cmd, int len, int flag)

? 作用:執行 U-Boot 命令行

? 參數:

? cmd: 命令字符指針

? len: 命令行長度,設置為-1 則自動獲取

? flag: 任意,因為 sunxi 中沒有用到

? 返回:

? 0: 成功

? 非 0: 失敗

應用參考:

common/autoboot.c autoboot_command實現了 U-Boot 的自動啟動命令

s = env_get("bootcmd");

run_command_list(s, -1, 0)。

8.4 Flash 的讀寫

int sunxi_flash_read(uint start_block, uint nblock, void *buffer)

? 作用:將指定起始位置start_block的nblock讀取到buffer

? 參數:

? start_block: 起始地址

? nblock:block 個數

? buffer: 內存地址

? 返回:

? 0: 成功

? 非 0: 失敗

int sunxi_flash_write(uint start_block, uint nblock, void *buffer)

? 作用:將buffer寫入指定起始位置start_block的nblock中

? 參數:

? start_block: 起始地址

? nblock:block 個數

? buffer: 內存地址

? 返回:

? 0: 成功

? 非 0: 失敗

int sunxi_sprite_read(uint start_block, uint nblock, void *buffer)

? 作用與sunxi_flash_read相似

int sunxi_sprite_write(uint start_block, uint nblock, void *buffer)

? 作用與sunxi_flash_write相似

應用參考

common/sunxi/board_helper.c sunxi_set_bootcmd_from_mis實現了對 misc 分區的讀寫操作

8.5 獲取分區信息

int sunxi_partition_get_partno_byname(const char *part_name)

? 作用:根據分區名稱獲取分區號

? 參數:

? part_name: 分區名稱

? 返回:

? <0: 失敗

? >0(分區號):成功

int sunxi_partition_get_info_byname(const char *part_name, uint *part_offset, uint *part_size)

? 作用:根據分區名稱獲取分區的偏移量和大小

? 參數:

? part_name: 分區名稱

? part_offset: 分區的偏移量

? part_size: 分區的大小

? 返回:

? 0: 成功

? -1: 失敗

uint sunxi_partition_get_offset_byname(const char *part_name)

? 作用:根據分區名稱獲取偏移量

? 參數:

? part_name: 分區名稱

? 返回:

? <=0 : 失敗

? >0 : 成功

int sunxi_partition_get_info(const char *part_name, disk_partition_t *info)

? 作用:根據part_name獲取分區信息

? 參數:

? part_name: 分區名稱

? info: 分區信息

? 返回:

? 非 0: 失敗

? 0: 成功

lbaint_t sunxi_partition_get_offset(int part_index)

? 作用:card sprite 模式下獲取分區的偏移量

? 參數:

? part_index: 分區號

? 返回:

? >=0(偏移量):成功

? -1: 失敗

應用參考

啟動時加載圖片:drivers/video/sunxi/logo_display/sunxi_load_bmp.c

8.6 GPIO 相關操作

int fdt_get_one_gpio(const char* node_path, const char* prop_name,user_gpio_set_t* gpio_list)

? 作用:根據路徑node_path和 gpio 名稱prop_name獲取 gpio 配置

? 參數:

? node_path:fdt 路徑

? prop_name:gpio 名稱

? gpio_list:待獲取的 gpio 信息

? 返回:

? 0:成功

? -1:失敗

ulong sunxi_gpio_request(user_gpio_set_t *gpio_list, __u32 group_count_max)

? 作用:根據 gpio 配置獲取 gpio 操作句柄

? 參數:

? gpio_list:gpio 配置列表,可以由fdt_get_one_gpio獲得

? group_count_max: gpio_list中最大的 gpio 配置個數

? 返回:

? 0:失敗

? >0(gpio 操作句柄):成功

__s32 gpio_write_one_pin_value(ulong p_handler, __u32 value_to_gpio, const char *gpio_name)

? 作用:根據 gpio 操作句柄寫數據

? 參數:

? p_handler:gpio 操作句柄,可由sunxi_gpio_request獲取

? value_to_gpio:待寫入數據,0 或 1

? gpio_name:gpio 名稱

? 返回:

? EGPIO_SUCCESS:成功

? EGPIO_FAIL:失敗

應用參考

操作 led 狀態:

ssprite/sprite_led.c user_gpio_set_t gpio_init; fdt_get_one_gpio("/soc/card_boot", "sprite_gpio0", &gpio_init); //獲取/soc/card_boot中sprite_gpio0的gpio配置 sprite_led_hd = sunxi_gpio_request(&gpio_init, 1); //獲取gpio操作句柄 gpio_write_one_pin_value(sprite_led_hd, sprite_led_status, "sprite_gpio0"); //操作led狀態

9 常用資源的初始化階段

? env :環境變量初始化后可以訪問

? fdt :在 U-Boot 運行開始即可訪問

? malloc :在重定位后才能訪問

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11402

    瀏覽量

    212071
  • 移植
    +關注

    關注

    1

    文章

    391

    瀏覽量

    28467
  • u-boot
    +關注

    關注

    0

    文章

    122

    瀏覽量

    38612
  • 編譯
    +關注

    關注

    0

    文章

    672

    瀏覽量

    33460
  • 開發指南
    +關注

    關注

    0

    文章

    34

    瀏覽量

    7696
收藏 人收藏

    評論

    相關推薦

    U-Boot介紹

    在移植 Linux之前我們需要先移植一個 bootloader 代碼,這個 bootloader 代碼用于啟動 Linux 內核, bootloader有很多,常用的就是 U-Boot
    的頭像 發表于 10-08 10:50 ?4456次閱讀

    U-boot的基本介紹

    從本文開始,將陸續推送“手把手教你移植U-boot”系列文章,目標是由淺入深地講解U-boot的工作流程、原理、配置方法和移植方法,手把手教你完成U-boot的移植工作,默認硬件開發
    發表于 07-14 16:52 ?3390次閱讀
    <b class='flag-5'>U-boot</b>的基本介紹

    視壯rk3288/rk3399 Rockchip《U-Boot 開發指南 V3.7》

    `視壯rk3288/rk3399 Rockchip《U-Boot 開發指南 V3.7》`
    發表于 05-05 10:12

    U-Boot的啟動及移植分析

    bootloader 開發是嵌入式系統必不可少而且十分重要的部分,U-Boot 為功能強大的bootloader 開發軟件。本文詳細分析了U-Boot 的啟動流程,并結合其源碼,闡述了
    發表于 09-01 16:34 ?27次下載

    u-boot的Makefile分析

    u-boot的Makefile分析 U-BOOT是一個LINUX下的工程,在編譯之前必須已經安裝對應體系結構的交叉編譯環境,這里只針對ARM,編譯器系列軟件為arm-linux-*。
    發表于 05-17 09:16 ?2115次閱讀

    u-boot學習指南

    u-boot 是免費的,我們做嵌入式的一般只需要使用 u-boot 即可,但如果你想成為一個比較強的嵌入式系統工程師,而且還做了自己開發板,那么還是要學習一下如果將網上下載的通用 u-boot
    發表于 11-17 15:54 ?2次下載

    u-boot簡介

    演化而來。其源碼目錄、編譯形式與Linux內核很相似,事實上,不少U-Boot源碼就是根據相應的Linux內核源程序進行簡化而形成的,尤其是一些設備的驅動程序,這從U-Boot源碼的注
    發表于 10-14 11:17 ?3656次閱讀

    DENX U-BootLinux 使用手冊

    DENX U-BootLinux 使用手冊
    發表于 10-30 09:59 ?5次下載
    DENX <b class='flag-5'>U-Boot</b>及<b class='flag-5'>Linux</b> 使用手冊

    fireflyAIO-3288J主板U-Boot使用簡介

    RK U-Boot 基于開源的 U-Boot 進行開發,工作模式有啟動加載模式和下載模式。
    的頭像 發表于 12-20 10:06 ?1684次閱讀
    fireflyAIO-3288J主板<b class='flag-5'>U-Boot</b>使用簡介

    fireflyAIO-3399J主板U-Boot使用介紹

    RK U-Boot 基于開源的 U-Boot 進行開發,工作模式有啟動加載模式和下載模式。
    的頭像 發表于 12-24 10:00 ?1844次閱讀
    fireflyAIO-3399J主板<b class='flag-5'>U-Boot</b>使用介紹

    Linux:使用 QEMU 測試 U-BOOT的步驟

    Linux:使用 QEMU 測試 U-BOOT的步驟
    的頭像 發表于 06-23 09:42 ?3551次閱讀
    <b class='flag-5'>Linux</b>:使用 QEMU 測試 <b class='flag-5'>U-BOOT</b>的步驟

    U-Boot架構淺析

    導讀:嵌入式Linux系統搭建,bootloader是必不可少的一環,而U-Boot已成嵌入式Linux事實標準。所以較為深入的分析U-Boot的設計,對于更...
    發表于 02-07 11:56 ?7次下載
    <b class='flag-5'>U-Boot</b>架構淺析

    創建自定義的u-boot命令

    為什么會有這篇文章,因為小生被u-boot源碼的設計所吸引了(源碼對命令的處理過程)。自定義u-boot命令屬于u-boot源碼的開發技術啦,可能u
    的頭像 發表于 08-08 14:46 ?1217次閱讀

    RZ/N1D-DB U-Boot and Linux 快速入門指南

    RZ/N1D-DB U-Boot and Linux 快速入門指南
    發表于 03-16 19:35 ?0次下載
    RZ/N1D-DB <b class='flag-5'>U-Boot</b> and <b class='flag-5'>Linux</b> 快速入門<b class='flag-5'>指南</b>

    RZ/N1D-DB U-Boot and Linux 快速入門指南

    RZ/N1D-DB U-Boot and Linux 快速入門指南
    發表于 07-06 20:22 ?0次下載
    RZ/N1D-DB <b class='flag-5'>U-Boot</b> and <b class='flag-5'>Linux</b> 快速入門<b class='flag-5'>指南</b>
    主站蜘蛛池模板: 久久精品国产99久久72 | 欧美一级第一免费高清 | 手机在线视频观看 | 色成人亚洲 | 久久人人网 | 日韩毛片免费在线观看 | 亚洲一区二区三区在线 | 在线免费国产视频 | 色综合天天干 | 国产黄色网 | 一级毛片免费不卡直观看 | 亚洲视频一二 | 欧美色88 | 夜夜橹橹网站夜夜橹橹 | 欧美18videosex性欧美69 | 高清一区二区在线观看 | 一级特黄特黄的大片免费 | 狠狠色噜狠狠狠狠色综合久 | 国产亚洲婷婷香蕉久久精品 | 91九色麻豆 | 欧美黄页网 | 精品99久久 | 在线观看播放视频www | 亚洲人成人网毛片在线播放 | 午夜黄色在线观看 | asian极品呦女爱爱 | 成人男女啪啪免费观看网站 | 天天夜干 | 超h高h文污肉 | 四虎影院的网址 | 在线免费视频一区二区 | 69xxx欧美| 日本理论午夜中文字幕第一页 | 加勒比黑人喝羽月希奶水 | 国产成人综合欧美精品久久 | 丁香五月缴情综合网 | 天天操操操操操操 | 毛片免费网站 | 欧美日韩色综合网站 | 色宅男看片午夜大片免费看 | 久久e|