日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

U-Boot 移植

發布時間:2023/12/10 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 U-Boot 移植 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • NXP官方開發板uboot編譯測試
    • 查找NXP官方的開發板默認配置文件_defconfig
    • 配置編譯NXP官方開發板對應的uboot
    • 燒寫驗證與驅動測試(定位缺少的驅動)
  • 在NXP官方U-Boot 中添加自己的開發板
    • 添加開發板默認配置文件
    • 添加開發板對應的頭文件(mx6ull_alientek_emmc.h)
    • 添加開發板對應的板級文件夾
    • 修改U-Boot 圖形界面配置文件
    • 使用新添加的板子配置編譯uboot
    • LCD驅動修改
    • 網絡驅動修改
    • 其他需要修改的地方
  • bootcmd和bootargs環境變量(修改mx6ull_alientek_emmc.h)
    • 環境變量bootcmd(啟動內核命令)
    • 環境變量bootargs(內核傳參)
  • uboot 啟動Linux 測試
    • 從EMMC 啟動Linux 系統
    • 從網絡啟動Linux 系統
  • DDR初始化參數修改
  • 總結

上一章節我們詳細的分析了uboot 的啟動流程,對uboot 有了一個初步的了解。

前兩章我們都是使用的正點原子提供的uboot,本章我們就來學習如何將NXP 官方的uboot 移植到正點原子的I.MX6ULL 開發板上,學習如何在uboot 中添加我們自己的板子。

NXP官方開發板uboot編譯測試

查找NXP官方的開發板默認配置文件_defconfig

uboot 的移植并不是說我們完完全全的從零開始將uboot 移植到我們現在所使用的開發板或者開發平臺上,這個工作一般是半導體廠商做的,半導體廠商負責將uboot 移植到他們的芯片上,因此半導體廠商都會自己做一個開發板,這個開發板就叫做原廠開發板,比如大家學習STM32 的時候聽說過的discover 開發板就是ST 自己做的。

半導體廠商會將uboot 移植到他們自己的原廠開發板上,測試好以后就會將這個uboot 發布出去,這就是大家常說的原廠BSP 包。我們一般做產品的時候就會參考原廠的開發板做硬件,然后在原廠提供的BSP 包上做修改,將uboot 或者linux kernel 移植到我們的硬件上。這個就是uboot 移植的一般流程:

①、在uboot 中找到參考的開發平臺,一般是原廠的開發板。
②、參考原廠開發板移植uboot 到我們所使用的開發板上。

正點原子的I.MX6ULL 開發板參考的是NXP 官方的I.MX6ULL EVK 開發板做的硬件,因此我們在移植uboot 的時候就可以以NXP 官方的I.MX6ULL EVK 開發板為藍本。

本章我們是將NXP 官方的uboot 移植到正點原子的I.MX6ULL 開發板上,NXP 官方的uboot 放到了開發板光盤中,路徑為:1、例程源碼->4、NXP 官方原版Uboot 和Linux->uboot-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2。將uboot-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2 發送到Ubuntu中并解壓,然后創建VSCode 工程。

configs 目錄下有很多跟I.MX6UL/6ULL 有關的配置如圖33.1.1.1 所示,

從圖33.1.1.1 可以看出有很多的默認配置文件,其中以mx6ul 開頭的是I.MX6UL 芯片的,mx6ull 開頭的是I.MX6ULL 開發板的。I.MX6UL/6ULL 有9x9mm 和14x14mm 兩種尺寸的,所以我們可以看到會有mx6ull_9x9 和mx6ull_14x14 開頭的默認配置文件。

我們使用的是14x14mm的芯片,所以關注mx6ull_14x14 開頭的默認配置文件。正點原子的I.MX6ULL 有EMMC 和NAND 兩個版本的,因此我們最終只需要關注mx6ull_14x14_evk_emmc_defconfig 和
mx6ull_14x14_evk_nand_defconfig 這兩個配置文件就行了。本章我們講解EMMC 版本的移植(NAND 版本移植很多類似),所以使用mx6ull_14x14_evk_emmc_defconfig 作為默認配置文件。

配置編譯NXP官方開發板對應的uboot

找到NXP 官方I.MX6ULL EVK 開發板對應的默認配置文件以后就可以配置和編譯了,使用如下命令配置uboot:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_emmc_defconfig

配置完成會生成.config文件,然后進行編譯

make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16

編譯完成以后結果如圖33.1.2.1 所示,官方提供的uboot就編譯成功了。

修改Makefile文件簡化操作:

從圖33.1.2.1 可以看出,編譯成功。我們在編譯的時候需要輸入ARCH 和CORSS_COMPILE這兩個變量的值,這樣太麻煩了。我們可以直接在頂層Makefile 中直接給ARCH 和CORSS_COMPILE 賦值,修改如圖33.1.2.2 所示(視頻里命令多一個問號):

圖33.1.2.2 中的250、251 行就是直接給ARCH 和CROSS_COMPILE 賦值,這樣我們就可以使用如下簡短的命令來編譯uboot 了:

make mx6ull_14x14_evk_emmc_defconfig make V=1 -j16

創建shell腳本簡化操作:

如果既不想修改uboot 的頂層Makefile,又想編譯的時候不用輸入那么多,那么就直接創建個shell 腳本就行了,shell 腳本名為mx6ull_14x14_emmc.sh,然后在shell 腳本里面輸入如下內容:

#!/bin/bash make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_emmc_defconfig make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16

記得給mx6ull_14x14_emmc.sh 這個文件可執行權限,使用mx6ull_14x14_emmc.sh 腳本編譯uboot 的時候每次都會清理一下工程,然后全部重新編譯,編譯的時候直接執行這個腳本就行了,命令如下:

./mx6ull_14x14_evk_emmc.sh

編譯完成以后會生成u-boot.bin、u-boot.imx 等文件,但是這些文件是NXP 官方I.MX6ULL EVK 開發板。能不能用到正點原子的I.MX6ULL 開發板上呢?試一下不就知道了!

燒寫驗證與驅動測試(定位缺少的驅動)

將imxdownload 軟件拷貝到uboot 源碼根目錄下,然后使用imxdownload 軟件將u-boot.bin燒寫到SD卡中(和前面的裸機一樣),燒寫命令如下:

chmod 777 imxdownload //給予imxdownload 可執行權限 ./imxdownload u-boot.bin /dev/sdd //燒寫到SD 卡中,不能燒寫到/dev/sda 或sda1 里面

燒寫完成以后將SD 卡插入I.MX6U-ALPHA 開發板的TF卡槽中,最后設置開發板從SD卡啟動。打開SecureCRT,設置好開發板所使用的串口并打開,復位開發板,SecureCRT 接收到如下圖33.1.3.1 所示信息:

從圖33.1.3.1 可以看出,uboot 啟動正常,雖然我們用的是NXP 官方I.MX6ULL 開發板的uboot,但是在正點原子的I.MX6ULL 開發板上是可以正常啟動的。而且DRAM 識別正確,為512MB,
注意:如果用的NAND 版本的核心版的話uboot 啟動會失敗!因為NAND 核心版用的256MB的DRAM。

1、SD 卡和EMMC 驅動檢查

檢查一下SD 卡和EMMC 驅動是否正常,使用命令mmc list 列出當前的MMC 設備,結果如圖33.1.3.2 所示:

從圖33.1.3.2 可以看出當前有兩個MMC 設備,檢查每個MMC 設備信息,先檢查MMC 設備0,輸入如下命令:

mmc dev 0 mmc info

結果如圖33.1.3.3 所示:

從圖33.1.3.3 可以看出,mmc 設備0 是SD 卡,SD 卡容量為14.8GB,這個和我所使用的SD 卡信息相符,說明SD 卡驅動正常。再來檢查MMC 設備1,輸入如下命令:

mmc dev 1 mmc info

結果如圖33.1.3.4 所示:

從圖33.1.3.4 可以看出,mmc 設備1 為EMMC,容量為3.6GB,說明EMMC 驅動也成功,SD 卡和EMMC 的驅動都沒問題。

2、LCD 驅動檢查

如果uboot 中的LCD 驅動正確的話,啟動uboot 以后LCD 上應該會顯示出NXP 的logo,如下圖33.1.3.5 所示:

如果你用的不是正點原子的4.3 寸480x272 分辨率的屏幕的話,那么LCD 就不會顯示33.1.3.5 所示logo 界面。因為NXP 官方I.MX6ULL 開發板的屏幕就是4.3 寸480x272 分辨率的,所以uboot 默認LCD 驅動是4.3 寸480x272 分辨率的。如果使用其他分辨率的LCD 就需要修改LCD 驅動,這里我們先不修改LCD 驅動,稍后我們在講解如何修改uboot 中的LCD驅動,我們只需要記得,uboot 的LCD 需要修改就行了。

3、網絡驅動

uboot 啟動的時候提示“Board Net Initialization Failed”和“No ethernet found.”這兩行,說明網絡驅動也有問題,正常情況下應該是如圖33.1.3.6 所示提示:

現在沒有圖33.1.3.6 中的信息,那更別說ping 一下ubuntu 主機了,說明當前uboot 的網絡部驅動也是有問題的,這是因為正點原子開發板的網絡芯片復位引腳和NXP 官方開發板不一樣,因此需要修改驅動。

總結一下NXP 官方I.MX6ULL EVK 開發板的ubootx在正點原子EMMC版本I.MX6ULL開發板上的運行情況:

  • ①、uboot 啟動正常,DRAM 識別正確,SD 卡和EMMC 驅動正常。
  • ②、uboot 里面的LCD 驅動默認是給4.3 寸480x272 分辨率的,如果使用的其他分辨率的屏幕需要修改驅動。
  • ③、網絡不能工作,識別不出來網絡信息,需要修改驅動。

接下來我們要做的工作如下:

  • ①、前面我們一直使用著NXP 官方開發板的uboot 配置,接下來需要在uboot 中添加我們自己的開發板,也就是正點原子的I.MX6ULL 開發板。
  • ②、解決LCD 驅動和網絡驅動的問題。

在NXP官方U-Boot 中添加自己的開發板

NXP 官方uboot 中默認都是NXP 自己的開發板,雖說我們可以直接在官方的開發板上直接修改,使uboot 可以完整的運行在我們的板子上。但是從學習的角度來講,這樣我們就不能了解到uboot 是如何添加新平臺的。接下來我們就參考NXP 官方的I.MX6ULL EVK 開發板,學習如何在uboot 中添加我們的開發板或者開發平臺。

添加開發板默認配置文件

先在configs 目錄下創建默認配置文件,復制mx6ull_14x14_evk_emmc_defconfig,然后重
命名為mx6ull_alientek_emmc_defconfig,命令如下:

cd configs cp mx6ull_14x14_evk_emmc_defconfig mx6ull_alientek_emmc_defconfig

然后將文件mx6ull_alientek_emmc_defconfig 中的內容改成下面的:

CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=board/freescale/mx6ull_alientek_emmc/imximage.cfg,MX6ULL_EVK_EMMC_REWORK" CONFIG_ARM=y CONFIG_ARCH_MX6=y CONFIG_TARGET_MX6ULL_ALIENTEK_EMMC=y CONFIG_CMD_GPIO=y

可以看出,mx6ull_alientek_emmc_defconfig 基本和mx6ull_14x14_evk_emmc_defconfig 中的內容一樣,只是第1 行和第4 行做了修改(改成正點原子ALIENTEK板子自己定義的名字)。

添加開發板對應的頭文件(mx6ull_alientek_emmc.h)

前面講的_defconfig配置文件的配置項很少,就5行,配置的還不夠,重點是mx6ull_alientek_emmc.h里面對應的配置文件。每一個板子都有一個這樣對應的 .h和 .c 配置文件。

在目錄include/configs 下添加I.MX6ULL-ALPHA 開發板對應的頭文件,復制
include/configs/mx6ullevk.h,并重命名為mx6ull_alientek_emmc.h,命令如下:

cp include/configs/mx6ullevk.h mx6ull_alientek_emmc.h

拷貝完成以后將:

#ifndef __MX6ULLEVK_CONFIG_H #define __MX6ULLEVK_CONFIG_H

改為:

#ifndef __MX6ULL_ALIENTEK_EMMC_CONFIG_H #define __MX6ULL_ALIENTEK_EMMC_CONFIG_H

mx6ull_alientek_emmc.h 里面有很多宏定義,這些宏定義基本用于配置uboot,也有一些I.MX6ULL 的配置項目。如果我們自己要想使能或者禁止uboot 的某些功能,那就在mx6ull_alientek_emmc.h 里面做修改即可。mx6ull_alientek_emmc.h 里面的內容比較多,去掉一些用不到的配置,精簡后的內容如下:

