정보
IMXBSPPG
Rev. LF5.15.5_1.0.0, 31 March 2022를 기준으로 작성
Chapter 3 Porting U-Boot
3.1 Introduction
이 장에서는 i.MX U-Boot를 다운로드, 빌드, 로드하는 방법을 설명한다. 독립 실행형(standalone) 환경과 Yocto Project로 하는 두 가지 방법을 설명한다.
3.1.1 How to build U-Boot in standalone envirnoment
독립 실행형 환경에서 U-Boot를 빌드하려면 아래 단계를 수행한다 :
- 호스트 시스템에 배치하여 컴파일하기 위한 개발 SDK를 생성한다. 여기에는 툴, 툴 체인, 작은 rootfs가 포함된다. 동일한 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가 실행된 빌드 디렉토리에서, .sh파일을 tmp/deploy/sdk에서 호스트 머신으로 복사하고 SDK를 설치하기 위해 스크립트를 실행한다. 기본 위치는 /opt이지만 호스트 머신의 어디에나 배치할 수 있다.
- 아래의 명령어를 사용하여 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는 현재 릴리즈에서 최신 헤더, 툴 체인, 툴을 선택하도록 각 릴리즈에 대해 업데이트되어야 한다.
- 호스트 시스템에서 U-Boot 빌드를 위해 다음 단계를 수행한다 :
- 호스트 머신에서, i.MX 8 SoC 용으로 빌드하기 전에 아래의 명령어로 환경을 설정한다.
$ source/opt/fsl-imx-xwayland/5.15.5/environment-setup-aarch64-poky-linux $ export ARCH=arm64
- 호스트 머신에서, i.MX 6이나 i.MX 7 SoC 용으로 빌드하기 전에 아래의 명령어로 환경을 설정한다.
$ export CROSS_COMPILE=/opt/fsl-imx-fb/5.15.5/environment-setup-cortexa9hf-vfp-neon-poky-linux-gnueabi $ export ARCH=arm
- 독립 실행형 환경에서 U-Boot를 빌드하려면, 아래의 명령어를 실행한다.
clone으로 소스를 다운로드한다 :
$ git clone https://source.codeaurora.org/external/imx/uboot-imx
- 독립 실행형 환경에서 U-Boot를 빌드하려면, uboot-imx 소스 코드의 configs/ 디렉토리에서 대상 boot에 대한 구성을 찾는다. 아래의 예는 i.MX 6ULL이 대상인 경우이다.
$ cd uboot-imx $ make distclean $ make mx6ull_14x14_evk_defconfig $ make
- 사용자 보드를 생성하려면, 해당 SoC에 대한 레퍼런스 defconfig를 새 이름으로 복사하고 config 폴더에 저장하고 새로운 구성 이름을 사용하여 빌드한다.
- i.MX 8의 경우, imx-mkimage 툴을 사용하여 U-Boot 바이너리를 Arm Trusted Firmware (ATF) 및 SCFW 결합하여 최종 flash.bin 부팅 이미지를 생성하고, SD 카드에 저장한다. 자세한 내용은 imx-mkimage 툴을 참고한다.
- 부팅 이미지를 SD 카드에 저장하려면, 아래의 명령어를 실행한다 :
dd if=<boot_image> of=/dev/sd<x> bs=1k seek=<offset> conv=fsync
명령어 옵션 설명 :
- offset는
- 1 - i.MX 6이나 i.MX 7 용
- 33 - i.MX 8QuadMax A0, i.MX 8QuadXPlus A0, i.MX 8M Quad, i.MX 8M Mini 용
- 32 - i.MX 8QuadXPlus B0, i.MX 8QuadMax B0, i.MX 8DXL, i.MX 8M Nano, i.MX 8M Plus
- sd<x>는
- SD 카드에 대한 디바이스 노드
- boot_image는
- u-boot.imx - i.MX 6이나 i.MX 7 용
- flash.bin - i.MX 8
- offset는
- 호스트 머신에서, i.MX 8 SoC 용으로 빌드하기 전에 아래의 명령어로 환경을 설정한다.
3.1.2 How to build and load U-Boot in Yocto Project
Yocto Project에서 U-Boot 변경 사항을 통합하려면, 아래의 단계를 수행한다 :
- 매니페스트(manifest) 브랜치나 릴리즈 레이어의 README 지침에 따라 Yocto Project의 i.MX 레퍼런스 보드에 해당되는 SoC를 빌드하기 위한 환경을 설정한다. 여기에는 Yocto Project 메타 데이터와 빌드 환경 설정을 위한 imx-setup-release를 다운로드하기 위한 리포지토리(저장소) 초기화와 리포지토리 동기화 사용이 포함된다.
- 해당되는 SoC에 대한 레퍼런스 보드 커널을 빌드한다. 아래는 예이다. 처음으로, 이빌드는 필요한 모든 툴과 종속 관계의 것 들을 빌드하기 때문에 긴 시간이 걸린다.
$ MACHINE=imx6qsabresd bitbake u-boot-imx
- 사용자 보드에 대한 커널 변경 사항을 보관할 사용자 정의 레이어를 만든다. 사용자 정의 레이어를 생성하는 더 간단한 예로 기존 i.MX 데모의 XBMC나 IOTG를 살펴본다. 사용자 정의 레이어는 <build-dir>/conf 디렉토리의 bblayer.conf에 추가하여 통합된다. 레이어에는 레이어를 설명하는 conf/layer.conf 파일이 있어야한다.
- 사용자 보드 SoC에 해당되는 기존 머신 파일을 사용자 정의 레이어에 복사한다 :
$ cp sources/meta-freescale/conf/machine/imx6qsabresd.conf <new layer>/conf/machine/<custom_name>.conf
- UBOOT_CONFIG 옵션을 사용하여 머신 구성을 편집한다.
- 아래 줄을 conf/local.conf에 추가하여 u-boot-imx로 빌드할 커널의 기본 버전을 변경한다. 여러 U-Boot 공급자가 있어서, 이로 인해 u-boot-imx 버전을 지정해서 사용해야 한다.
PREFERRED_PROVIDER_virtual/bootloader_<custom_name> = "u-boot-imx"
- 사용자 머신 빌드
<build-dir>/tmp/work/<custom_name>-poky-linux-gnueabi/u-boot-imx/<version>을 확인하여 빌드 출력을 찾는다. 또한 <build-dir>/tmp/deploy/images/<custom_name>에서 부팅 바이너리를 찾는다.$ MACHINE=<custom_name> bitbake u-boot-imx
- 사용자 머신과 defconfig에 대한 U-Boot 패치는 u-boot-imx_%.bbappend에 제공될 수 있으며, 이러한 행을 예제로 patch1.patch은 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 레퍼런스 보드 코드의 복제본이고 사용자 정의해야 한다.
DDR 기술은 두 보드 사이(사용자 보드와 레퍼런스 보드)에 잠재적인 주요 차이점이다. DDR 기술에 차이가 있는 경우, DDR 초기화를 포팅해야 한다. DDR 초기화는 U-Boot 이미지의 부트 헤더 내부에 있는 DCD 테이블에 코드로 되어 있다. 부트로더, 커널 또는 드라이버 코드를 포팅할 때, 레퍼런스를 위해 쉽게 접근할 수 있는 회로도가 있어야 한다.
두 보드 사이의 DDR 기술에 차이가 있는 경우, DDR 초기화를 포팅해야 한다. DDR 초기화는 U-Boot 이미지의 부트 헤더 내부에 있는 DCD 테이블에 코드로 되어 있다. 부트로더, 커널 또는 드라이버 코드를 포팅할 때, 레퍼런스를 위해 쉽게 접근할 수 있는 회로도가 있어야 한다.
3.2.1 Changing the DCD table for i.MX DDR initialization
메모리 인터페이스를 초기화하기 전에, 해당 I/O 핀을 적확한 모드와 임피던스로 구성하고 MMDC 모듈을 초기화한다.
DDR에 대한 캘리브레이션 파라미터를 생성하는 방법은, i.MX 6 Series DDR Calibration (AN4467)을 참조한다. 또한 사용자는 DDR 초기화를 위해 i.MX Design and Tool Lists에서 DDR script Aid 및 DDR stress tools를 사용할 수 있다.
- 사용자 보드에 포팅하려면, DDR을 정확하게 초기화해야 한다.
- i.MX 6Quad 사용자 보드로 예를 들어 본다. board/freescale/mx6<customer_board_name>/imximage.cfg to mx6q.cfg 파일을 연다.
- 메모리 사양과 일치하도록 이 파일의 모든 항목을 수정한다. 이 코드 블록은 DDR 메모리를 초기화하기 위해 ROM 코드에서 읽혀진다.
- i.MX 8QuadMax A0와 i.MX 8QuadXPlus A0의 경우, U-Boot는 DDR 초기화를 위한 DCD 테이블을 포함하지 않는다. 최종 imx-boot 이미지를 생성하려면, 사용자는 imx-mkimage에서 DCD 테이블을 업데이트해야 한다.
- i.MX 8QuadXPlus B0, i.MX 8QuadMax B0, i.MX 8DXL의 경우, DDR 초기화 코드는 SCFW에 있다. 사용자는 SCFW에서 DCD 테이블을 업데이트하고, imx-mkimage로 새로운 SCFW을 빌드해야 한다.
- 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 트레이닝 코드가 포함된다. 그래서 사용자가 코드를 수정해야 한다.
3.2.2 Booting with the modified U-Boot
이 섹션에서는 u-boot.imx를 컴파일하고 SD 카드에 저장하는 방법을 설명한다.
DDR 구성(board/freescale/<customer_board_name>/imximage.cfg)을 성공적으로 수정하면, 사용자는 u-boot.imx를 컴파일하고 SD 카드에 저장할 수 있다. 이를 확인하려면, SD 카드를 CPU 보드의 SD 카드 소켓에 삽입하고 보드의 전원을 켠다.
보드가 i.MX 6Quad SABRE-SD를 기반으로 하는 경우, 콘솔에 아래 메세지가 표시되어야 한다 :
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
=>
사용자 보드가 i.MX 8QuadMax Validation 보드를 기반으로 하는 경우, 콘솔에 다음 메세지가 표시되어야 한다 :
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 Adding new driver initialization code to board files
아래 단계는 새로운 드라이버를 추가하는 방법과 코드를 초기화하는 방법을 설명한다.
- board/freescale/mx<customer_board>/에서 mx<customer_board>.c를 찾는다.
- mx<customer_board>.c를 편집하고, clock, IOMUX, GPIO를 포함한 새로운 드라이버 초기화 코드를 추가한다.
- 드라이버 초기화 함수를 board_init이나 board_late_init에 배치한다.
참고
- 사용자가 CONFIG_BOARD_EARLY_INIT_F를 정의하면, 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 Futher customization at system boot
사용자 U-Boot 보드 프로젝트에 추가로 사용자 정의하려면, 시스템 부트에서 호출하는 첫 번째 함수를 사용한다 :
board_init_f in "common/board_f.c"
board_early_init_f()
board_init()
모든 보드 초기화는 이 함수 내에서 실행된다. 함수 포인터인 init_requence_f[] array와 init_sequence_r[] array을 통해 실행하는 것으로 시작한다.
init_sequence_f[] array 내부의 첫 번재 보드에 종속된 함수는 board_early_init_f()이다. board_early_init_f()는 board/freescale/mx6<custom board name>.c 내부에 구현되어 있다.
아래 코드 라인은 매우 중요하다 :
...
setup_iomux_uart();
...
참고
디바이스 트리를 사용하는 경우, machine ID는 사용되지 않는다. DTS 파일의 호환 가능한 문자열은 보드를 일치하는 데 사용된다. 변형된 각 부트 파일에 대한 디바이스 트리는 arch/arm/dts 디렉토리의 머신 구성 파일에서 지정된다.
3.2.5 Customizing the printed board name
출력되는 보드 이름을 사용자 정의하려면, checkboard() 함수를 사용한다.
이 함수는 board/freescale/mx6<custom board name>.c 내부에 구현된 init_sequence_f[] array에서 호출된다. 출력되는 보드 이름을 사용자 정의하는 데 checkboard()를 사용하는 두 가지 방법이 있다. 무차별 대입(brute force) 방식 또는 사용자 보드에서 구현되는 경우 보다 유연한 식별 방법을 사용하는 것이다.
무차별 대입 방식으로 사용자 정의하려면, checkboard() 내부에서 identify_board_id()를 삭제하고 printf("Board: "); 를 printf("Board: i.MX on <custom board>\n"); 로 변경한다.
이 교체가 이루어지지 않으면, 사용자 보드는 다른 식별 방법을 사용할 수 있다. 사용자 보드 식별 방법에 따라서 식별은 감지할 수 있고 __print_board_info() 함수를 구현하여 출력할 수 있다.
3.3 Debugging
디버깅을 하는 두 가지 방법이 있다 :
- JTAG 툴을 사용하는 방법
- printf를 사용하는 방법
3.3.1 Using JTAG tool for debugging
일반적으로 JTAG 툴은 UART 초기화 전과 같이 아주 이른 단계에서 디버그하거나 printf로 디버그하기 어려운 경우에 사용된다.
- 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 사용을 권장한다.
- ELF 파일인 U-Boot를 U-Boot 루트 디렉토리에 완전히 로드하거나 단지 심볼(빠르게)만 로드하여 단계별로 디버깅한다.
참고
JTAG 툴에서 디버깅하기 더 쉽도록 컴파일 최적화 수준을 0으로 만든다.
3.3.2 Using printf for debugging
이는 디버깅에 사용되는 가장 일반적인 방법이다. 사용자는 디버깅을 위해 드라이버에서 값을 출력할 수 있다.
참고
board_init와 같은 초기 단계에서 printf를 사용하려면, board_early_init_f()와 같이 UART 초기화 코드를 초기에 배치한다.
'NXP i.MX SoC Family > i.MX BSP Porting Guide' 카테고리의 다른 글
i.MX BSP Porting Guide - Configuring OP-TEE (0) | 2022.07.02 |
---|---|
i.MX BSP Porting Guide - Porting System Controller Firmware (0) | 2022.07.01 |
i.MX BSP Porting Guide - Porting Kernel (0) | 2022.06.29 |
i.MX BSP Porting Guide - Supporting Cameras with MIPI-CSI (0) | 2022.06.29 |
i.MX BSP Porting Guide - Introduction (0) | 2022.06.29 |