SoC : : Architecture/: : i.MX

i.MX 9 BSP Porting Guide - Porting U-Boot

Jay.P Morgan 2024. 4. 30. 23:36

  3.0 Intro

 

  이 장에서는 독립 실행형 (standalone) 환경과 Yocto Project를 통해 i.MX U-Boot를 다운로드, 빌드 및 로드하는 방법을 설명합니다

 

  3.1.1 How to build U-Boot in standalone environment

  독립 실행형 환경에서 U-Boot를 구축하려면 다음 단계를 수행하십시오.

 

  1.  호스트 시스템에 배치하기 위해 컴파일할 도구, 툴체인 및 작은 rootfs가 포함된 개발 SDK를 생성합니다. 동일한 SDK를 사용하여 독립형 커널을 구축할 수 있습니다.

 

    ㄱ.  다음 명령을 사용하여 Yocto Project 빌드 환경에서 SDK를 생성하세요. Yocto Project 빌드 환경을 설정하려면 i.MX Yocto Project User's Guide (IMXLXYOCTOUG)의 단계를 따르세요. 다음 명령에서 Target-Machine을 빌드하려는 머신으로 설정합니다. i.MX Yocto Project User's Guide (IMXLXYOCTOUG)의 "Build Configurations" 섹션을 참조하세요. populate_sdk는 Yocto Project 없이 독립형 환경을 설정하는 스크립트 파일을 생성합니다. 현재 릴리스의 최신 헤더, 툴체인 및 도구를 선택하려면 릴리스마다 이 SDK를 업데이트해야 합니다.

DISTRO=Target-Distro MACHINE=Target-Machine bitbake core-image-minimal -c  populate_sdk

 

유용한 DISTRO 옵션을 사용하려면, i.MX Yocto Project User's Guide (IMXLXYOCTOUG)의 "Build Configurations" 섹션을 참조하세요.

    ㄴ.  BitBake가 실행된 빌드 디렉터리에서 tmp/deploy/sdk의 .sh 파일을 호스트 머신에 복사하여 SDK를 설치하는 스크립트를 빌드하고 실행합니다. 기본 위치는 /opt이지만 호스트 시스템의 어느 위치에나 배치할 수 있습니다.

 

  2. 호스트 시스템에서 다음 단계를 수행하여 U-Boot를 빌드합니다.

    ㄱ.  i.MX 8 SoC를 빌드하기 전에 호스트 시스템에서 다음 명령을 사용하여 환경을 설정합니다.

$ source/opt/fsl-imx-xwayland/6.6.3/environment-setup-aarch64-poky-linux $ export ARCH=arm64

 

    ㄴ. i.MX 6 또는 i.MX 7 SoC를 빌드하기 전에 호스트 시스템에서 다음 명령을 사용하여 환경을 설정합니다.

$ export CROSS_COMPILE=/opt/fsl-imx-fb/6.6.3/environment-setup-cortexa9hf-vfp-neon-poky-linux-gnueabi
$ export ARCH=arm

 

    ㄷ. 독립형 환경에서 U-Boot를 빌드하려면 다음 명령을 실행하십시오.
         다음을 사용하여 복제하여 소스를 다운로드하세요.

$ git clone https://github.com/nxp-imx/uboot-imx

 

    ㄹ. 독립형 환경에서 U-Boot를 빌드하려면 uboot-imx 소스 코드의 configs/ 디렉터리에서 대상 부팅에 대한 구성을 찾으세요. 다음 예에서는 i.MX 6ULL이 대상입니다.

$ cd uboot-imx
$ make distclean
$ make mx6ull_14x14_evk_defconfig
$ make

 

    ㅁ. 사용자 정의 보드를 생성하려면 연결된 SoC에 대한 참조 defconfig를 새 이름으로 복사하고 configs 폴더에 배치한 다음 새 구성 이름을 사용하여 빌드합니다.
    ㅂ. i.MX 8의 경우 imx-mkimage 도구를 사용하여 U-Boot 바이너리를 ATF(Arm Trusted Firmware) 및 SCFW와 결합하여 최종 flash.bin 부팅 이미지를 생성하고 SD 카드에 굽습니다. 자세한 내용은 imx-mkimage 도구를 참조하세요.
    ㅅ. 부팅 이미지를 SD 카드에 구우려면 다음 명령을 실행합니다.