1 /* 2 * Copyright (C) 2016 Freescale Semiconductor, Inc. 3 * 4 * Configuration settings for the Freescale i.MX6UL 14x14 EVK board. 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 #ifndef __MX6ULL_ALEITENK_EMMC_CONFIG_H 9 #define __MX6ULL_ALEITENK_EMMC_CONFIG_H 10 11 12 #include <asm/arch/imx-regs.h> 13 #include <linux/sizes.h> 14 #include "mx6_common.h" 15 #include <asm/imx-common/gpio.h> 16 ...... 28 29 #define is_mx6ull_9x9_evk() CONFIG_IS_ENABLED(TARGET_MX6ULL_9X9_EVK) 30 31 #ifdef CONFIG_TARGET_MX6ULL_9X9_EVK 32 #define PHYS_SDRAM_SIZE SZ_256M 33 #define CONFIG_BOOTARGS_CMA_SIZE "cma=96M " 34 #else 35 #define PHYS_SDRAM_SIZE SZ_512M 36 #define CONFIG_BOOTARGS_CMA_SIZE "" 37 /* DCDC used on 14x14 EVK, no PMIC */ 38 #undef CONFIG_LDO_BYPASS_CHECK 39 #endif 40 41 /* SPL options */ 42 /* We default not support SPL 43 * #define CONFIG_SPL_LIBCOMMON_SUPPORT 44 * #define CONFIG_SPL_MMC_SUPPORT 45 * #include "imx6_spl.h" 46 */ 47 48 #define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG 49 50 #define CONFIG_DISPLAY_CPUINFO 51 #define CONFIG_DISPLAY_BOARDINFO 52 53 /* Size of malloc() pool */ 54 #define CONFIG_SYS_MALLOC_LEN (16 * SZ_1M) 55 56 #define CONFIG_BOARD_EARLY_INIT_F 57 #define CONFIG_BOARD_LATE_INIT 58 59 #define CONFIG_MXC_UART 60 #define CONFIG_MXC_UART_BASE UART1_BASE 61 62 /* MMC Configs */ 63 #ifdef CONFIG_FSL_USDHC 64 #define CONFIG_SYS_FSL_ESDHC_ADDR USDHC2_BASE_ADDR 65 66 /* NAND pin conflicts with usdhc2 */ 67 #ifdef CONFIG_SYS_USE_NAND 68 #define CONFIG_SYS_FSL_USDHC_NUM 1 69 #else 70 #define CONFIG_SYS_FSL_USDHC_NUM 2 71 #endif 72 #endif 73 74 /* I2C configs */ 75 #define CONFIG_CMD_I2C 76 #ifdef CONFIG_CMD_I2C 77 #define CONFIG_SYS_I2C 78 #define CONFIG_SYS_I2C_MXC 79 #define CONFIG_SYS_I2C_MXC_I2C1 /* enable I2C bus 1 */ 80 #define CONFIG_SYS_I2C_MXC_I2C2 /* enable I2C bus 2 */ 81 #define CONFIG_SYS_I2C_SPEED 100000 82 ...... 89 90 #define CONFIG_SYS_MMC_IMG_LOAD_PART 1 91 92 #ifdef CONFIG_SYS_BOOT_NAND 93 #define CONFIG_MFG_NAND_PARTITION "mtdparts=gpmi-nand:64m(boot),16m(kernel),16m(dtb),1m(misc),-(rootfs) " 94 #else 95 #define CONFIG_MFG_NAND_PARTITION "" 96 #endif 97 98 #define CONFIG_MFG_ENV_SETTINGS \ 99 "mfgtool_args=setenv bootargs console=${console},${baudrate} " \ ...... 111 "bootcmd_mfg=run mfgtool_args;bootz ${loadaddr} ${initrd_addr} ${fdt_addr};\0" \ 112 113 #if defined(CONFIG_SYS_BOOT_NAND) 114 #define CONFIG_EXTRA_ENV_SETTINGS \ 115 CONFIG_MFG_ENV_SETTINGS \ 116 "panel=TFT43AB\0" \ ...... 126 "bootz ${loadaddr} - ${fdt_addr}\0" 127 128 #else 129 #define CONFIG_EXTRA_ENV_SETTINGS \ 130 CONFIG_MFG_ENV_SETTINGS \ 131 "script=boot.scr\0" \ ...... 202 "fi;\0" \ 203 204 #define CONFIG_BOOTCOMMAND \ 205 "run findfdt;" \ ...... 216 "else run netboot; fi" 217 #endif 218 219 /* Miscellaneous configurable options */ 220 #define CONFIG_CMD_MEMTEST 221 #define CONFIG_SYS_MEMTEST_START 0x80000000 222 #define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_MEMTEST_START + 0x8000000) 223 224 #define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR 225 #define CONFIG_SYS_HZ 1000 226 227 #define CONFIG_STACKSIZE SZ_128K 228 229 /* Physical Memory Map */ 230 #define CONFIG_NR_DRAM_BANKS 1 231 #define PHYS_SDRAM MMDC0_ARB_BASE_ADDR 232 233 #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM 234 #define CONFIG_SYS_INIT_RAM_ADDR IRAM_BASE_ADDR 235 #define CONFIG_SYS_INIT_RAM_SIZE IRAM_SIZE 236 237 #define CONFIG_SYS_INIT_SP_OFFSET \ 238 (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE) 239 #define CONFIG_SYS_INIT_SP_ADDR \ 240 (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET) 241 242 /* FLASH and environment organization */ 243 #define CONFIG_SYS_NO_FLASH 244 ...... 255 256 #define CONFIG_SYS_MMC_ENV_DEV 1 /* USDHC2 */ 257 #define CONFIG_SYS_MMC_ENV_PART 0 /* user area */ 258 #define CONFIG_MMCROOT "/dev/mmcblk1p2" /* USDHC2 */ 259 260 #define CONFIG_CMD_BMODE 261 ...... 275 276 /* NAND stuff */ 277 #ifdef CONFIG_SYS_USE_NAND 278 #define CONFIG_CMD_NAND 279 #define CONFIG_CMD_NAND_TRIMFFS 280 281 #define CONFIG_NAND_MXS 282 #define CONFIG_SYS_MAX_NAND_DEVICE 1 283 #define CONFIG_SYS_NAND_BASE 0x40000000 284 #define CONFIG_SYS_NAND_5_ADDR_CYCLE 285 #define CONFIG_SYS_NAND_ONFI_DETECTION 286 287 /* DMA stuff, needed for GPMI/MXS NAND support */ 288 #define CONFIG_APBH_DMA 289 #define CONFIG_APBH_DMA_BURST 290 #define CONFIG_APBH_DMA_BURST8 291 #endif 292 293 #define CONFIG_ENV_SIZE SZ_8K 294 #if defined(CONFIG_ENV_IS_IN_MMC) 295 #define CONFIG_ENV_OFFSET (12 * SZ_64K) 296 #elif defined(CONFIG_ENV_IS_IN_SPI_FLASH) 297 #define CONFIG_ENV_OFFSET (768 * 1024) 298 #define CONFIG_ENV_SECT_SIZE (64 * 1024) 299 #define CONFIG_ENV_SPI_BUS CONFIG_SF_DEFAULT_BUS 300 #define CONFIG_ENV_SPI_CS CONFIG_SF_DEFAULT_CS 301 #define CONFIG_ENV_SPI_MODE CONFIG_SF_DEFAULT_MODE 302 #define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED 303 #elif defined(CONFIG_ENV_IS_IN_NAND) 304 #undef CONFIG_ENV_SIZE 305 #define CONFIG_ENV_OFFSET (60 << 20) 306 #define CONFIG_ENV_SECT_SIZE (128 << 10) 307 #define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE 308 #endif 309 310 311 /* USB Configs */ 312 #define CONFIG_CMD_USB 313 #ifdef CONFIG_CMD_USB 314 #define CONFIG_USB_EHCI 315 #define CONFIG_USB_EHCI_MX6 316 #define CONFIG_USB_STORAGE 317 #define CONFIG_EHCI_HCD_INIT_AFTER_RESET 318 #define CONFIG_USB_HOST_ETHER 319 #define CONFIG_USB_ETHER_ASIX 320 #define CONFIG_MXC_USB_PORTSC (PORT_PTS_UTMI | PORT_PTS_PTW) 321 #define CONFIG_MXC_USB_FLAGS 0 322 #define CONFIG_USB_MAX_CONTROLLER_COUNT 2 323 #endif 324 325 #ifdef CONFIG_CMD_NET 326 #define CONFIG_CMD_PING 327 #define CONFIG_CMD_DHCP 328 #define CONFIG_CMD_MII 329 #define CONFIG_FEC_MXC 330 #define CONFIG_MII 331 #define CONFIG_FEC_ENET_DEV 1 332 333 #if (CONFIG_FEC_ENET_DEV == 0) 334 #define IMX_FEC_BASE ENET_BASE_ADDR 335 #define CONFIG_FEC_MXC_PHYADDR 0x2 336 #define CONFIG_FEC_XCV_TYPE RMII 337 #elif (CONFIG_FEC_ENET_DEV == 1) 338 #define IMX_FEC_BASE ENET2_BASE_ADDR 339 #define CONFIG_FEC_MXC_PHYADDR 0x1 340 #define CONFIG_FEC_XCV_TYPE RMII 341 #endif 342 #define CONFIG_ETHPRIME "FEC" 343 344 #define CONFIG_PHYLIB 345 #define CONFIG_PHY_MICREL 346 #endif 347 348 #define CONFIG_IMX_THERMAL 349 350 #ifndef CONFIG_SPL_BUILD 351 #define CONFIG_VIDEO 352 #ifdef CONFIG_VIDEO 353 #define CONFIG_CFB_CONSOLE 354 #define CONFIG_VIDEO_MXS 355 #define CONFIG_VIDEO_LOGO 356 #define CONFIG_VIDEO_SW_CURSOR 357 #define CONFIG_VGA_AS_SINGLE_DEVICE 358 #define CONFIG_SYS_CONSOLE_IS_IN_ENV 359 #define CONFIG_SPLASH_SCREEN 360 #define CONFIG_SPLASH_SCREEN_ALIGN 361 #define CONFIG_CMD_BMP 362 #define CONFIG_BMP_16BPP 363 #define CONFIG_VIDEO_BMP_RLE8 364 #define CONFIG_VIDEO_BMP_LOGO 365 #define CONFIG_IMX_VIDEO_SKIP 366 #endif 367 #endif 368 369 #define CONFIG_IOMUX_LPSR 370 ...... 375 #endif

從示例代碼33.2.2.1 可以看出,mx6ull_alientek_emmc.h 文件中基本都是“CONFIG_”開頭的宏定義,這也說明mx6ull_alientek_emmc.h 文件的主要功能就是配置或者裁剪uboot。如果需要某個功能的話就在里面添加這個功能對應的CONFIG_XXX 宏即可,如果不需要某個功能的話就刪除掉對應的宏即可。我們以示例代碼33.2.2.1 為例,詳細的看一下mx6ull_alientek_emmc.h
中這些宏都是什么功能。

第14 行,添加了頭文件mx6_common.h,如果在mx6ull_alientek_emmc.h 中沒有發現有配置某個功能或命令,但是實際卻存在的話,可以到mx6_common.h 文件里面去找一下。

第29~39 行,設置DRAM的大小,宏PHYS_SDRAM_SIZE 就是板子上DRAM 的大小,如果用的NXP 官方的9X9 EVK 開發板的話DRAM 大小就為256MB。否則的話默認為512MB,正點原子的I.MX6U-ALPHA 開發板用的是512MB DDR3。

第50 行,定義宏CONFIG_DISPLAY_CPUINFO,uboot 啟動的時候可以輸出CPU信息

第51 行,定義宏CONFIG_DISPLAY_BOARDINFO,uboot 啟動的時候可以輸出板子信息

第54 行,CONFIG_SYS_MALLOC_LEN 為malloc內存池大小,這里設置為16MB。

第56 行,定義宏CONFIG_BOARD_EARLY_INIT_F,這樣board_init_f 函數就會調用board_early_init_f 函數。

第57 行,定義宏CONFIG_BOARD_LATE_INIT ,這樣board_init_r 函數就會調用board_late_init 函數。

第59、60 行,使能I.MX6ULL 的串口功能,宏CONFIG_MXC_UART_BASE 表示串口寄存器基地址,這里使用的串口1,基地址為UART1_BASE,UART1_BASE 定義在文件arch/arm/include/asm/arch-mx6/imx-regs.h 中,imx-regs.h 是I.MX6ULL 寄存器描述文件,根據imx-regs.h 可得到UART1_BASE 的值如下:

UART1_BASE= (ATZ1_BASE_ADDR + 0x20000)=AIPS1_ARB_BASE_ADDR + 0x20000=0x02000000 + 0x20000=0X02020000

查閱I.MX6ULL 參考手冊,UART1 的寄存器基地址正是0X02020000,如圖33.2.2.1 所示:

第63、64 行,EMMC 接在I.MX6ULL 的USDHC2 上,宏CONFIG_SYS_FSL_ESDHC_ADDR為EMMC 所使用接口的寄存器基地址,也就是USDHC2(EMMC)的基地址,查看核心板如下圖所示:

第67~72 行,跟NAND 相關的宏,因為NAND 和USDHC2 的引腳是共用的,因此如果使用NAND 的只能使用一個USDHC 設備(SD 卡)。如果沒有使用NAND,那么就有兩個USDHC 設備(EMMC 和SD 卡),宏CONFIG_SYS_FSL_USDHC_NUM 表示USDHC 數量。EMMC 版本的
核心版沒有用到NAND,所以CONFIG_SYS_FSL_USDHC_NUM=2。

第75~81,和I2C有關的宏定義,用于控制使能哪個I2C,I2C 的速度為多少。

第92~96 行,NAND 的分區設置,如果使用NAND 的話,默認的NAND 分區為:"mtdparts=gpmi-nand:64m(boot),16m(kernel),16m(dtb),1m(misc),-(rootfs) ",分區結果如表33.2.2.1所示:

NAND 的分區是可以調整的,比如boot 分區我們用不了64M 這么大,因此可以將其改小,其他的分區一樣的。

第98~111 行,宏CONFIG_MFG_ENV_SETTINGS 定義了一些環境變量,使用MfgTool 燒寫系統時候會用到這里面的環境變量。

第113~202 行,通過條件編譯來設置宏CONFIG_EXTRA_ENV_SETTINGS ,宏CONFIG_EXTRA_ENV_SETTINGS 也是設置一些環境變量,此宏會設置bootargs 這個環境變量,后面我們會詳細分析這個宏定義。

第204~217 行,設置宏CONFIG_BOOTCOMMAND,此宏就是設置環境變量bootcmd 的值。后面會詳細的分析這個宏定義。

第220~222 行,設置命令memtest 相關宏定義,比如使能命令memtest,設置memtest 測試的內存起始地址和內存大小。

第224 行,宏CONFIG_SYS_LOAD_ADDR 表示linux kernel 在DRAM 中的加載地址,也就是linux kernel 在DRAM 中的存儲首地址,CONFIG_LOADADDR=0X80800000。

第225 行,宏CONFIG_SYS_HZ 為系統時鐘頻率,這里為1000Hz。

第227 行,宏CONFIG_STACKSIZE 為棧大小,這里為128KB。

第230 行,宏CONFIG_NR_DRAM_BANKS 為DRAM BANK 的數量,I.MX6ULL 只有一個DRAM BANK,我們也只用到了一個BANK,所以為1。

第231 行,宏PHYS_SDRAM 為I.MX6ULL 的DRAM 控制器MMDC0 所管轄的DRAM 范圍起始地址,也就是0X80000000。

第233 行,宏CONFIG_SYS_SDRAM_BASE 為DRAM 的起始地址。

第234 行,宏CONFIG_SYS_INIT_RAM_ADDR 為I.MX6ULL 內部IRAM 的起始地址(也就是OCRAM 的起始地址),為0X00900000。

第235 行,宏CONFIG_SYS_INIT_RAM_SIZE 為I.MX6ULL 內部IRAM 的大小(OCRAM的大小),為0X00040000=128KB。

第237~240 行,宏CONFIG_SYS_INIT_SP_OFFSET 和CONFIG_SYS_INIT_SP_ADDR 與初始SP 有關,第一個為初始SP 偏移,第二個為初始SP 地址。