dd if=<boot_image> of=/dev/sd<x> bs=1k seek=<offset> conv=fsync


어디:

• 오프셋은 다음과 같습니다.
1 - i.MX 6 또는 i.MX 7용
33 - i.MX 8QuadMax A0, i.MX 8QuadXPlus A0, i.MX 8M 쿼드, i.MX 8M Mini용
32 - i.MX 8QuadXPlus B0, i.MX 8QuadMax B0, i.MX 8DXL, i.MX 8M Nano, i.MX 8M Plus 및 i.MX 93용

• sd<x> : SD 카드의 장치 노드입니다.
• boot_image : u-boot.imx - i.MX 6 또는 i.MX 7용
flash.bin - i.MX8용

 

 

  3.1.2 How to build and load U-Boot in Yocto Project

 

  Yocto 프로젝트에 U-Boot 변경 사항을 통합하려면 다음 단계를 수행하세요:

  1.   Yocto Project의 i.MX Reference Board에 관련 SoC를 빌드하기 위한 빌드 환경설정을  매니페스트 브랜치 또는 릴리스 레이어에 있는 README의 지침에 따라 진행합니다. 여기에는 저장소 초기화 및 동기화를 사용하여 Yocto Project 메타데이터를 다운로드하고 imx-setup-release를 사용하여 빌드 환경을 설정하는 것이 포함됩니다.

  2.  관련 SoC용 Reference Board Kernel을 구축합니다. 다음은 예시로, 첫 빌드는 필요한 모든 도구를 빌드하고 의존성 때문에 시간이 더 오래걸립니다.

$ MACHINE=imx6qsabresd bitbake u-boot-imx

 

  3.  커스텀 보드 커널 변경 사항을 보관할 커스텀 레이어를 만듭니다. 커스텀 레이어를 생성하려면 기존 레이어를 살펴보세요.
  더 간단한 예를 보려면 XBMC 또는 IOTG용 i.MX 데모를 참조하세요. 커스텀 레이어는 /conf 디렉토리의 bblayer.conf에 추가하여 통합됩니다. 레이어에는 conf/layer.conf 파일에서 레이어 이름을 기술해야 합니다.

  4.  커스텀 보드의 SoC와 연결된 기존 머신 파일을 커스텀 레이어에 복사합니다. :

$ cp sources/meta-freescale/conf/machine/imx6qsabresd.conf <new layer>/conf/ machine/<custom_name>.conf

 

  5.  UBOOT_CONFIG 옵션을 사용하여 머신 구성 파일을 편집합니다.
  6.  conf/local.conf에 아래 코드를 추가하여 u-boot-imx로 빌드할 커널의 perferred version(기본 버전)을 변경합니다. 다양한 U-Boot 제공업체가 있으므로 u-boot-imx 버전을 사용해야 합니다.

PREFERRED_PROVIDER_virtual/bootloader_<custom_name> = "u-boot-imx"

 

  7.  커스텀 머신을 빌드하세요.

$ MACHINE=<custom_name> bitbake u-boot-imx

 

빌드 결과물을 찾으려면 /tmp/work/-poky-linux-gnueabi/u-boot-imx/ 을 확인하세요. 또한 부팅 바이너리를 찾으려면  /tmp/deploy/images/를 살펴보세요.

  8.  커스텀 시스템 및 defconfig에 대한 U-Boot 패치는 u-boot-imx_%.bbappend에서 아래의 예시처럼 제공할 수 있으며,  source/<custum_layer>/ recipe-bsp/ uboot-imx/files 에 배치된 패치로 patch1.patch를 제공할 수 있습니다.:

8.    U-Boot patches for the custom machine and defconfig can be provided in a u-boot-imx_%.bbappend with these lines as an example and patch1.patch as a patch placed in sources/<custom_layer>/ recipes-bsp/uboot-imx/files:

FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" SRC_URI_append = "file://patch1.patch".

 

 

  3.2  Customizing the i.MX custom board code

 

  새로운 i.MX 커스텀 보드는 U-Boot 소스 트리의 일부이지만 i.MX Reference Board 코드와 중복되므로 커스터마이징 해야 합니다.
  DDR 기술은 두 보드 간의 잠재적인 주요 차이점입니다. DDR 기술에 차이가 있는 경우 DDR 초기화를 포팅해야 합니다. DDR 초기화는 U-Boot 이미지의 부팅 헤더 내부에 있는 DCD 테이블에 코딩되어 있습니다. 부트로더, 커널 또는 드라이버 코드를 포팅할 때 참고하기 위해서 쉽게 접근 가능한 회로도가 있어야 합니다.

 

  3.2.1 i.MX DDR 초기화를 위한 DCD 테이블 변경

 

  메모리 인터페이스를 초기화하기 전에, 관련 I/O 핀을 올바른 모드와 임피던스로 설정한 다음, MMDC 모듈을 초기화하십시오.
  DDR에 대한 Calibration parameters를 생성하는 방법은 i.MX 6 Series DDR Calibration (AN4467) 을 참고하세요. 사용자는 DDR 초기화를 위해 i.MX Design and Tool Lists에서 DDR 스크립트 지원 및 DDR 스트레스 도구를 사용할 수도 있습니다.

  1.  커스텀 보드를 포팅하려면, DDR이 제대로 초기화되어야 합니다.

 

  2.  i.MX 6Quad 커스텀 보드를 예로 들면, Board/freescale/mx6<customer_board_name>/imximage.cfg 파일을 mx6q.cfg로 엽니다.

 

  3.  메모리 사양과 일치하도록 위 파일의 모든 항목을 수정합니다. 이 코드 블록들은 ROM 코드로 읽혀 DDR 메모리를 초기화합니다.

  4.  i.MX 8QuadMax A0, i.MX 8QuadXPlus A0의 경우, U-Boot는 DDR 초기화를 위한 DCD테이블을 포함하지 않습니다. 최종 imx-boot 이미지를 생성하려면 사용자는 imx-mkimage에서 DCD 테이블 파일을 업데이트해야 합니다.

 

  5. i.MX 8QuadXPlus B0, i.MX 8QuadMax B0, i.MX 8DXL의 경우, DDR 초기화 코드는 SCFW에 있습니다. 사용자는 SCFW에서 DCD테이블을 업데이트하고 imx-mkimage에 대한 새 SCFW를 구축해야 합니다.

 

  6.  i.MX 8M Quad, i.MX 8M Mini, i.MX 8M Nano 및 i.MX 8M Plus의 경우, U-Boot에는 DCD가 포함되어 있지 않습니다. DDR을 초기화하는 것은 SPL에 따라 다릅니다. SPL에는 DDR PHY 및 DDR 컨트롤러 초기화와 DDR PHY training을 위한 코드가 포함되어 있으므로 사용자는 코드를 수정해야 합니다.

 

SPL contains the codes for DDR PHY and DDR controller initialization and DDR PHY training, so users need to modify the codes.

 

 

  3.2.2 수정된 U-Boot로 부팅하기


이 섹션에서는 u-boot.imx를 컴파일하고 SD 카드에 쓰는 방법을 설명합니다.
DDR 구성(board/freescale/<customer_board_name>/imximage.cfg)이 성공적으로 수정되면, u-boot.imx를 컴파일하고 SD 카드에 쓸 수 있습니다. 이를 확인하려면 SD카드를 CPU보드의 SD카드 소켓에 삽입하고 보드의 전원을 켜십시오.
보드가 i.MX 6Quad SABRESD를 기반으로 하는 경우 콘솔에 다음 메시지가 표시되어야 합니다.
커스텀 보드가 i.MX 8QuadMax Validation 보드를 기반으로 하는 경우 콘솔에 다음 메시지가 표시되어야 합니다.:

U-Boot 2017.03-00240-gb8760a1 (March 10 2017 - 14:32:18)
CPU:   Freescale i.MX6Q rev1.2 at 792 MHz
CPU:   Temperature 36 C
Reset cause: POR
Board: MX6Q-Sabreauto revA
I2C:   ready
DRAM:  2 GiB
PMIC:  PFUZE100 ID=0x10
NAND:  0 MiB
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
No panel detected: default to Hannstar-XGA
Display: Hannstar-XGA (1024x768)
In:    serial
Out:   serial Err:   serial
switch to partitions #0, OK mmc1 is current device
Net:   FEC [PRIME]
Normal Boot
Hit any key to stop autoboot:  0
=>
U-Boot 2017.03-imx_4.9.51_8qm_beta1_8qxp_alpha+gc1ec08e (Nov 22 2017 - 00:39:31
 -0600)