第256 行,宏CONFIG_SYS_MMC_ENV_DEV 為默認的MMC 設備,這里默認為USDHC2,也就是EMMC。

第257 行,宏CONFIG_SYS_MMC_ENV_PART 為模式分區,默認為第0 個分區。

第258 行,宏CONFIG_MMCROOT 設置進入linux 系統的根文件系統所在的分區,這里設置為"/dev/mmcblk1p2",也就是EMMC 設備的第2 個分區。第0 個分區保存uboot,第1 個分區保存linux 鏡像和設備樹,第2 個分區為Linux 系統的根文件系統。

第277~291 行,與NAND 有關的宏定義,如果使用NAND 的話。

第293 行,宏CONFIG_ENV_SIZE 為環境變量大小,默認為8KB。

第294~308 行,宏CONFIG_ENV_OFFSET 為環境變量偏移地址,這里的偏移地址是相對于存儲器的首地址。如果環境變量保存在EMMC 中的話,環境變量偏移地址為12* 64KB。如果環境變量保存在SPI FLASH 中的話,偏移地址為768*1024。如果環境變量保存在NAND 中的話,偏移地址為60<<20(60MB),并且重新設置環境變量的大小為128KB。

第312~323 行,與USB 相關的宏定義。

第325~342 行,與網絡相關的宏定義,比如使能dhcp、ping 等命令。第331 行的宏CONFIG_FEC_ENET_DEV 指定uboot 所使用的網口,I.MX6ULL 有兩個網口,為0 的時候使用ENET1,為1 的時候使用ENET2。宏IMX_FEC_BASE 為ENET 接口的寄存器首地址,宏
CONFIG_FEC_MXC_PHYADDR 為網口PHY 芯片的地址。宏CONFIG_FEC_XCV_TYPE 為PHY 芯片所使用的接口類型,I.MX6U-ALPHA 開發板的兩個PHY 都使用的RMII 接口。

第344~END,剩下的都是一些配置宏,比如CONFIG_VIDEO 宏用于開啟LCD,CONFIG_VIDEO_LOGO 使能LOGO 顯示,CONFIG_CMD_BMP 使能BMP 圖片顯示指令。這樣就可以在uboot 中顯示圖片了,一般用于顯示logo

關于mx6ull_alientek_emmc.h 就講解到這里,其中以CONFIG_CMD 開頭的宏都是用于使能相應命令的,其他的以CONFIG 開頭的宏都是完成一些配置功能的。以后會頻繁的和mx6ull_alientek_emmc.h 這個文件打交道。

添加開發板對應的板級文件夾

uboot 中每個板子都有一個對應的文件夾來存放板級文件,比如開發板上外設驅動文件等等。NXP 的I.MX 系列芯片的所有板級文件夾都存放在board/freescale 目錄下,在這個目錄下有個名為mx6ullevk 的文件夾,這個文件夾就是NXP 官方I.MX6ULL EVK 開發板的板級文件夾。復制mx6ullevk,將其重命名為mx6ull_alientek_emmc,命令如下:

cd board/freescale/ cp mx6ullevk/ -r mx6ull_alientek_emmc

進入mx6ull_alientek_emmc 目錄中,將其中的mx6ullevk.c 文件重命名為
mx6ull_alientek_emmc.c,命令如下:

cd mx6ull_alientek_emmc mv mx6ullevk.c mx6ull_alientek_emmc.c

我們還需要對mx6ull_alientek_emmc 目錄下的文件做一些修改:

1、修改mx6ull_alientek_emmc 目錄下的Makefile 文件
將mx6ull_alientek_emmc 下的Makefile 文件內容改為如下所示:

1 # (C) Copyright 2015 Freescale Semiconductor, Inc. 2 # 3 # SPDX-License-Identifier: GPL-2.0+ 4 # 5 6 obj-y := mx6ull_alientek_emmc.o 7 8 extra-$(CONFIG_USE_PLUGIN) := plugin.bin 9 $(obj)/plugin.bin: $(obj)/plugin.o 10 $(OBJCOPY) -O binary --gap-fill 0xff $< $@

重點是第6 行的obj-y,改為mx6ull_alientek_emmc.o,這樣才會編譯mx6ull_alientek_emmc.c這個文件。

2、修改mx6ull_alientek_emmc 目錄下的imximage.cfg 文件
將imximage.cfg 中的下面一句:

PLUGIN board/freescale/mx6ullevk/plugin.bin 0x00907000

改為:

PLUGIN board/freescale/mx6ull_alientek_emmc /plugin.bin 0x00907000

3、修改mx6ull_alientek_emmc 目錄下的Kconfig 文件
修改Kconfig 文件,修改后的內容如下:

1 if TARGET_MX6ULL_ALIENTEK_EMMC 2 3 config SYS_BOARD 4 default "mx6ull_alientek_emmc" 5 6 config SYS_VENDOR 7 default "freescale" 8 9 config SYS_SOC 10 default "mx6" 11 12 config SYS_CONFIG_NAME 13 default "mx6ull_alientek_emmc" 14 15 endif

4、修改mx6ull_alientek_emmc 目錄下的MAINTAINERS 文件修改MAINTAINERS 文件,修改后的內容如下:

1 MX6ULL_ALIENTEK_EMMC BOARD 2 M: Peng Fan <peng.fan@nxp.com> 3 S: Maintained 4 F: board/freescale/mx6ull_alientek_emmc/ 5 F: include/configs/mx6ull_alientek_emmc.h

修改U-Boot 圖形界面配置文件

uboot 是支持圖形界面配置,關于uboot 的圖形界面配置下一章會詳細的講解。修改文件arch/arm/cpu/armv7/mx6/Kconfig(如果用的I.MX6UL 的話,應該修改arch/arm/Kconfig 這個文件),在207 行加入如下內容:

1 config TARGET_MX6ULL_ALIENTEK_EMMC 2 bool "Support mx6ull_alientek_emmc" 3 select MX6ULL 4 select DM 5 select DM_THERMAL

在最后一行的endif 的前一行添加如下內容:

source "board/freescale/mx6ull_alientek_emmc/Kconfig"

添加完成以后的Kconfig 文件如圖33.2.4.1 所示:

到此為止,I.MX6U-ALPHA 開發板就已經添加到uboot 中了,接下來就是編譯這個新添加的開發板。

使用新添加的板子配置編譯uboot

在uboot 根目錄下新建一個名為mx6ull_alientek_emmc.sh 的shell 腳本,在這個shell 腳本里面輸入如下內容:

1 #!/bin/bash 2 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean 3 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- (加空格) mx6ull_alientek_emmc_defconfig 4 make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16

第3 行我們使用的默認配置文件就是33.2.1 節中新建的mx6ull_alientek_emmc_defconfig 這個配置文件。給予mx6ll_alientek_emmc.sh 可執行權限,然后運行腳本來完成編譯,命令如下:

chmod 777 mx6ull_alientek_emmc.sh //給予可執行權限,一次即可 ./mx6ull_alientek_emmc.sh //運行腳本編譯uboot

等待編譯完成,編譯完成以后輸入如下命令,查看一下33.2.2 小節中添加的
mx6ull_alientek_emmc.h 這個頭文件有沒有被引用。

grep -nR "mx6ull_alientek_emmc.h"

如果有很多文件都引用了mx6ull_alientek_emmc.h 這個頭文件,那就說明新板子添加成功,如圖33.2.5.1 所示:

編譯完成以后就使用imxdownload 將新編譯出來的u-boot.bin 燒寫到SD 卡中測試,SecureCRT 輸出結果如圖33.2.5.2 所示:

從圖33.2.5.1 可以看出,此時的Board 還是“MX6ULL 14x14 EVK”,因為我們參考的NXP官方的I.MX6ULL 開發板來添加自己的開發板。如果接了LCD 屏幕的話會發現LCD 屏幕并沒有顯示NXP 的logo,而且從圖33.2.5.1 可以看出此時的網絡同樣也沒識別出來。前面已經說了,默認uboot 中的LCD 驅動和網絡驅動在正點原子的I.MX6U-ALPHA 開發板上是有問題的,需要修改。

LCD驅動修改

一般uboot 中修改驅動基本都是在xxx.h 和xxx.c 這兩個文件中進行的,xxx 為板子名稱,比如mx6ull_alientek_emmc.h 和mx6ull_alientek_emmc.c 這兩個文件。

一般修改LCD 驅動重點注意以下幾點:

  • ①、LCD 所使用的GPIO,查看uboot中LCD 的IO 配置是否正確。
  • ②、LCD 背光引腳GPIO 的配置。
  • ③、LCD 配置參數是否正確。

正點原子的I.MX6U-ALPHA 開發板LCD 原理圖和NXP 官方I.MX6ULL 開發板一致,也就是LCD 的IO 和背光IO 都一樣的,所以IO部分就不用修改了。

需要修改的之后LCD參數,打開文件mx6ull_alientek_emmc.c,找到如下所示內容:

struct display_info_t const displays[] = {{.bus = MX6UL_LCDIF1_BASE_ADDR,.addr = 0,.pixfmt = 24,.detect = NULL,.enable = do_enable_parallel_lcd,.mode = {.name = "TFT43AB",.xres = 480,.yres = 272,.pixclock = 108695,.left_margin = 8,.right_margin = 4,.upper_margin = 2,.lower_margin = 4,.hsync_len = 41,.vsync_len = 10,.sync = 0,.vmode = FB_VMODE_NONINTERLACED} } };

示例代碼33.2.6.1 中定義了一個變量displays,類型為display_info_t,這個結構體是LCD信息結構體,其中包括了LCD 的分辨率像素格式,LCD 的各個參數等。display_info_t 定義在文件arch/arm/include/asm/imx-common/video.h 中,定義如下:

struct display_info_t {int bus;int addr;int pixfmt;int (*detect)(struct display_info_t const *dev);void (*enable)(struct display_info_t const *dev);struct fb_videomode mode;};

pixfmt 是像素格式,也就是一個像素點是多少位,如果是RGB565 的話就是16 位,如果是888 的話就是24 位,一般使用RGB888。
結構體display_info_t 還有個mode 成員變量,此成員變量也是個結構體,為fb_videomode,定義在文件include/linux/fb.h 中,定義如下:

struct fb_videomode {const char *name; /* optional */u32 refresh; /* optional */u32 xres;u32 yres;u32 pixclock;u32 left_margin;u32 right_margin;u32 upper_margin;u32 lower_margin;u32 hsync_len;u32 vsync_len;u32 sync;u32 vmode;u32 flag;};

結構體fb_videomode 里面的成員變量為LCD 的參數,這些成員變量函數如下(和前面裸機一致):

  • name:LCD 名字,要和環境變量中的panel 相等。
  • xres、yres:LCD X 軸和Y 軸像素數量。
  • pixclock:像素時鐘,每個像素時鐘周期的長度,單位為皮秒。
  • left_margin:HBP,水平同步后肩。
  • right_margin:HFP,水平同步前肩。
  • upper_margin:VBP,垂直同步后肩。
  • lower_margin:VFP,垂直同步前肩。
  • hsync_len:HSPW,行同步脈寬。
  • vsync_len:VSPW,垂直同步脈寬。
  • vmode:大多數使用FB_VMODE_NONINTERLACED,也就是不使用隔行掃描。

可以看出,這些參數和我們第二十四章講解裸機RGB LCD 的時候參數基本一樣,唯一不同的像素時鐘pixclock 的含義不同,以正點原子的7 寸1024*600 分辨率的屏幕(ATK7016)為例,屏幕要求的像素時鐘為51.2MHz,因此:

pixclock=(1/51200000)*10^12=19531

在根據其他的屏幕參數,可以得出ATK7016 屏幕的配置參數如下:

struct display_info_t const displays[] = {{.bus = MX6UL_LCDIF1_BASE_ADDR,.addr = 0,.pixfmt = 24,.detect = NULL,.enable = do_enable_parallel_lcd,.mode = {.name = "TFT7016",//名字可自定義.xres = 1024,.yres = 600,.pixclock = 19531,.left_margin = 140, //HBPD.right_margin = 160, //HFPD.upper_margin = 20, //VBPD.lower_margin = 12, //VFBD.hsync_len = 20, //HSPW.vsync_len = 3, //VSPW.sync = 0,.vmode = FB_VMODE_NONINTERLACED} } };

使用示例代碼33.2.6.4 中的屏幕參數替換掉mx6ull_alientek_emmc.c 中uboot 默認的屏幕參數。
打開mx6ull_alientek_emmc.h,找到所有如下語句:

panel=TFT43AB

將其改為:

panel=TFT7016

也就是設置panel 為TFT7016,panel 的值要與示例代碼33.2.6.4 中的.name 成員變量的值一致。修改完成以后重新編譯一遍uboot 并燒寫到SD 中啟動。

重啟以后LCD 驅動一般就會工作正常了,LCD 上回顯示NXP 的logo。但是有可能會遇到LCD 并沒有工作,還是黑屏,這是什么原因呢?在uboot 命令模式輸入“print”來查看環境變量panel 的值,會發現panel 的值要是TFT43AB(或其他的,反正不是TFT7016),如圖33.2.6.1所示:

這是因為之前有將環境變量保存到EMMC 中,uboot 啟動以后會先從EMMC 中讀取環境變量,如果EMMC 中沒有環境變量的話才會使用mx6ull_alientek_emmc.h 中的默認環境變量。

如果EMMC 中的環境變量panel 不等于TFT7016,那么LCD 顯示肯定不正常,我們只需要在uboot 中修改panel 的值為TFT7016 即可,在uboot 的命令模式下輸入如下命令:

setenv panel TFT7016 saveenv

上述命令修改環境變量panel 為TFT7016,然后保存,重啟uboot,此時LCD 驅動就工作正常了。如果LCD 還是沒有正常工作的,那就要檢查自己哪里有沒有改錯,或者還有哪里沒有修改。

網絡驅動修改

1、I.MX6U-ALPHA 開發板網絡簡介

I.MX6UL/ULL 內部有個以太網MAC 外設,也就是ENET,需要外接一個PHY 芯片來實現有線網絡通信功能,也就是內部MAC+外部PHY芯片的方案。

大家可能聽過DM9000 這個網絡芯片,在一些沒有內部MAC 的CPU 中,比如三星的2440,4412 等,就會采用DM9000 來實現聯網功能。DM9000 提供了一個類似SRAM 的訪問接口,主控CPU 通過這個接口即可與DM9000 進行通信,DM9000就是一個MAC+PHY 芯片。這個方案就相當于外部MAC+外部PHY。

那么I.MX6U 這樣的內部MAC+PHY 芯片與DM9000 方案比有什么優勢嗎?那優勢大了去了!首先就是通信效率和速度,一般SOC 內部的MAC 是帶有一個專用DMA 的,專門用于處理網絡數據包,采用SRAM 來讀寫DM9000 的速度是壓根就沒法和內部MAC+外部PHY 芯片的速度比。采用外部DM9000 完全是無奈之舉,誰讓2440,4412 這些芯片內部沒有以太網外設呢,現在又想用有線網絡,沒有辦法只能找個DM9000 的方案。從這里也可以看出,三星的2440、4412 這些芯片設計之初就不是給工業產品用的,他們是給消費類電子使用的,比如手機、平板等,手機或平板要上網,可以通過WIFI 或者4G,我是沒有見過哪個手機或者平板上網是要接根網線的。正點原子的I.MX6U-ALPHA 開發板也可以通過WIFI 或者4G 上網,這個是后話了。

I.MX6UL/ULL 有兩個網絡接口ENET1 和ENET2,正點原子的I.MX6U-ALPHA 開發板提供了這兩個網絡接口,其中ENET1 和ENET2 都使用LAN8720A作為PHY 芯片。NXP 官方的I.MX6ULL EVK 開發板使用KSZ8081 這顆PHY 芯片,LAN8720A 相比KSZ8081 具有體積小、外圍器件少、價格便宜等優點。

直接使用KSZ8081 固然可以,但是我們在實際的產品中不一定會使用KSZ8081,有時候為了降低成本會選擇其他的PHY 芯片,這個時候就有個問題:換了PHY 芯片以后網絡驅動怎么辦?為此,正點原子的I.MX6U-ALPHA 開發板將ENET1 和ENET2的PHY 換成了LAN8720A,這樣就可以給大家講解更換PHY 芯片以后如何調整網絡驅動,使網絡工作正常。

  • 先來看一下I.MX6U-ALPHA 開發板ENET1 的網絡原理圖如圖33.2.7.1 所示:

    ENET1 的網絡PHY 芯片為LAN8720A,通過RMII 接口與I.MX6ULL 相連,正點原子I.MX6U-ALPHA 開發板的ENET1 引腳與NXP 官方的I.MX6ULL EVK 開發板基本一樣,唯獨復位引腳不同。從圖33.2.7.1 可以看出,正點原子I.MX6U-ALPHA 開發板的ENET1 復位引腳ENET1_RST 接到了I.M6ULL 的SNVS_TAMPER7 這個引腳上。

LAN8720A 內部是有寄存器的,I.MX6ULL 會讀取LAN8720 內部寄存器來判斷當前的物理鏈接狀態、連接速度(10M 還是100M)和雙工狀態(半雙工還是全雙工)。I.MX6ULL 通過MDIO接口來讀取PHY 芯片的內部寄存器,MDIO 接口有兩個引腳,ENET_MDC 和ENET_MDIO,ENET_MDC 提供時鐘,ENET_MDIO 進行數據傳輸。

一個MDIO 接口可以管理32 個PHY 芯片,同一個MDIO 接口下的這些PHY 使用不同的器件地址來做區分,MIDO 接口通過不同的器件地址即可訪問到相應的PHY 芯片。I.MX6U-ALPHA 開發板ENET1 上連接的LAN8720A器件地址為0X0(引腳接下拉即可確定),所示我們要修改ENET1 網絡驅動的話重點就三點:

①、ENET1 復位引腳初始化(每個LAN8720A都有一個復位引腳)。
②、LAN8720A 的器件ID。
③、LAN8720 驅動

  • 再來看一下ENET2 的原理圖,如圖33.2.7.2 所示:

    關于ENET2 網絡驅動的修改也注意一下三點:
    ①、ENET2 的復位引腳,從圖33.2.7.2 可以看出,ENET2 的復位引腳ENET2_RST 接到了I.MX6ULL 的SNVS_TAMPER8 上。
    ②、ENET2 所使用的PHY 芯片器件地址,從圖33.2.7.2 可以看出,PHY 器件地址為0X1。
    ③、LAN8720 驅動,ENET1 和ENET2 都使用的LAN8720,所以驅動肯定是一樣的(一般國際規定所有的PHY芯片前16寄存器都要一樣,所以驅動都是通用的,Linux內核通用驅動也是如此)。

2、網絡PHY地址修改

首先修改uboot 中的ENET1 和ENET2 的PHY 地址和驅動,打開mx6ull_alientek_emmc.h這個文件,找到如下代碼:

325 #ifdef CONFIG_CMD_NET 326 #define CONFIG_CMD_PING 327 #define CONFIG_CMD_DHCP 328 #define CONFIG_CMD_MII 329 #define CONFIG_FEC_MXC 330 #define CONFIG_MII 331 #define CONFIG_FEC_ENET_DEV 1 332 333 #if (CONFIG_FEC_ENET_DEV == 0) 334 #define IMX_FEC_BASE ENET_BASE_ADDR 335 #define CONFIG_FEC_MXC_PHYADDR 0x2 336 #define CONFIG_FEC_XCV_TYPE RMII 337 #elif (CONFIG_FEC_ENET_DEV == 1) 338 #define IMX_FEC_BASE ENET2_BASE_ADDR 339 #define CONFIG_FEC_MXC_PHYADDR 0x1 340 #define CONFIG_FEC_XCV_TYPE RMII 341 #endif 342 #define CONFIG_ETHPRIME "FEC" 343 344 #define CONFIG_PHYLIB 345 #define CONFIG_PHY_MICREL 346 #endif

第331 行的宏CONFIG_FEC_ENET_DEV 用于選擇使用哪個網口,默認為1,也就是選擇ENET2。第335 行為ENET1 的PHY 地址,默認是0X2,第339 行為ENET2 的PHY 地址,默認為0x1。根據前面的分析可知,正點原子的I.MX6U-ALPHA 開發板ENET1 的PHY 地址為0X0,ENET2 的PHY 地址為0X1,所以需要將第335 行的宏CONFIG_FEC_MXC_PHYADDR改為0x0。

第345 行定了一個宏CONFIG_PHY_MICREL,此宏用于使能uboot 中Micrel 公司的PHY驅動,KSZ8081 這顆PHY 芯片就是Micrel 公司生產的,不過Micrel 已經被Microchip 收購了。

如果要使用LAN8720A,那么就得將CONFIG_PHY_MICREL 改為CONFIG_PHY_SMSC,也就是使能uboot 中的SMSC 公司中的PHY 驅動,因為LAN8720A 就是SMSC 公司生產的。所以示例代碼33.2.7.1 有三處要修改:

①、修改ENET1 網絡PHY 的地址。
②、修改ENET2 網絡PHY 的地址。
③、使能SMSC 公司的PHY 驅動。

修改后的網絡PHY 地址參數如下所示:

325 #ifdef CONFIG_CMD_NET 326 #define CONFIG_CMD_PING 327 #define CONFIG_CMD_DHCP 328 #define CONFIG_CMD_MII 329 #define CONFIG_FEC_MXC 330 #define CONFIG_MII 331 #define CONFIG_FEC_ENET_DEV 1 332 333 #if (CONFIG_FEC_ENET_DEV == 0) 334 #define IMX_FEC_BASE ENET_BASE_ADDR 335 #define CONFIG_FEC_MXC_PHYADDR 0x0 336 #define CONFIG_FEC_XCV_TYPE RMII 337 #elif (CONFIG_FEC_ENET_DEV == 1) 338 #define IMX_FEC_BASE ENET2_BASE_ADDR 339 #define CONFIG_FEC_MXC_PHYADDR 0x1 340 #define CONFIG_FEC_XCV_TYPE RMII 341 #endif 342 #define CONFIG_ETHPRIME "FEC" 343 344 #define CONFIG_PHYLIB 345 #define CONFIG_PHY_SMSC 346 #endif

3、刪除uboot 中74LV595 的驅動代碼

uboot 中網絡PHY 芯片地址修改完成以后就是網絡復位引腳的驅動修改了,打開mx6ull_alientek_emmc.c,找到如下代碼:

#define IOX_SDI IMX_GPIO_NR(5, 10) #define IOX_STCP IMX_GPIO_NR(5, 7) #define IOX_SHCP IMX_GPIO_NR(5, 11) #define IOX_OE IMX_GPIO_NR(5, 8)

示例代碼33.2.7.3 中以IOX 開頭的宏定義是74LV595 的相關GPIO,因為NXP 官方I.MX6ULL EVK 開發板使用74LV595 來擴展IO,兩個網絡的復位引腳就是由74LV595 來控制的。正點原子的I.MX6U-ALPHA 開發板并沒有使用74LV595,因此我們將示例代碼33.2.7.3 中的代碼刪除掉,替換為如下所示代碼:

#define ENET1_RESET IMX_GPIO_NR(5, 7) #define ENET2_RESET IMX_GPIO_NR(5, 8)

ENET1 的復位引腳連接到SNVS_TAMPER7 上,對應GPIO5_IO07,ENET2 的復位引腳連接到SNVS_TAMPER8 上,對應GPIO5_IO08。

繼續在mx6ull_alientek_emmc.c 中找到如下代碼:

static iomux_v3_cfg_t const iox_pads[] = {/* IOX_SDI */MX6_PAD_BOOT_MODE0__GPIO5_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL),/* IOX_SHCP */MX6_PAD_BOOT_MODE1__GPIO5_IO11 | MUX_PAD_CTRL(NO_PAD_CTRL),/* IOX_STCP */MX6_PAD_SNVS_TAMPER7__GPIO5_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL),/* IOX_nOE */MX6_PAD_SNVS_TAMPER8__GPIO5_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL), };

同理,示例代碼33.2.7.5 是74LV595 的IO 配置參數結構體,將其刪除掉。繼續在mx6ull_alientek_emmc.c 中找到函數iox74lv_init,如下所示:

static void iox74lv_init(void) {int i;gpio_direction_output(IOX_OE, 0);for (i = 7; i >= 0; i--) {gpio_direction_output(IOX_SHCP, 0);gpio_direction_output(IOX_SDI, seq[qn_output[i]][0]);udelay(500);gpio_direction_output(IOX_SHCP, 1);udelay(500);} ...... /* * shift register will be output to pins */gpio_direction_output(IOX_STCP, 1); }; void iox74lv_set(int index) {int i;for (i = 7; i >= 0; i--) {gpio_direction_output(IOX_SHCP, 0);if (i == index)gpio_direction_output(IOX_SDI, seq[qn_output[i]][0]);elsegpio_direction_output(IOX_SDI, seq[qn_output[i]][1]);udelay(500);gpio_direction_output(IOX_SHCP, 1);udelay(500);} ...... /* * shift register will be output to pins */ gpio_direction_output(IOX_STCP, 1); };

iox74lv_init 函數是74LV595 的初始化函數,iox74lv_set 函數用于控制74LV595 的IO 輸出電平,將這兩個函數全部刪除掉!

在mx6ull_alientek_emmc.c 中找到board_init 函數,此函數是板子初始化函數,會被board_init_r 調用,board_init 函數內容如下:

int board_init(void) {......imx_iomux_v3_setup_multiple_pads(iox_pads, ARRAY_SIZE(iox_pads));iox74lv_init();......return 0; }

board_init 會調用imx_iomux_v3_setup_multiple_pads 和iox74lv_init 這兩個函數來初始化74lv595 的GPIO,將這兩行刪除掉。

至此,mx6ull_alientek_emmc.c 中關于74LV595 芯片的驅動代碼都刪除掉了,接下來就是添加I.MX6U-ALPHA 開發板兩個網絡復位引腳了。

4、添加I.MX6U-ALPHA 開發板網絡復位引腳驅動

在mx6ull_alientek_emmc.c 中找到如下所示代碼:

640 static iomux_v3_cfg_t const fec1_pads[] = { 641 MX6_PAD_GPIO1_IO06__ENET1_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL), 642 MX6_PAD_GPIO1_IO07__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL), ...... 649 MX6_PAD_ENET1_RX_ER__ENET1_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL), 650 MX6_PAD_ENET1_RX_EN__ENET1_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL), 651 }; 652 653 static iomux_v3_cfg_t const fec2_pads[] = { 654 MX6_PAD_GPIO1_IO06__ENET2_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL), 655 MX6_PAD_GPIO1_IO07__ENET2_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL), ...... 664 MX6_PAD_ENET2_RX_EN__ENET2_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL), 665 MX6_PAD_ENET2_RX_ER__ENET2_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL), 666 };

結構體數組fec1_pads 和fec2_pads 是ENET1 和ENET2 這兩個網口的IO 配置參數,在這兩個數組中添加兩個網口的復位IO 配置參數,完成以后如下所示:

640 static iomux_v3_cfg_t const fec1_pads[] = { 641 MX6_PAD_GPIO1_IO06__ENET1_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL), 642 MX6_PAD_GPIO1_IO07__ENET1_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL), ...... 649 MX6_PAD_ENET1_RX_ER__ENET1_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL), 650 MX6_PAD_ENET1_RX_EN__ENET1_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL), 651 MX6_PAD_SNVS_TAMPER7__GPIO5_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL), 652 }; 653 654 static iomux_v3_cfg_t const fec2_pads[] = { 655 MX6_PAD_GPIO1_IO06__ENET2_MDIO | MUX_PAD_CTRL(MDIO_PAD_CTRL), 656 MX6_PAD_GPIO1_IO07__ENET2_MDC | MUX_PAD_CTRL(ENET_PAD_CTRL), ...... 665 MX6_PAD_ENET2_RX_EN__ENET2_RX_EN | MUX_PAD_CTRL(ENET_PAD_CTRL), 666 MX6_PAD_ENET2_RX_ER__ENET2_RX_ER | MUX_PAD_CTRL(ENET_PAD_CTRL), 667 MX6_PAD_SNVS_TAMPER8__GPIO5_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL), 668 };

示例代碼33.2.7.9 中,第651 行和667 行分別是ENET1 和ENET2 的復位IO 配置參數。

繼續在文件mx6ull_alientek_emmc.c 中找到函數setup_iomux_fec,此函數默認代碼如下:

668 static void setup_iomux_fec(int fec_id) 669 { 670 if (fec_id == 0) 671 imx_iomux_v3_setup_multiple_pads(fec1_pads, 672 ARRAY_SIZE(fec1_pads)); 673 else 674 imx_iomux_v3_setup_multiple_pads(fec2_pads, 675 ARRAY_SIZE(fec2_pads)); 676 }