CPU:   Freescale i.MX8QM revA A53 at 1200 MHz at 12C
Model: Freescale i.MX8QM ARM2
Board: iMX8QM LPDDR4 ARM2
Boot:  SD1
DRAM:  6 GiB start sata init
SATA link 0 timeout.
MMC:   Actual rate for SDHC_0 is 396000000
Actual rate for SDHC_1 is 396000000
Actual rate for SDHC_2 is 396000000
FSL_SDHC: 0, FSL_SDHC: 1, FSL_SDHC: 2
Run CMD11 1.8V switch
*** Warning - bad CRC, using default environment
[pcie_ctrla_init_rc] LNK DOWN 8600000
In:    serial
Out:   serial
Err:   serial  BuildInfo:
-  SCFW 9f3fa3da, IMX-MKIMAGE 90fbac1a, ATF
-  U-Boot 2017.03-imx_4.9.51_8qm_beta1_8qxp_alpha+gc1ec08e
switch to partitions #0, OK
mmc1 is current device
SCSI:  Net:
Warning: ethernet@5b040000 using MAC address from ROM
eth0: ethernet@5b040000 [PRIME]
Error: ethernet@5b050000 address not set.
Normal Boot
Hit any key to stop autoboot:  0

 

 

  커스텀 보드가 i.MX 8M Quad EVK 보드를 기반으로 하는 경우 콘솔에 다음 메시지가 표시되어야 합니다.

U-Boot SPL 2017.03-imx_v2017.03_4.9.51_imx8m_ga+gb026428 (Mar 01 2018 -
 03:15:20)
PMIC:  PFUZE100 ID=0x10
start to config phy: p0=3200mts, p1=667mts with 1D2D training
check ddr4_pmu_train_imem code check ddr4_pmu_train_imem code pass check ddr4_pmu_train_dmem code check ddr4_pmu_train_dmem code pass config to do 3200 1d training.
Training PASS
check ddr4_pmu_train_imem code check ddr4_pmu_train_imem code pass check ddr4_pmu_train_dmem code check ddr4_pmu_train_dmem code pass config to do 3200 2d training.
Training PASS
check ddr4_pmu_train_imem code check ddr4_pmu_train_imem code pass check ddr4_pmu_train_dmem code check ddr4_pmu_train_dmem code pass pstate=1: set dfi clk done done
Training PASS
Load 201711 PIE
Normal Boot
Trying to boot from MMC2
U-Boot 2017.03-imx_v2017.03_4.9.51_imx8m_ga+gb026428 (Mar 01 2018 - 03:15:20
 -0600)
CPU:   Freescale i.MX8MQ rev2.0 1500 MHz (running at 1000 MHz)
CPU:   Commercial temperature grade (0C to 95C) at 21C
Reset cause: POR
Model: Freescale i.MX8MQ EVK
DRAM:  3 GiB
TCPC:  Vendor ID [0x1fc9], Product ID [0x5110]
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
*** Warning - bad CRC, using default environment
No panel detected: default to HDMI
Display: HDMI (1280x720)
In:    serial
Out:   serial
Err:   serial  BuildInfo:
-  ATF d2cbb20
-  U-Boot 2017.03-imx_v2017.03_4.9.51_imx8m_ga+gb026428
switch to partitions #0, OK mmc1 is current device
Net:
Warning: ethernet@30be0000 using MAC address from ROM
eth0: ethernet@30be0000
Normal Boot
Hit any key to stop autoboot:  0 u-boot=>

 

 

  3.2.3 보드 파일에 새 드라이버 초기화 코드 추가

 

다음 단계에서는 새 드라이버를 추가하는 방법과 코드를 초기화하는 방법을 설명합니다.

  1.  board/freescale/mx<customer_board>/에서 mx<customer_board>.c를 찾습니다.
  2.  mx<customer_board>.c를 편집하고, 새 드라이버 초기화 코드,  clock, IOMUX 및 GPIO를 추가합니다.
  3.  드라이버 초기화 기능을 Board_init 또는 Board_late_init에 넣습니다.

 