函數setup_iomux_fec 就是根據fec1_pads 和fec2_pads 這兩個網絡IO 配置數組來初始化I.MX6ULL 的網絡IO。

我們需要在其中添加網絡復位IO 的初始化代碼,并且復位一下PHY 芯片,修改后的setup_iomux_fec 函數如下:

668 static void setup_iomux_fec(int fec_id) 669 { 670 if (fec_id == 0) 671 { 672 673 imx_iomux_v3_setup_multiple_pads(fec1_pads, 674 ARRAY_SIZE(fec1_pads)); 675 676 gpio_direction_output(ENET1_RESET, 1); 677 gpio_set_value(ENET1_RESET, 0); 678 mdelay(20); 679 gpio_set_value(ENET1_RESET, 1); 680 } 681 else 682 { 683 imx_iomux_v3_setup_multiple_pads(fec2_pads, 684 ARRAY_SIZE(fec2_pads)); 685 gpio_direction_output(ENET2_RESET, 1); 686 gpio_set_value(ENET2_RESET, 0); 687 mdelay(20); 688 gpio_set_value(ENET2_RESET, 1); 689 } 690 }

示例代碼33.2.7.11 中第676 行~679 行和第685 行~688 行分別對應ENET1 和ENET2 的復位IO 初始化,將這兩個IO 設置為輸出并且硬件復位一下LAN8720A,這個硬件復位很重要!否則可能導致uboot 無法識別LAN8720A。

5、修改drivers/net/phy/phy.c 文件中的函數genphy_update_link

大功基本上告成,還差最后一步,uboot 中的LAN8720A 驅動有點問題,打開文件drivers/net/phy/phy.c,找到函數genphy_update_link,這是個通用PHY 驅動函數,此函數用于更新PHY 的連接狀態和速度。使用LAN8720A 的時候需要在此函數中添加一些代碼,修改后的函數genphy_update_link 如下所示:

221 int genphy_update_link(struct phy_device *phydev) 222 { 223 unsigned int mii_reg; 224 225 #ifdef CONFIG_PHY_SMSC 226 static int lan8720_flag = 0; 227 int bmcr_reg = 0; 228 if (lan8720_flag == 0) { 229 bmcr_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR); 230 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); 231 while(phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR) & 0X8000) { 232 udelay(100); 233 } 234 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, bmcr_reg); 235 lan8720_flag = 1; 236 } 237 #endif 238 239 /* 240 * Wait if the link is up, and autonegotiation is in progress 241 * (ie - we're capable and it's not done) 242 */ 243 mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); ...... 291 292 return 0; 293 }

225 行~ 237 行就是新添加的代碼,為條件編譯代碼段,只有使用SMSC 公司的PHY 這段代碼才會執行(目前只測試了LAN8720A,SMSC 公司其他的芯片還未測試)。第229 行讀取LAN8720A 的BMCR 寄存器(寄存器地址為0),此寄存器為LAN8720A 的配置寄存器,這里先讀取此寄存器的默認值并保存起來。230 行向寄存器BMCR 寄存器寫入BMCR_RESET(值為0X8000),因為BMCR 的bit15 是軟件復位控制位,因此230 行就是軟件復位(軟復位)LAN8720A,復位完成以后此位會自動清零。第231~233 行等待LAN8720A 軟件復位完成,也就是判斷BMCR的bit15 位是否為1,為1 的話表示還沒有復位完成。第234 行重新向BMCR 寄存器寫入以前的值,也就是229 行讀出的那個值。

至此網絡的復位引腳驅動修改完成,重新編譯uboot,然后將u-boot.bin 燒寫到SD 卡中并啟動,uboot 啟動信息如圖33.2.7.3 所示:

從圖33.2.6.4 中可以看到“Net:FEC1”這一行,提示當前使用的FEC1 這個網口,也就是ENET2。在uboot 中使用網絡之前要先設置幾個環境變量,命令如下:

setenv ipaddr 192.168.1.55 //開發板IP 地址 setenv ethaddr b8:ae:1d:01:00:00 //開發板網卡MAC 地址 setenv gatewayip 192.168.1.1 //開發板默認網關 setenv netmask 255.255.255.0 //開發板子網掩碼 setenv serverip 192.168.1.250 //服務器地址,也就是Ubuntu 地址 saveenv //保存環境變量

設置好環境變量以后就可以在uboot 中使用網絡了,用網線將I.MX6U-ALPHA 上的ENET2與電腦或者路由器連接起來,保證開發板和電腦在同一個網段內,通過ping 命令來測試一下網絡連接,命令如下:

ping 192.168.1.250

結果如圖33.2.7.4 所示:

從圖33.2.7.4 可以看出,有“host 192.168.1.250 is alive”這句,說明ping 主機成功,說明ENET2 網絡工作正常。

再來測試一下ENET1 的網絡是否正常工作,打開mx6ull_alientek_emmc.h,將CONFIG_FEC_ENET_DEV 改為0,然后重新編譯一下uboot 并燒寫到SD 卡中重啟。重啟開發板,uboot 輸出信息如圖33.2.7.5 所示:

從圖33.2.7.5 可以出,有“Net:FEC0”這一行,說明當前使用的FEC0 這個網卡,也就是ENET1,同樣的ping 一下主機,結果如圖33.2.7.5 所示:

從圖33.2.7.6 可以看出,ping 主機也成功,說明ENET1 網絡也工作正常,至此,I.MX6U-ALPHA 開發板的兩個網絡都工作正常了,建議大家將ENET2 設置為uboot 的默認網卡!也就是將宏CONFIG_FEC_ENET_DEV 設置為1。

其他需要修改的地方

在uboot 啟動信息中會有“Board: MX6ULL 14x14 EVK”這一句,也就是說板子名字為“MX6ULL 14x14 EVK”,要將其改為我們所使用的板子名字,比如“MX6ULL ALIENTEKEMMC”或者“MX6ULL ALIENTEK NAND”。打開文件mx6ull_alientek_emmc.c,找到函數checkboard,將其改為如下所示內容:

int checkboard(void) {if (is_mx6ull_9x9_evk())puts("Board: MX6ULL 9x9 EVK\n");elseputs("Board: MX6ULL ALIENTEK EMMC\n");return 0; }

修改完成以后重新編譯uboot 并燒寫到SD 卡中驗證,uboot 啟動信息如圖33.2.8.1 所示:

從圖33.2.8.1 可以看出,Board 變成了“MX6ULL ALIENTEK EMMC”。至此uboot 的驅動部分就修改完成了,uboot 移植也完成了。

uboot 的最終目的就是啟動Linux 內核,所以需要通過啟動Linux 內核來判斷uboot 移植是否成功。在啟動Linux 內核之前我們先來學習兩個重要的環境變量bootcmd 和bootargs。

bootcmd和bootargs環境變量(修改mx6ull_alientek_emmc.h)

uboot 中有兩個非常重要的環境變量bootcmd 和bootargs,接下來看一下這兩個環境變量。

bootcmd 和bootagrs 是采用類似shell 腳本語言編寫的,里面有很多的變量引用,這些變量其實都是環境變量,有很多是NXP 自己定義的。

文件mx6ull_alientek_emmc.h 中的宏CONFIG_EXTRA_ENV_SETTINGS 保存著這些環境變量的默認值,內容如下:

前面講的_defconfig配置文件的配置項很少,就5行,配置的還不夠,重點是mx6ull_alientek_emmc.h里面對應的配置文件。每一個板子都有一個這樣對應的 .h和 .c 配置文件,上一節添加開發板對應的頭文件已經講過了。

113 #if defined(CONFIG_SYS_BOOT_NAND) 114 #define CONFIG_EXTRA_ENV_SETTINGS \ 115 CONFIG_MFG_ENV_SETTINGS \ 116 "panel=TFT43AB\0" \ 117 "fdt_addr=0x83000000\0" \ 118 "fdt_high=0xffffffff\0" \ ...... 126 "bootz ${loadaddr} - ${fdt_addr}\0" 127 128 #else 129 #define CONFIG_EXTRA_ENV_SETTINGS \ 130 CONFIG_MFG_ENV_SETTINGS \ 131 "script=boot.scr\0" \ 132 "image=zImage\0" \ 133 "console=ttymxc0\0" \ 134 "fdt_high=0xffffffff\0" \ 135 "initrd_high=0xffffffff\0" \ 136 "fdt_file=undefined\0" \ ...... 194 "findfdt="\ 195 "if test $fdt_file = undefined; then " \ 196 "if test $board_name = EVK && test $board_rev = 9X9; then " \ 197 "setenv fdt_file imx6ull-9x9-evk.dtb; fi; " \ 198 "if test $board_name = EVK && test $board_rev = 14X14; then " \ 199 "setenv fdt_file imx6ull-14x14-evk.dtb; fi; " \ 200 "if test $fdt_file = undefined; then " \ 201 "echo WARNING: Could not determine dtb to use; fi; " \ 202 "fi;\0" \

宏CONFIG_EXTRA_ENV_SETTINGS 是個條件編譯語句,使用NAND 和EMMC 的時候宏CONFIG_EXTRA_ENV_SETTINGS 的值是不同的。

環境變量bootcmd(啟動內核命令)

bootcmd 在前面已經說了很多次了,bootcmd 保存著uboot 默認命令,uboot 倒計時結束以后就會執行bootcmd 中的命令。這些命令一般都是用來啟動Linux 內核的,比如讀取EMMC 或者NAND Flash 中的Linux 內核鏡像文件和設備樹文件到DRAM 中,然后啟動Linux 內核。

可以在uboot 啟動以后進入命令行設置bootcmd 環境變量的值。如果EMMC 或者NAND 中沒有保存bootcmd 的值,那么uboot 就會使用默認的值,板子第一次運行uboot 的時候都會使用默認值來設置bootcmd 環境變量。打開文件include/env_default.h,在此文件中有如下所示內容(之所以內容這么多,是為了兼容性):

13 #ifdef DEFAULT_ENV_INSTANCE_EMBEDDED 14 env_t environment __PPCENV__ = { 15 ENV_CRC, /* CRC Sum */ 16 #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT 17 1, /* Flags: valid */ 18 #endif 19 { 20 #elif defined(DEFAULT_ENV_INSTANCE_STATIC) 21 static char default_environment[] = { 22 #else 23 const uchar default_environment[] = { 24 #endif 25 #ifdef CONFIG_ENV_CALLBACK_LIST_DEFAULT 26 ENV_CALLBACK_VAR "=" CONFIG_ENV_CALLBACK_LIST_DEFAULT "\0" 27 #endif 28 #ifdef CONFIG_ENV_FLAGS_LIST_DEFAULT 29 ENV_FLAGS_VAR "=" CONFIG_ENV_FLAGS_LIST_DEFAULT "\0" 30 #endif 31 #ifdef CONFIG_BOOTARGS 32 "bootargs=" CONFIG_BOOTARGS "\0" 33 #endif 34 #ifdef CONFIG_BOOTCOMMAND 35 "bootcmd=" CONFIG_BOOTCOMMAND "\0" 36 #endif 37 #ifdef CONFIG_RAMBOOTCOMMAND 38 "ramboot=" CONFIG_RAMBOOTCOMMAND "\0" 39 #endif 40 #ifdef CONFIG_NFSBOOTCOMMAND 41 "nfsboot=" CONFIG_NFSBOOTCOMMAND "\0" 42 #endif 43 #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) 44 "bootdelay=" __stringify(CONFIG_BOOTDELAY) "\0" 45 #endif 46 #if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0) 47 "baudrate=" __stringify(CONFIG_BAUDRATE) "\0" 48 #endif 49 #ifdef CONFIG_LOADS_ECHO 50 "loads_echo=" __stringify(CONFIG_LOADS_ECHO) "\0" 51 #endif 52 #ifdef CONFIG_ETHPRIME 53 "ethprime=" CONFIG_ETHPRIME "\0" 54 #endif 55 #ifdef CONFIG_IPADDR 56 "ipaddr=" __stringify(CONFIG_IPADDR) "\0" 57 #endif 58 #ifdef CONFIG_SERVERIP 59 "serverip=" __stringify(CONFIG_SERVERIP) "\0" 60 #endif 61 #ifdef CONFIG_SYS_AUTOLOAD 62 "autoload=" CONFIG_SYS_AUTOLOAD "\0" 63 #endif 64 #ifdef CONFIG_PREBOOT 65 "preboot=" CONFIG_PREBOOT "\0" 66 #endif 67 #ifdef CONFIG_ROOTPATH 68 "rootpath=" CONFIG_ROOTPATH "\0" 69 #endif 70 #ifdef CONFIG_GATEWAYIP 71 "gatewayip=" __stringify(CONFIG_GATEWAYIP) "\0" 72 #endif 73 #ifdef CONFIG_NETMASK 74 "netmask=" __stringify(CONFIG_NETMASK) "\0" 75 #endif 76 #ifdef CONFIG_HOSTNAME

第13~23 行,這段代碼是個條件編譯,由于沒有定義
DEFAULT_ENV_INSTANCE_EMBEDDED 和CONFIG_SYS_REDUNDAND_ENVIRONMENT,
因此uchar default_environment[]數組保存環境變量。

在示例代碼33.3.1.1 中指定了很多環境變量的默認值,比如bootcmd 的默認值就是CONFIG_BOOTCOMMAND ,bootargs 的默認值就是CONFIG_BOOTARGS。我們可以在mx6ull_alientek_emmc.h 文件中通過設置宏CONFIG_BOOTCOMMAND 來設置bootcmd 的默認值,NXP 官方設置的CONFIG_BOOTCOMMAND 值如下:

204 #define CONFIG_BOOTCOMMAND \ 205 "run findfdt;" \ 206 "mmc dev ${mmcdev};" \ 207 "mmc dev ${mmcdev}; if mmc rescan; then " \ 208 "if run loadbootscript; then " \ 209 "run bootscript; " \ 210 "else " \ 211 "if run loadimage; then " \ 212 "run mmcboot; " \ 213 "else run netboot; " \ 214 "fi; " \ 215 "fi; " \ 216 "else run netboot; fi"

看起來很復雜的樣子!因為uboot 使用了類似shell 腳本語言的方式來編寫的,我們一行一行來分析。

第205 行,run findfdt;使用的是uboot 的run 命令來運行findfdt,findfdt 是NXP 自行添加的環境變量。findfdt 是用來查找開發板對應的設備樹文件(.dtb)。IMX6ULL EVK 的設備樹文件為imx6ull-14x14-evk.dtb,findfdt 內容如下:

"findfdt="\ "if test $fdt_file = undefined; then " \ "if test $board_name = EVK && test $board_rev = 9X9; then " \ "setenv fdt_file imx6ull-9x9-evk.dtb; fi; " \ "if test $board_name = EVK && test $board_rev = 14X14; then " \ "setenv fdt_file imx6ull-14x14-evk.dtb; fi; " \ "if test $fdt_file = undefined; then " \ "echo WARNING: Could not determine dtb to use; fi; " \ "fi;\0" \

findfdt 里面用到的變量有fdt_file,board_name,board_rev,這三個變量內容如下(啟動UBOOT就會顯示這些環境變量):

fdt_file=undefined,board_name=EVK,board_rev=14X14

findfdt 做的事情就是判斷,fdt_file 是否為undefined,如果fdt_file 為undefined 的話那就要根據板子信息得出所需的.dtb 文件名。此時fdt_file 為undefined,所以根據board_name 和board_rev 來判斷實際所需的.dtb 文件,如果board_name 為EVK 并且board_rev=9x9 的話fdt_file
就為imx6ull-9x9-evk.dtb。如果board_name 為EVK 并且board_rev=14x14 的話fdt_file 就設置為imx6ull-14x14-evk.dtb。因此IMX6ULL EVK 板子的設備樹文件就是imx6ull-14x14-evk.dtb,因此run findfdt 的結果就是設置fdt_file 為imx6ull-14x14-evk.dtb。

第206 行,mmc dev ${mmcdev}用于切換mmc 設備,mmcdev 為1,因此這行代碼就是:mmc dev 1,也就是切換到EMMC 上。

第207 行,先執行mmc dev ${mmcdev}切換到EMMC 上,然后使用命令mmc rescan 掃描看有沒有SD 卡或者EMMC 存在,如果沒有的話就直接跳到216 行,執行run netboot,netboot也是一個自定義的環境變量,這個變量是從網絡啟動Linux 的。如果mmc 設備存在的話就從mmc 設備啟動

第208 行,運行loadbootscript 環境變量,此環境變量內容如下:

loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};

其中mmcdev=1,mmcpart=1,loadaddr=0x80800000,script= boot.scr,因此展開以后就是:

loadbootscript=fatload mmc 1:1 0x80800000 boot.scr;

loadbootscript 就是從mmc1 的分區1 中讀取文件boot.src 到DRAM 的0X80800000 處。但是mmc1 的分區1 中沒有boot.src 這個文件,可以使用命令“ls mmc 1:1”查看一下mmc1 分區1 中的所有文件,看看有沒有boot.src 這個文件。

第209 行,如果加載boot.src 文件成功的話就運行bootscript 環境變量,bootscript 的內容如下:

bootscript=echo Running bootscript from mmc ...; source

因為boot.src 文件不存在,所以bootscript 也就不會運行。

第211 行,如果loadbootscript 沒有找到boot.src 的話就運行環境變量loadimage,環境變量loadimage 內容如下:

loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}

其中mmcdev=1,mmcpart=1,loadaddr=0x80800000,image = zImage,展開以后就是:

loadimage=fatload mmc 1:1 0x80800000 zImage

可以看出loadimage 就是從mmc1 的分區中讀取zImage 到內存的0X80800000 處,而mmc1的分區1 中存在zImage。

第212 行,加載linux 鏡像文件zImage 成功以后就運行環境變量mmcboot,否則的話運行netboot 環境變量。mmcboot 環境變量如下:

154 "mmcboot=echo Booting from mmc ...; " \ 155 "run mmcargs; " \ 156 "if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \ 157 "if run loadfdt; then " \ 158 "bootz ${loadaddr} - ${fdt_addr}; " \ 159 "else " \ 160 "if test ${boot_fdt} = try; then " \ 161 "bootz; " \ 162 "else " \ 163 "echo WARN: Cannot load the DT; " \ 164 "fi; " \ 165 "fi; " \ 166 "else " \ 167 "bootz; " \ 168 "fi;\0" \

第154 行,輸出信息“Booting from mmc …”。

第155 行,運行環境變量mmcargs,mmcargs 用來設置bootargs,后面分析bootargs 的時候在學習。

第156 行,判斷boot_fdt 是否為yes 或者try,根據uboot 輸出的環境變量信息可知boot_fdt=try。因此會執行157 行的語句。

第157 行,運行環境變量loadfdt,環境變量loadfdt 定義如下:

loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}

展開以后就是:

loadfdt=fatload mmc 1:1 0x83000000 imx6ull-14x14-evk.dtb

因此loadfdt 的作用就是從mmc1 的分區1 中讀取imx6ull-14x14-evk.dtb 文件并放到0x83000000處。

第158 行,如果讀取.dtb 文件成功的話那就調用命令bootz 啟動linux,調用方法如下:

bootz ${loadaddr} - ${fdt_addr};

展開就是:

bootz 0x80800000 - 0x83000000 (注意‘-’前后要有空格)

至此Linux 內核啟動,如此復雜的設置就是為了從EMMC 中讀取zImage 鏡像文件和設備樹文件。經過分析,濃縮出來的僅僅是4 行精華:

mmc dev 1 //切換到EMMC fatload mmc 1:1 0x80800000 zImage //讀取zImage 到0x80800000 處 fatload mmc 1:1 0x83000000 imx6ull-14x14-evk.dtb //讀取設備樹到0x83000000 處 bootz 0x80800000 - 0x83000000 //啟動Linux

NXP 官方將CONFIG_BOOTCOMMAND 寫的這么復雜只有一個目的:為了兼容多個板子,所以寫了個很復雜的腳本。

當我們明確知道我們所使用的板子的時候就可以大幅簡化宏CONFIG_BOOTCOMMAND 的設置,比如我們要從EMMC 啟動,那么宏CONFIG_BOOTCOMMAND 就可簡化為:

#define CONFIG_BOOTCOMMAND \"mmc dev 1;" \"fatload mmc 1:1 0x80800000 zImage;" \"fatload mmc 1:1 0x83000000 imx6ull-alientek-emmc.dtb;" \"bootz 0x80800000 - 0x83000000;"

或者可以直接在uboot 中設置bootcmd 的值,這個值就是保存到EMMC 中的,命令如下:

setenv bootcmd 'mmc dev 1; fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000;'

環境變量bootargs(內核傳參)

bootargs 保存著uboot 傳遞給Linux 內核的參數,在上一小節講解bootcmd 的時候說過,bootargs 環境變量是由mmcargs 設置的,mmcargs 環境變量如下:

mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}

其中console=ttymxc0,baudrate=115200,mmcroot=/dev/mmcblk1p2 rootwait rw,因此將mmcargs 展開以后就是:

mmcargs=setenv bootargs console= ttymxc0, 115200 root= /dev/mmcblk1p2 rootwait rw

可以看出環境變量mmcargs 就是設置bootargs 的值為“console= ttymxc0, 115200 root= /dev/mmcblk1p2 rootwait rw”,bootargs 就是設置了很多的參數的值,這些參數Linux 內核會使用到,常用的參數有:

1、console(控制臺)
console 用來設置linux 終端(或者叫控制臺),也就是通過什么設備來和Linux 進行交互,是串口還是LCD 屏幕?如果是串口的話應該是串口幾等等。一般設置串口作為Linux 終端,這樣我們就可以在電腦上通過SecureCRT 來和linux 交互了。這里設置console 為ttymxc0,因為linux啟動以后I.MX6ULL 的串口1 在linux 下的設備文件就是/dev/ttymxc0,在Linux 下,一切皆文件。

ttymxc0 后面有個“,115200”,這是設置串口的波特率,console=ttymxc0,115200 綜合起來就是設置ttymxc0(也就是串口1)作為Linux 的終端,并且串口波特率設置為115200。

2、root
root 用來設置根文件系統的位置,root=/dev/mmcblk1p2 用于指明根文件系統存放在mmcblk1 設備的分區2 中。
EMMC 版本的核心板啟動linux 以后會存在/dev/mmcblk0、
/dev/mmcblk1、/dev/mmcblk0p1、/dev/mmcblk0p2、/dev/mmcblk1p1 和/dev/mmcblk1p2 這樣的文件:

/dev/mmcblkx(x=0~ n)表示mmc 設備, /dev/mmcblkxpy(x=0~ n,y=1~n)表示mmc 設備x 的分區y。

在I.MX6U-ALPHA 開發板中/dev/mmcblk1 表示EMMC,而/dev/mmcblk1p2 表示EMMC 的分區2。

root 后面有“rootwait rw”,rootwait 表示等待mmc 設備初始化完成以后再掛載,否則的話mmc 設備還沒初始化完成就掛載根文件系統會出錯的。rw 表示根文件系統是可讀可寫的,不加rw 的話可能無法在根文件系統中進行寫操作,只能進行讀操作。

3、rootfstype
此選項一般配置root 一起使用,rootfstype 用于指定根文件系統類型,如果根文件系統為ext 格式的話此選項無所謂。如果根文件系統是yaffs、jffs 或ubifs 的話就需要設置此選項,指定根文件系統的類型。

bootargs 常設置的選項就這三個,后面遇到其他選項的話再講解。

uboot 啟動Linux 測試

uboot 已經移植好了,bootcmd 和bootargs 這兩個重要的環境變量也講解了,接下來就要測試一下uboot 能不能完成它的工作:啟動Linux 內核。
我們測試兩種啟動Linux 內核的方法,一種是直接從EMMC 啟動,一種是從網絡啟動。

從EMMC 啟動Linux 系統

上面是手動方式一行一行命令實現的,下面的是使用環境變量命令自定執行的。

從EMMC 啟動也就是將編譯出來的Linux 鏡像文件zImage 和設備樹文件保存在EMMC中,uboot 從EMMC 中讀取這兩個文件并啟動,這個是我們產品最終的啟動方式。

EMMC一共三個分區:
第一個分區:UBOOT
第二個分區:zImage和.dtb設備樹(FAT文件系統)
第三個分區:根文件系統

但是我們目前還沒有講解如何移植linux 和設備樹文件,以及如何將zImage 和設備樹文件保存到EMMC中。不過大家拿到手的I.MX6U-ALPHA 開發板(EMMC 版本)已經將zImage 文件和設備樹(.dtb)文件燒寫到了EMMC 中,所以我們可以直接讀取來測試。

設置從EMMC啟動:

mmc dev 1

檢查一下EMMC 的分區1 中有沒有zImage 文件和設備樹文件,輸入命令“ls mmc 1:1”,結果如圖33.4.1.1 所示:


從圖33.4.1.1 中可以看出,此時EMMC 分區1 中存在zimage 和imx6ull-alientek-emmc.dtb這兩個文件,所以我們可以測試新移植的uboot 能不能啟動linux 內核。

設置bootargs 和bootcmd這兩個環境變量,設置如下:

setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw' setenv bootcmd 'mmc dev 1; fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000;' saveenv

設置好以后直接輸入boot,或者run bootcmd 即可啟動Linux 內核,如果Linux 內核啟動成功的話就會輸出如圖33.4.1.2 所示的啟動信息:

從網絡啟動Linux 系統

從網絡啟動linux 系統的唯一目的就是為了方便調試!不管是為了調試linux 系統還是linux 下的驅動。每次修改linux 系統文件或者linux 下的某個驅動以后都要將其燒寫到EMMC 中去測試,這樣太麻煩了。

我們可以設置linux 從網絡啟動,也就是將linux 鏡像文件和根文件系統都放到Ubuntu 下某個指定的文件夾中,這樣每次重新編譯linux 內核或者某個linux 驅動以后只需要使用cp 命令將其拷貝到這個指定的文件夾中即可,這樣就不用需要頻繁的燒寫EMMC,這樣就加快了開發速度。

我們可以通過nfs 或者tftp 從Ubuntu 中下載zImage 和設備樹文件,根文件系統的話也可以通過nfs 掛載,不過本小節我們不講解如何通過nfs 掛載根文件系統,這個在講解根文件系統移植的時候再講解。這里我們使用tftp 從Ubuntu 中下載zImage 和設備樹文件,前提是要將zImage 和設備樹文件放到Ubuntu 下的tftp 目錄中,具體方法在30.4.4 小節講解tftp 命令的時候已經詳細的介紹過了。

設置bootargs 和bootcmd 這兩個環境變量,設置如下:

setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw' setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000' saveenv

一開始是通過tftp 下載zImage 和imx6ull-alientek-emmc.dtb 這兩個文件,過程如下圖33.4.2.1所示:

下載完成以后就是啟動Linux 內核,啟動過程如圖33.4.2.2 所示:

DDR初始化參數修改



具體校準方法參照前面裸機部分。

總結

uboot 移植到此結束,簡單總結一下uboot 移植的過程:

①、不管是購買的開發板還是自己做的開發板,基本都是參考半導體廠商的dmeo 板,而半導體廠商會在他們自己的開發板上移植好uboot、linux kernel 和rootfs 等,最終制作好BSP包提供給用戶。我們可以在官方提供的BSP 包的基礎上添加我們的板子,也就是俗稱的移植。
②、我們購買的開發板或者自己做的板子一般都不會原封不動的照抄半導體廠商的demo板,都會根據實際的情況來做修改,既然有修改就必然涉及到uboot 下驅動的移植。
③、一般uboot 中需要解決串口、NAND、EMMC 或SD 卡、網絡和LCD 驅動,因為uboot的主要目的就是啟動Linux 內核,所以不需要考慮太多的外設驅動。
④、在uboot 中添加自己的板子信息,根據自己板子的實際情況來修改uboot 中的驅動。

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的U-Boot 移植的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