Note:  
• 다음을 정의하면 매우 초기 단계에서 Board_early_init_f() 함수가 호출됩니다.
CONFIG_BOARD_EARLY_INIT_F. 아주 초기 단계에서 설정해야 하는 UART/SPI-NOR/NAND IOMUX 설정 기능을 넣을 수 있습니다.
• Board_init() 함수는 Board_early_init_f와 Board_late_init 사이에서 호출됩니다. 여기에서 일반적인 보드 수준 설정을 수행할 수 있습니다. CONFIG_BOARD_EARLY_INIT_F를 정의하지 않은 경우 UART 설정이 완료되기 전에 printf를 호출하지 마세요. 그렇지 않으면 시스템이 다운될 수 있습니다.
• Board_late_init() 함수는 나중에 호출됩니다. 초기화 코드를 디버깅하려면 초기화 함수를 그 안에 넣으세요.

 

 

  3.2.4 시스템 부팅 시 추가 사용자 정의


U-Boot 보드 프로젝트를 추가로 사용자 정의하려면 시스템 부팅이 호출하는 첫 번째 함수를 사용하세요.

board_init_f in "common/board_f.c"
board_early_init_f() board_init()

 

  모든 보드 초기화는 이 함수 내에서 실행됩니다. init_sequence_f[] 배열과 init_sequence_r[] 함수 포인터 배열을 통해 실행하는 것으로 시작됩니다.
  init_sequence_f[] 배열 내부의 첫 번째 보드 종속 함수는 board_early_init_f()입니다. Board_early_init_f()는 board/freescale/mx6<custom board name>.c 내부에서 구현됩니다.
  다음 코드 줄은 매우 중요합니다.

...
setup_iomux_uart(); ...

Note: 디바이스 트리를 사용하는 경우 컴퓨터 ID는 사용되지 않습니다. DTS 파일의 호환 문자열을 사용하여 보드를 일치시킵니다. 각 부팅 변형 파일의 장치 트리는 arch/arm/dts 디렉토리의 시스템 구성 파일에 지정됩니다.

 

 

  3.2.5  Customizing the printed board name

 

  보드 이름을 사용자 정의하려면 checkboard() 함수를 사용하십시오.

  이 함수는 board/freescale/ mx6<custom board name>.c 내에 구현된 init_sequence_f[] 배열에서 호출됩니다. 보드 이름을 변경하기 위해 checkboard()를 사용하는 방법에는 두 가지가 있습니다:  brute force way 또는 커스텀 보드에 구현된 경우 보다 유연한 식별 방법을 사용하는 것입니다.

 

  brute force way를 변경하려면 checkboard() 내부에서 recognition_board_id()를 삭제하고 printf("Board: ");를 교체하세요. printf("보드: <custom board>의 i.MX\n");.

  교체가 이루어지지 않을 경우 커스텀 보드는 다른 식별 방법을 사용할 수 있습니다. 커스텀 보드에 식별 방법에 따라 __print_board_info() 함수를 구현하여 식별을 감지하고 인쇄할 수 있습니다.

 

 

  3.3  Debugging

 

  디버깅을 수행하는 방법에는 두 가지가 있습니다.
    • JTAG 툴 사용
    • printf 사용

 

 

  3.3.1 디버깅을 위해 JTAG tool 사용


  일반적으로 JTAG은 매우 초기 단계, 예를 들어 UART 초기화 전이나 printf로 디버깅하기 어려울 때 디버깅하는 데 사용됩니다.

  1.  JTAG 툴이 i.MX 6의 Arm Cortex-A9 코어, i.MX 7Dual 및 6UltraLite의 Arm Cortex-A7 코어, i.MX 8QuadMax의 Arm Cortex-A53/A72 및 i.MX 8QuadXPlus의 Arm Cortex-A35를 지원하는지 확인하십시오. TRACE32를 사용하는 것이 좋습니다.
  2.  ELF 파일인 U-Boot를 U-Boot의 루트 디렉터리에 완전히 로드하거나 기호만(빠르게) 로드하여 단계별로 디버그합니다.

Note:  컴파일 시 최적화 수준을 0으로 설정하세요. 이렇게 하면 JTAG 도구에서 디버깅하기가 더 쉽습니다.

 

 

  3.3.2 디버깅을 위해 printf 사용하기


  이는 디버깅에 사용되는 가장 일반적인 방법입니다. 디버깅을 위해 드라이버에서 값을 인쇄할 수 있습니다.

Note:  Board_init와 같은 초기 단계에서 printf를 사용하려면 board_early_init_f()와 같이 UART 초기화 코드를 더 일찍 배치하십시오. 인쇄된 보드 이름을 사용자 정의하려면 checkboard() 함수를 사용하십시오.