国产成人精品久久久 | 国产精品视频在线看 | 免费视频一二三 | 超碰97网站| 又黄又刺激又爽的视频 | 日本性动态图 | 亚洲专区路线二 | 欧美一区二区在线看 | 九九精品毛片 | 国产不卡在线观看视频 | 五月天六月色 | 成人国产精品久久久春色 | 狠狠色丁香婷婷综合欧美 | 日本久热 | 国内精品久久久久久久 | 狠狠色丁香婷综合久久 | 91视频高清完整版 | 一区在线观看 | 国产精品2018 | 在线视频电影 | 日韩欧美高清在线观看 | 日韩精品国产一区 | 亚洲一级在线观看 | 日韩久久激情 | 国产午夜一区二区 | 日日操天天爽 | 国产精品久久久777 成人手机在线视频 | 国产一二三四在线观看视频 | 91中文字幕永久在线 | 婷婷丁香在线观看 | 免费a级大片 | 午夜婷婷在线观看 | 欧美一级性 | 91社区国产高清 | 免费男女羞羞的视频网站中文字幕 | 亚洲欧美在线综合 | 在线黄av | 欧美激情综合网 | 国产美腿白丝袜足在线av | 欧美一级网站 | 一区二区三区电影 | 免费看高清毛片 | 亚洲天堂精品 | 日韩免费网址 | 久久综合五月天婷婷伊人 | 五月天色婷婷丁香 | 免费亚洲视频 | 日本一区二区三区视频在线播放 | 国产成人精品网站 | 99超碰在线播放 | 国产二区电影 | 91漂亮少妇露脸在线播放 | 91精品久久久久久综合乱菊 | 欧美视频日韩 | 国产黄色片免费看 | 色香网| 久久99久久99精品免观看粉嫩 | 中文字幕永久在线 | 中文字幕在线视频精品 | 欧美精品乱码久久久久 | 日韩av免费在线电影 | 九色精品免费永久在线 | 视频一区二区免费 | 免费视频成人 | 人人干天天射 | 久久久免费看片 | 99久久精品无码一区二区毛片 | 国产成人免费 | 国产中文字幕在线 | 日韩精品在线观看视频 | 亚洲精品国产第一综合99久久 | 欧美在线一 | 国产无套精品久久久久久 | 国产精品麻豆一区二区三区 | 在线免费观看麻豆 | 亚洲综合色视频在线观看 | 久久精品中文字幕免费mv | 欧美一二三区在线播放 | 亚洲精品免费看 | 午夜影院在线观看18 | 国产小视频在线播放 | 91黄在线看 | 97在线观看免费观看高清 | 毛片永久新网址首页 | 免费三级黄色片 | 综合国产视频 | 日日草av| 国产综合小视频 | 久久久综合香蕉尹人综合网 | 国产成人精品一区二区三区在线 | 99久久婷婷国产综合精品 | 色网站在线免费观看 | 伊人一级| 国产片免费在线观看视频 | 久久久久区 | 午夜国产福利在线 | 天天搞夜夜骑 | 日韩免费电影一区二区 | 一二三区av| 国产精品一级视频 | 国产成人一区二区三区免费看 | 天干啦夜天干天干在线线 | 成人在线视频免费观看 | 99re中文字幕 | 在线免费av网| 97成人超碰 | av在线免费网站 | 日日操网站| 亚洲毛片在线观看. | 9色在线视频 | 综合av在线| 亚洲一二三在线 | 国产欧美久久久精品影院 | 日韩午夜一级片 | 日韩va在线观看 | 免费黄色在线网站 | 天天五月天色 | 成人小视频免费在线观看 | 中文字幕日本特黄aa毛片 | 欧美一区三区四区 | 精品一区二区三区四区在线 | 国产一区二区三区四区大秀 | 久久免费播放 | 少妇搡bbbb搡bbb搡忠贞 | 在线免费三级 | 69夜色精品国产69乱 | 午夜精品一区二区三区免费视频 | 国产精品毛片一区二区在线看 | 久艹在线免费观看 | 亚洲视屏 | 91丨九色丨蝌蚪丰满 | 丝袜美腿在线 | 在线电影av | 久草视频播放 | 国产剧情一区 | 亚洲欧美视频一区二区三区 | 五月婷婷激情五月 | 亚洲成年人av | 国产九色在线播放九色 | 开心色插| 性色av免费在线观看 | 久久国产精品久久精品 | 亚洲精品乱码久久久久久写真 | 欧美一级片 | 五月在线视频 | 亚洲经典精品 | bbbbb女女女女女bbbbb国产 | 日韩激情片在线观看 | 国产精品一区在线观看你懂的 | 精品中文字幕在线观看 | 在线导航福利 | 国内精品久久久久影院一蜜桃 | 日本不卡一区二区 | 免费看国产黄色 | 日本69hd| 国产中文在线播放 | 麻豆视频免费观看 | 一级免费片 | 免费在线观看国产黄 | 在线 视频 一区二区 | 五月婷婷影视 | 在线免费色 | 男女拍拍免费视频 | 国产无遮挡又黄又爽馒头漫画 | 五月婷婷综 | 国产在线精品二区 | 69xxxx欧美 | 国产精品影音先锋 | 色多多在线观看 | 中文字幕免费高 | 亚洲激情视频在线 | 深爱激情五月综合 | 免费精品在线视频 | 亚洲一区精品人人爽人人躁 | 成人夜晚看av | 欧美精品久久人人躁人人爽 | 黄色毛片一级片 | 天堂av网址 | 久久综合九色综合97婷婷女人 | 国产不卡一二三区 | 中文字幕区 | 啪啪肉肉污av国网站 | 亚洲精品国精品久久99热 | 亚洲国产剧情av | 中文字幕在线影院 | 五月婷婷激情综合 | 婷婷丁香六月 | 99久久9 | 亚洲精品国产精品乱码不99热 | 在线观看视频三级 | 国产一区在线播放 | 国产精品久久在线观看 | 国产中出在线观看 | bbbb操bbbb| 国产精品久久久久久久av大片 | 91在线最新 | 亚洲五月激情 | 婷婷www | 精品免费视频. | 久操中文字幕在线观看 | 99看视频在线观看 | 国产99久久久欧美黑人 | 天天天天天天天天操 | 日韩精品一区在线观看 | 91天天操 | 人人添人人澡人人澡人人人爽 | 中文字幕乱码电影 | 成人在线观看资源 | 国产手机在线 | 国产日韩欧美在线免费观看 | 欧美男男激情videos | 99视频精品全国免费 | 日韩在线免费视频观看 | 中文字幕综合在线 | 丁香在线观看完整电影视频 | 国产精品一区久久久久 | 奇米影视8888| 欧美精品生活片 | av黄色在线观看 | 伊色综合久久之综合久久 | bayu135国产精品视频 | 黄影院| 人人爽人人看 | 日韩精品视频免费看 | 国产成人高清在线 | 精品一区二区久久久久久久网站 | 91麻豆精品国产 | 国产精品99久久免费黑人 | 一级欧美一级日韩 | 亚洲精品视频一二三 | 亚洲精品一区二区网址 | 99热国内精品 | 黄色大片国产 | www.黄色片网站 | 久久久久 免费视频 | 国产精品久久久久久久久久久杏吧 | 国产伦精品一区二区三区照片91 | 美女激情影院 | 日韩av资源在线观看 | 国产黄色片网站 | 日本99干网 | 天天干天天操天天拍 | 成人国产精品av | 亚洲精品久久久久久中文传媒 | 久碰视频在线观看 | www.xxxx欧美| 黄色网址中文字幕 | 免费久久久久久 | 久久综合九色综合久久久精品综合 | 久久视奸| 日日夜色 | 久久天天躁狠狠躁夜夜不卡公司 | 毛片网站免费 | 国产第页 | 九九交易行官网 | 久久久久久蜜桃一区二区 | 欧美 亚洲 另类 激情 另类 | 麻豆一区二区三区视频 | 2019精品手机国产品在线 | 久久久99精品免费观看乱色 | 国产一区二区在线看 | 国产精品久久久久久久久久三级 | 国产在线观看av | 91视频免费看网站 | 国产中文在线字幕 | 综合色站导航 | 97视频入口免费观看 | 日韩精品免费一区二区三区 | 国产成人精品av在线 | 久久久伦理 | 亚洲精品在 | 国产精彩视频一区二区 | 91中文字幕视频 | 91少妇精拍在线播放 | 在线视频观看亚洲 | 亚洲专区中文字幕 | 五月婷婷播播 | 久久艹99| 国产亚洲婷婷免费 | 亚洲欧洲精品久久 | 99久久精品免费看国产免费软件 | 久久天天拍 | 国产精选在线 | 欧美福利片在线观看 | 91看国产| av综合av| 99视频精品 | av软件在线观看 | 久久久在线视频 | 国产精品久久久一区二区三区网站 | 超碰久热 | 在线免费观看视频一区二区三区 | 最近中文字幕在线中文高清版 | 国产美女无遮挡永久免费 | 99麻豆视频 | 又粗又长又大又爽又黄少妇毛片 | www视频在线观看 | 国产69精品久久久久久 | 青青河边草观看完整版高清 | 成人av一二三区 | 久久观看 | 超碰国产在线播放 | 色噜噜狠狠狠狠色综合 | 蜜臀av性久久久久蜜臀aⅴ流畅 | 色悠悠久久综合 | 亚洲国产播放 | 日韩精品在线播放 | 日本特黄特色aaa大片免费 | 免费av看片 | 黄色在线看网站 | 国产在线欧美日韩 | 日韩电影一区二区在线观看 | 久久免费视频一区 | 中文字幕文字幕一区二区 | 久久一二三四 | 欧美 日韩 性 | 色综合久久88色综合天天 | 大荫蒂欧美视频另类xxxx | 成人性生爱a∨ | 在线观看黄av| 中文字幕在线播放日韩 | 久久久久国产精品视频 | 在线成人免费av | 日韩欧美一区二区不卡 | 手机成人免费视频 | 亚洲黄色片在线 | www.狠狠操 | 国产成人三级三级三级97 | www久久国产 | av免费电影在线观看 | 欧美日性视频 | 国产黄色播放 | 在线观看黄色 | 久久久精品一区二区三区 | 色中色亚洲 | 97热久久免费频精品99 | 波多野结衣视频在线 | 西西444www大胆高清视频 | 久久色中文字幕 | 九九热视频在线免费观看 | 色综合网| 婷婷视频在线观看 | 久久综合狠狠综合久久狠狠色综合 | 久久99久久99精品 | 精品国产视频在线观看 | 国产69久久精品成人看 | av高清影院 | 91网免费看 | 久久综合婷婷 | 欧美综合色在线图区 | 亚洲精品自拍视频在线观看 | 99国产精品一区 | 精品国产免费人成在线观看 | 国产免费影院 | 精品国产伦一区二区三区观看体验 | 精品一区三区 | 欧美日韩二区三区 | 99精品99| 天天操天天爱天天干 | 天干啦夜天干天干在线线 | 国产视频在线观看一区 | 国产.精品.日韩.另类.中文.在线.播放 | 2019中文字幕网站 | av免费看av| 欧美 激情 国产 91 在线 | 99久久婷婷国产综合亚洲 | 中文成人字幕 | 天天想夜夜操 | 久久久久免费精品 | av免费看av| 美女精品在线 | 精品国产1区2区 | 9免费视频 | 精品福利在线观看 | 久久免费国产精品 | 久久伊人色综合 | 天天综合在线观看 | 精品久久久免费视频 | 日本高清xxxx | 五月香婷 | 免费人成网ww44kk44 | 亚洲最大av在线播放 | 又湿又紧又大又爽a视频国产 | 国产黄免费 | 最新国产在线 | 午夜av免费| 国产精品99免费看 | 久久国产视屏 | 特级西西444www大胆高清无视频 | 2023国产精品自产拍在线观看 | 亚洲精品乱码久久久久久蜜桃动漫 | 在线看国产日韩 | 国产精品18久久久久久久久 | 久久久精品久久日韩一区综合 | 精品国产一区二区在线 | 在线免费国产视频 | 国产美女网站视频 | 色婷婷丁香 | 男女视频91| 日韩av片无码一区二区不卡电影 | 欧美亚洲国产日韩 | 欧美一区在线观看视频 | 中文字幕在线观看三区 | www.亚洲精品视频 | 国产精品一区二区三区视频免费 | 亚洲精品视频大全 | 麻豆久久一区二区 | 综合色在线 | a资源在线 | 日韩日韩日韩日韩 | 日韩在线观看视频中文字幕 | 天天爽天天射 | 亚洲精品久久久久久久蜜桃 | 国产美女精品人人做人人爽 | 96精品高清视频在线观看软件特色 | 麻豆视频在线观看免费 | 毛片99| 91香蕉视频黄| 在线天堂8√ | 国产片免费在线观看视频 | 久久视频精品在线观看 | 狠狠狠色丁香婷婷综合久久五月 | 天天操天天干天天摸 | 日韩精品免费在线观看视频 | 91香蕉嫩草 | 99这里精品| 国产亚洲视频在线免费观看 | 亚洲精品视频免费在线 | 天天看天天干天天操 | 香蕉网在线 | 成人视屏免费看 | www.夜夜操.com| 中文字幕字幕中文 | 手机成人免费视频 | 九九久久电影 | 亚洲成人av电影 | 不卡的av电影在线观看 | 亚洲综合色站 | 日韩欧美国产免费播放 | 亚洲一区视频免费观看 | 久久精精品视频 | 91看片在线| 99热九九这里只有精品10 | 国产在线观看,日本 | 福利视频一二区 | www久草| 久久免费看毛片 | 久久精品91视频 | 99中文字幕视频 | av日韩在线网站 | 一级α片 | 国产精品1000 | 亚洲精品2区 | 六月婷色| 六月丁香激情综合色啪小说 | 成人免费av电影 | 99久久精品免费视频 | 99视频精品视频高清免费 | 国产人免费人成免费视频 | 我要色综合天天 | 日韩综合在线观看 | 国产中文字幕91 | 欧洲精品视频一区二区 | 日日爽视频 | 粉嫩aⅴ一区二区三区 | 激情自拍av | 久久精品站 | 国产日韩精品欧美 | 精品在线不卡 | 国产精品原创 | 久草在线视频免费资源观看 | 精品一区二区三区久久久 | 在线高清av | 久久久久国产一区二区 | 日韩视频中文 | 精品中文字幕在线播放 | 91av视频播放 | 91视频久久久久 | 97视频入口免费观看 | 久久婷婷久久 | 欧美日韩国产在线观看 | 99re亚洲国产精品 | 国产精品黄色av | 在线观看免费版高清版 | 国产精品国内免费一区二区三区 | 亚洲一级片免费观看 | 国产在线中文字幕 | 国产传媒一区在线 | 日本在线中文在线 | 国产麻豆精品免费视频 | 美女网站在线免费观看 | 91在线看黄 | 中文字幕在线视频一区二区三区 | 狠狠色伊人亚洲综合成人 | 特级黄录像视频 | 国产精品美女在线观看 | 992tv在线观看网站 | 在线观看免费日韩 | 久久久久亚洲精品成人网小说 | 97手机电影网 | 99热精品在线观看 | 精品视频在线免费 | 国产伦理一区二区 | 日韩有码中文字幕在线 | 婷婷色 亚洲| 91在线免费观看网站 | 色国产视频 | 国产视频在线观看一区 | 五月婷婷久久丁香 | 中文字幕人成乱码在线观看 | 日韩在线大片 | 午夜精品区 | 亚洲va欧美va人人爽春色影视 | 日韩高清免费无专码区 | 久久欧美视频 | av电影免费在线看 | 香蕉影院在线观看 | www.狠狠插.com | 亚洲精品456在线播放第一页 | www.婷婷色| 日日干,天天干 | 国产精品毛片一区二区 | 日韩国产精品久久久久久亚洲 | 久久久久免费精品视频 | 69精品在线 | 69xx视频 | 深夜福利视频在线观看 | 国产精品6| 亚洲精品视频在线观看视频 | 国产精品无av码在线观看 | 天天操天天干天天操天天干 | 日韩av网页| 久久公开免费视频 | 国产亚洲永久域名 | 国产精品嫩草影视久久久 | 亚洲国产成人在线观看 | 四虎国产永久在线精品 | 国产在线 一区二区三区 | 最新国产视频 | 日日干激情五月 | 免费男女网站 | 久久综合五月天婷婷伊人 | 国产一区二区久久久久 | 精品a视频 | 免费观看一区二区 | 国产成人亚洲在线观看 | 日本精品中文字幕在线观看 | 日韩欧美在线中文字幕 | 日韩免费看片 | 午夜精品电影一区二区在线 | 成人精品久久久 | 欧美超碰在线 | 国内精品久久久久影院男同志 | 成人毛片100免费观看 | 亚洲精品久久久久58 | 亚洲mv大片欧洲mv大片免费 | 极品嫩模被强到高潮呻吟91 | 在线欧美中文字幕 | 天天色天天操天天爽 | 手机在线视频福利 | 国产资源精品在线观看 | 91看片淫黄大片在线播放 | 欧美色图一区 | 国产69精品久久久久99尤 | 日韩动态视频 | 久久精品一区 | 最近更新中文字幕 | 亚洲视频久久 | 国产精品 日韩 欧美 | 日韩精品一区二区在线视频 | 992tv在线成人免费观看 | 久久超级碰视频 | 久久精精品 | 午夜私人影院久久久久 | 成人av在线亚洲 | 五月天com| 黄色成人毛片 | 亚洲乱码一区 | 日韩大片在线 | 2000xxx影视 | 国产高清久久 | 国产视频二区三区 | 国产黄色一级片在线 | 九九九九色 | 亚洲精品18日本一区app | 天天操狠狠操夜夜操 | 国产精品免费在线 | 97超视频在线观看 | 亚洲成人av片在线观看 | 中文字幕av在线电影 | 中文字幕在线国产精品 | 摸bbb搡bbb搡bbbb| 亚洲综合成人在线 | 婷婷激情在线 | 欧美黑人巨大xxxxx | 日韩免费视频线观看 | 久久麻豆视频 | 就色干综合 | 久草在线在线 | 欧美乱码精品一区 | 久久国产女人 | 久久国产精品99久久人人澡 | 午夜视频福利 | 国产明星视频三级a三级点| 亚洲精品高清在线观看 | 国产啊v在线观看 | 亚洲天堂色婷婷 | 久久久国产精品一区二区中文 | 亚洲欧美日韩国产精品一区午夜 | 在线观看视频一区二区三区 | 亚洲专区在线播放 | 九月婷婷综合网 | 96av在线视频 | 天天插狠狠插 | 日本字幕网 | 久久影院中文字幕 | 91资源在线视频 | 九九九九九九精品任你躁 | 久久久久成人精品亚洲国产 | av大全在线| 国产一级大片免费看 | 成人h在线| 国产日韩视频在线观看 | 国产日韩欧美在线观看 | 97精品国产97久久久久久粉红 | 亚洲一二三区精品 | 日韩av一区二区三区在线观看 | 国产精品高清在线观看 | 天天拍天天爽 | 69视频国产 | 视频三区在线 | 91丨九色丨91啦蝌蚪老版 | 天天操天天干天天插 | 视频在线一区 | 天天色播| 乱子伦av | 国产一区不卡在线 | 免费热情视频 | 国产精品久久久久久久久蜜臀 | 国产精品久久久久久高潮 | 超碰官网 | 一区二区三区久久 | 日本精品久久久一区二区三区 | 免费黄色av电影 | 夜夜骑日日 | 亚洲综合网站在线观看 | 五月婷婷导航 | 日韩精品久久一区二区三区 | 亚洲一区二区观看 | 欧美日韩亚洲精品在线 | 久久久免费看视频 | 亚洲精品高清视频在线观看 | 在线免费91| 色丁香色婷婷 | 亚洲香蕉视频 | 日韩一区二区三区在线看 | 综合久久一本 | 久久观看免费视频 | 亚洲va欧美va国产va黑人 | 亚洲黄色免费在线 | 亚洲成人欧美 | 美女精品久久久 | 人人爽人人爽人人片 | 天天人人 | 91精品爽啪蜜夜国产在线播放 | 欧美一级片在线观看视频 | 日韩美女免费线视频 | av在线播放国产 | 伊人网综合在线观看 | 日韩极品在线 | 国产精品手机在线观看 | 日本视频高清 | 日韩3区 | 91精品啪啪| 国产精品美女久久久久久久久久久 | 久久99国产精品免费网站 | 三级免费黄 | 婷婷色网站 | 日韩av视屏 | 久久视频精品在线观看 | 一级性av| 激情婷婷av | 日本爽妇网 | 亚洲一级影院 | 久久久久久国产精品亚洲78 | 国产伦理一区二区三区 | 欧美精品一区二区在线观看 | 涩涩网站在线观看 | 欧美日韩国内在线 | 天天射天天干天天插 | 久久综合久久综合这里只有精品 | 亚洲日韩欧美一区二区在线 | 精品国产区在线 | 亚洲综合丁香 | 国产免费高清视频 | 视频在线观看一区 | 精品视频一区在线 | aaa毛片视频 | 看黄色91| 国产午夜一区二区 | 91看片在线 | 中国一级特黄毛片大片久久 | www.日韩免费| wwwwww黄| 美女网站在线看 | 国产视频精品免费 | 国内揄拍国内精品 | 国内精品久久久久久久97牛牛 | 99人成在线观看视频 | 国产色视频123区 | 国产在线精品区 | 亚洲欧洲精品一区二区 | 欧美日韩伦理一区 | av大全在线播放 | 欧洲精品一区二区 | 免费视频a | 亚洲一区久久 | 九九日九九操 | 岛国片在线| 国产精品大尺度 | 精品久久久久久久久久 | 欧美色精品天天在线观看视频 | 少妇精品久久久一区二区免费 | 国产资源站 | 激情伊人五月天 | 69亚洲精品 | 91热视频 | 日韩理论电影在线 | av天天草 | 美腿丝袜一区二区三区 | 在线观看成人 | 精品a在线| 国产一区国产精品 | 欧美极品在线播放 | 日韩视频区 | 成人午夜免费剧场 | 最近av在线| 日本韩国欧美在线观看 | 91精品入口| 欧美日韩首页 | 美女国产网站 | 五月婷香蕉久色在线看 | 日韩欧美视频在线观看免费 | 日韩精品综合在线 | 久久久免费| 日韩中文幕 | 69成人在线 | 亚洲日韩欧美一区二区在线 | 在线视频 成人 | 国产精品6| 成人免费在线视频观看 | 国产天天综合 | 最近更新好看的中文字幕 | 中文字幕亚洲精品在线观看 | 日本中文字幕在线观看 | 久久免费的视频 | 97国产大学生情侣白嫩酒店 | 不卡的av在线 | 91中文在线视频 | 在线观看中文 | 亚洲成人国产 | 国产免费又爽又刺激在线观看 | 99热超碰 | 97操碰| 狠狠躁18三区二区一区ai明星 | 欧美视频www | 亚洲在线精品 | 美女网站视频色 | 中日韩在线| 在线视频观看你懂的 | 国产精品久久久久久久久久99 | 亚洲最大av| 最新av中文字幕 | 人人超碰人人 | 99r在线观看| 综合在线色 | 天天色天天操天天爽 | 国产亚洲观看 | 亚洲成aⅴ人在线观看 | 久久久色 | 四虎在线永久免费观看 | 国产涩涩在线观看 | 丁香视频在线观看 | 99久久99视频只有精品 | 91精品国产欧美一区二区 | 国产一区二区高清视频 | 免费看特级毛片 | 国产精品美女久久久网av | 五月婷婷色综合 | 日本午夜在线亚洲.国产 | 国产精品6| 国产精品在线看 | 少妇视频一区 | 国产在线精品区 | 久久er99热精品一区二区 | av三级在线看 | 伊人国产女 | 成人在线视频免费 | 99精品免费观看 | 99热精品国产 | 超碰电影在线观看 | 香蕉视频在线视频 | 免费在线黄网 | 人人爽爽人人 | 国产96视频 | 一区二区三区电影在线播 | 国产精品久久亚洲 | 欧美成人基地 | 嫩草av在线 | 免费在线观看日韩视频 | 国产黄在线播放 | 九九九九九国产 | 91精品视频一区二区三区 | 久久久久欧美精品999 | 精品国产一区二区三区在线观看 | 日韩精品免费一区 | 婷婷综合成人 | 91av片| 91麻豆精品一区二区三区 | 国产专区日韩专区 | 亚洲日本一区二区在线 | 日韩成人av在线 | 国产成人在线网站 | 俺要去色综合狠狠 | 中文字幕资源在线 | 狠狠躁18三区二区一区ai明星 | 成人av资源网 | 成人资源在线观看 | 国产91免费观看 | 开心激情久久 | 亚洲国产精品激情在线观看 | 久久最新网址 | 久久免费视频一区 | 久99热| 成人免费在线观看av | 午夜精品视频福利 | 91人人干| 懂色av一区二区在线播放 | 精品乱码一区二区三四区 | 成人a大片 | 国产午夜精品一区二区三区嫩草 | 九九热精品视频在线观看 | 免费在线观看国产精品 | 亚洲免费婷婷 | 日韩经典一区二区三区 | 97电影网手机版 | 久久精品99视频 | 国产成人精品久久久 | 在线视频 一区二区 | 99精品免费久久久久久久久日本 | 亚洲欧美日韩国产一区二区三区 | 亚洲日本在线一区 | 97精品超碰一区二区三区 | 中文字幕在线看人 | 免费在线观看的av网站 | av九九九| 久久精品国产精品亚洲 | 国产在线p | 二区视频在线观看 | 蜜桃av综合网 | 国产福利精品在线观看 | 天天操操操操操 | 丁香婷婷激情国产高清秒播 | 波多野结衣小视频 | 一区二区视频欧美 | 91成人免费视频 | 日本99久久 | 在线观看日韩av | 九七视频在线观看 | 天天视频色 | 97色在线视频 | 欧美与欧洲交xxxx免费观看 | 久久精品人人做人人综合老师 | 欧洲一区二区三区精品 | 女人高潮一级片 | 91在线视频免费观看 | www.色婷婷.com| 国产精品永久免费在线 | 日韩精品一区二区三区视频播放 | 99热99| 丁香六月av | 欧美另类z0zx | 国内精品福利视频 | 色www.| 蜜臀av在线一区二区三区 | 欧美一区二区三区在线视频观看 | 天天天天色射综合 | 亚洲综合爱 | 丁香六月天 | 97精品在线 | 欧美成人tv | 日韩亚洲欧美中文字幕 | 丁香影院在线 | 午夜资源站 | 综合色影院 | 看国产黄色大片 | 久久精品影视 | 91黄在线看| 久久久精品国产免费观看同学 | 中文字幕在线观看一区二区 | 久久久免费在线观看 | 亚洲丁香久久久 | 69久久久| 欧美视频在线二区 | 人人草人人做 | 亚洲精品高清一区二区三区四区 | 国语自产偷拍精品视频偷 | 亚洲免费av片 | 天天天天干| 亚洲视频电影在线 | 国产不卡在线观看视频 | 久久久久免费精品 | 色综合人人 | 在线免费中文字幕 | 欧美日韩一级在线 | av导航福利 | 国产精品一区二区中文字幕 | 欧美不卡视频在线 | 97视频资源 | 欧美另类网站 | 在线不卡视频 | 久久久久久久久久久电影 | 国产精品美女在线 | 91高清视频免费 | 欧美激情操 | 天天做日日做天天爽视频免费 | 色综合久久88色综合天天人守婷 | 欧美日韩精品网站 | 91观看视频| 国产不卡免费 | 欧美一二三视频 | 激情五月***国产精品 | 日日操天天操狠狠操 | 亚洲精品国产拍在线 | 99热国产在线中文 | 免费色av| 国内精品小视频 | 日本中文在线 | 久久久久欠精品国产毛片国产毛生 | 中文字幕色综合网 | 黄色精品网站 | 91免费看黄| 色综合天天射 | 久久久久 免费视频 | 久久国产成人午夜av影院潦草 | 91av免费看| 色永久免费视频 | av黄色在线观看 | 日色在线视频 | 成人一区二区三区中文字幕 | 国产在线观看黄 | va视频在线 | 亚洲精品小视频 | 国产精品国产精品 | 国产一区二区在线播放视频 | 亚洲成人资源在线 | 啪嗒啪嗒免费观看完整版 | 中文字幕综合在线 | 久久,天天综合 | 中文字幕网站视频在线 | 亚洲午夜精品在线观看 | 日韩69视频| 午夜在线观看 | 欧美日产一区 | 狠狠干狠狠色 | 99久久精品国产免费看不卡 | 久久精品国产精品亚洲 | 一区二区三区在线免费观看视频 | a级国产乱理伦片在线观看 亚洲3级 | 免费网站在线观看成人 | 免费福利在线视频 | 国色综合 | 日本特黄一级片 | 狠狠操天天射 | 九色福利视频 | 99精品国产高清在线观看 | 中文字幕精品一区 | 国产粉嫩在线观看 | 国产精品久久久久久久婷婷 | 国产视频精品久久 | 国产中文字幕视频在线观看 | 综合激情网... | 日韩欧美精品在线观看视频 | 精品产品国产在线不卡 | 激情深爱五月 | 在线观看的a站 | 最近2019年日本中文免费字幕 | 精品夜夜嗨av一区二区三区 | 国产五月 | 高潮久久久久久久久 | 婷婷av网 | 91久久丝袜国产露脸动漫 | 96精品在线| 日韩午夜在线播放 | 国产在线观看xxx | 国产精品一区二区吃奶在线观看 | 国内丰满少妇猛烈精品播放 | 超碰在线人 |