2025년 6월 27일 금요일

NVIDIA Jetson Orin Nano Developer Kit와 AI Programming(#3)

이번 시간에는 지난 시간에 이어 NVIDIA Jetson Orin Nano Developer Kit를 해부(3번째 시간)해 보고, 느낀 점을 독자 여러분과 공유해 보고자 한다. 😎

The 3rd time 🚀🚀🚀

목차
6. Jetson Kit Device Tree Overview
7. GPIO and DTB Overlay
8. I2C and SPI Device Tree and Device Drivers
9. CSI Camera and Others
10. Jetson AI - LLM 돌려 보기
References


Jetson Orin Nano Dev Kit은 다양한 주변 장치를 제공하고 있다. 따라서 이번 posting을 통해 어떠한 주변 장치가 있는지, 그리고 해당 주변 장치를 어떻게 제어할 수 있는지 최대한 확인해 보도록 하자. 😌


6. Jetson Kit Device Tree Overview
이번 장에서는Jetson Linux BSP 관련 내용 중, Device Tree와 Device Driver에 관한 내용을 살펴 보고자 한다. Jetson Orin Nano Dev Kit는 아주 다양한 주변 장치를 제공하고 있다. 따라서 이번 posting(혹은 다음 posting)에서는 아주 간단한 수준일지라도 최대한 많은 종류의 device를 사용하고 넘어가기로 하자. 💪

[그림 6.1] Jetson Orin Nano Carrier Board Block Diagram [출처 - 참고문헌 5]

[그림 6.2] Jetson Orin Module Interfaces [출처 - 참고문헌 6]

이번 장에서 소개하는 내용은 아래 jetson 공식 document site로 부터 많은 영감(?)을 받아 작성하였다.


6.1 Device Tree 분석
먼저, Jetson Orin Nano Dev Kit를 위한 device tree 파일은 아래 위치에 정의되어 있다.

Linux_for_Tegra/source/hardware/nvidia/t23x/nv-public  (bottom layer)

-rw-rw-r-- 1 chyi chyi   3318  6월 18 14:48 tegra234-p3701-0000.dtsi
-rw-rw-r-- 1 chyi chyi   2086  6월 18 14:48 tegra234-p3701-0008.dtsi
-rw-rw-r-- 1 chyi chyi    636  6월 18 14:48 tegra234-p3701.dtsi
-rw-rw-r-- 1 chyi chyi  10468  6월 18 14:48 tegra234-p3737-0000+p3701-0000.dts
-rw-rw-r-- 1 chyi chyi   1645  6월 18 14:48 tegra234-p3737-0000.dtsi
-rw-rw-r-- 1 chyi chyi   6517  6월 18 14:48 tegra234-p3740-0002+p3701-0008.dts
-rw-rw-r-- 1 chyi chyi   4407  6월 18 14:48 tegra234-p3740-0002.dtsi
-rw-rw-r-- 1 chyi chyi   5611  6월 18 14:48 tegra234-p3767.dtsi
-rw-rw-r-- 1 chyi chyi   2272  6월 18 14:48 tegra234-p3768-0000+p3767-0000.dts
-rw-rw-r-- 1 chyi chyi    883  6월 18 14:48 tegra234-p3768-0000+p3767-0005.dts
-rw-rw-r-- 1 chyi chyi   4691  6월 18 14:48 tegra234-p3768-0000.dtsi
-rw-rw-r-- 1 chyi chyi 161432  6월 18 14:48 tegra234.dtsi
___________________________________________________

Linux_for_Tegra/source/hardware/nvidia/t23x/nv-public/nv-platform  (top layer)

-rw-r--r-- 1 chyi chyi 11930  1월  8 10:10 tegra234-camera-p3785.dtsi
-rw-r--r-- 1 chyi chyi 27005  1월  8 10:10 tegra234-dcb-p3737-0000-p3701-0000.dtsi
-rw-r--r-- 1 chyi chyi  6403  1월  8 10:10 tegra234-p3701-0000-prod-overlay.dtsi
-rw-r--r-- 1 chyi chyi  2299  1월  8 10:10 tegra234-p3701-0000.dtsi
-rw-r--r-- 1 chyi chyi   478  1월  8 10:10 tegra234-p3701-0005.dtsi
-rw-r--r-- 1 chyi chyi  2912  1월  8 10:10 tegra234-p3701-0008.dtsi
-rw-r--r-- 1 chyi chyi   294  1월  8 10:10 tegra234-p3737-0000+p3701-0000-nv.dts
-rw-r--r-- 1 chyi chyi   302  1월  8 10:10 tegra234-p3737-0000+p3701-0004-nv.dts
-rw-r--r-- 1 chyi chyi   302  1월  8 10:10 tegra234-p3737-0000+p3701-0005-nv.dts
-rw-r--r-- 1 chyi chyi   302  1월  8 10:10 tegra234-p3737-0000+p3701-0008-nv.dts
-rw-r--r-- 1 chyi chyi  4444  1월  8 10:10 tegra234-p3737-0000+p3701-xxxx-nv-common.dtsi
-rw-r--r-- 1 chyi chyi  3509  1월  8 10:10 tegra234-p3737-0000.dtsi
-rw-r--r-- 1 chyi chyi  5589  1월  8 10:10 tegra234-p3740-0002+p3701-0008-nv-common.dtsi
-rw-r--r-- 1 chyi chyi   312  1월  8 10:10 tegra234-p3740-0002+p3701-0008-nv-safety.dts
-rw-r--r-- 1 chyi chyi   258  1월  8 10:10 tegra234-p3740-0002+p3701-0008-nv.dts
-rw-r--r-- 1 chyi chyi  5177  1월  8 10:10 tegra234-p3740-0002+p3701-0008-safety.dtsi
-rw-r--r-- 1 chyi chyi  6418  1월  8 10:10 tegra234-p3740-0002.dtsi
-rw-r--r-- 1 chyi chyi  2133  1월  8 10:10 tegra234-p3767-0000.dtsi
-rw-r--r-- 1 chyi chyi   501  1월  8 10:10 tegra234-p3768-0000+p3767-0000-nv-px1.dts
-rw-r--r-- 1 chyi chyi   375  1월  8 10:10 tegra234-p3768-0000+p3767-0000-nv-super.dts
-rw-r--r-- 1 chyi chyi   248  1월  8 10:10 tegra234-p3768-0000+p3767-0000-nv-taylor-high.dts
-rw-r--r-- 1 chyi chyi   246  1월  8 10:10 tegra234-p3768-0000+p3767-0000-nv-taylor-low.dts
-rw-r--r-- 1 chyi chyi   258  1월  8 10:10 tegra234-p3768-0000+p3767-0000-nv.dts
-rw-r--r-- 1 chyi chyi   375  1월  8 10:10 tegra234-p3768-0000+p3767-0001-nv-super.dts
-rw-r--r-- 1 chyi chyi   266  1월  8 10:10 tegra234-p3768-0000+p3767-0001-nv.dts
-rw-r--r-- 1 chyi chyi   537  1월  8 10:10 tegra234-p3768-0000+p3767-0003-nv-super.dts
-rw-r--r-- 1 chyi chyi   468  1월  8 10:10 tegra234-p3768-0000+p3767-0003-nv.dts
-rw-r--r-- 1 chyi chyi   537  1월  8 10:10 tegra234-p3768-0000+p3767-0004-nv-super.dts
-rw-r--r-- 1 chyi chyi   468  1월  8 10:10 tegra234-p3768-0000+p3767-0004-nv.dts
-rw-r--r-- 1 chyi chyi   537  1월  8 10:10 tegra234-p3768-0000+p3767-0005-nv-super.dts
-rw-r--r-- 1 chyi chyi   460  1월  8 10:10 tegra234-p3768-0000+p3767-0005-nv.dts
-rw-r--r-- 1 chyi chyi  7204  1월  8 10:10 tegra234-p3768-0000+p3767-xxxx-nv-common.dtsi
-rw-r--r-- 1 chyi chyi   847  1월  8 10:10 tegra234-p3768-0000.dtsi
📌 tegra234는 soc 명칭을, p3767은 som part number를, 그리고 p3768은 carrier board part number를 칭한다.
___________________________________________________

<Jetson Orin Nano Dev Kit device tree 계층 구조>
위의 많은 dts/dtsi 파일 중에서 Jetson Orin Nano Dev Kit 관련 부분만을 계층 구조로 정리해 보면 다음과 같다.

tegra234.dtsi
(SoC)
^
|
tegra234-p3767.dtsi
(SOM)
tegra234-p3768-0000.dtsi
(Carrier board)
^
|
tegra234-p3768-0000+p3767-0005.dts
(jetson orin nano dev kit) <- bottom layer
tegra234-p3768-0000+p3767-xxxx-nv-common.dtsi
^
|
tegra234-p3768-0000+p3767-0005-nv.dts
(nv-public/nv-platform) <- top layer

위의 device tree 계층 구조를 구성하는 주요 파일(dtsi/dts)을 하나씩 나열해 보았다.

[그림 6.3] tegra234.dtsi - SoC
📌 tegra234 SoC에 대한 device tree인데, 내용이 아주 길다.

[그림 6.4] tegra234-p3767.dtsi 파일 - SOM Module

[그림 6.5] tegra234-p3768-0000.dtsi 파일 - Reference Carrier Board

[그림 6.6] NVIDIA Jetson Orin Nano Dev Kit에 대한 device tree - tegra234-p3768-0000+p3767-0005.dts

[그림 6.7] nv-platform/tegra234-p3768-0000+p3767-xxxx-nv-common.dtsi

[그림 6.8] nv-platform/tegra234-p3768-0000+p3767-0005-nv.dts

현 시점에서 각각의 device tree 파일을 일일이 설명할 필요는 없을 듯하며, 필요시 각 파일의 내용을 들여다 보면서 이해(수정/변경)해야 할 것으로 보인다. 😋


6.2 Tegra234 GPIO 해부
Tegra234 SoC에는 2개의 GPIO controller chip(gpiochip0: main gpio, gpiochip1: aon gpio)이 내장되어 있다. 이 중 gpiochip0(Main GPIO chip)은 24개의 bank(GPIO_PORT_A ~ Z, GPIO_PORT_AC ~ AG)로 구성되어 있고, gpiochip1(AON GPIO chip)은 6개의 bank(GPIO_PORT_AA ~ GG)로 구성되어 있다. 이는 gpiodetect 명령과 gpioinfo 명령을 통해서도 확인 가능하다.

...
[그림 6.9] gpiodetect and gpioinfo 명령 실행 모습
📌 gpiochip0은 164개의 gpio line이 있고, gpiochip1은 32개의 line이 있다. 
📌 한편, gpioinfo, gpiodetect 명령 등을 포함한 libgpiod 관련 자세한 사항은 아래 문서를 참조하기 바란다.

한편, 아래 table은 gpiochip0의 bank(port) 정보, bank 당 pin의 갯수, 그리고 누적 핀의 갯수(offset) 정보를 보여준다.

[그림 6.10] gpiochip0(main gpio chip) port 구성 정보 [출처 - 참고문헌 3]

위의 내용에도 나와 있듯이, 보통은 각 bank(or port)당 8개의 gpio line이 존재할 것 같지만, 실제로는 그렇지 않은 것들도 보인다. 따라서 아래의 공식에 의해 각각 최대 192와 48개의 gpio line이 있어야 하지만, 실제로는 앞서 확인해 본 바와 같이 164개와 32개의 line만 존재하게 된다.

gpiochip0 : 24 bank(= port) x 8 = 192 lines
gpiochip1 : 6 bank(= port) x = 48 lines

따라서, 실제 gpio line 번호를 계산하는 것도 약간은 불편해 보인다. 가령 이전 posting에서 다루었던 J14 header pin 10(Force Recovery)의 경우는 아래와 같이 line 35(PG.00 = PORT G 0번 line)에 해당하는데, 이는 위의 table의 Port Offset 내용을 보면 그 이유를 쉽게 알 수가 있다.

line  35:      "PG.00" "Force Recovery" input active-low [used]

[그림 6.11] J14 header pin 10 Force Recovery => gpiochip0 PG.00(= line 35)
📌 PORT A (8개) + PORT B (1개) + PORT C (8개) + PORT D (4개) + PORT E (8개) + PORT F (6개) = 35가 된다.

참고로, 아래 내용은 carrier board device tree 내용 중, Force Recovery pin 설정 부분인데, 이를 통해 역으로 GPIO 정보(TEGRA234_MAIN_GPIO(G, 0))를 확인할 수도 있다.

<tegra234-p3768-0000.dtsi 파일 내용>
        key-force-recovery {
           label = "Force Recovery";
           gpios = <&gpio TEGRA234_MAIN_GPIO(G, 0) GPIO_ACTIVE_LOW>/* PG.00 */
           linux,input-type = <EV_KEY>;
           linux,code = <BTN_1>;
       };


한편, linux kernel에서는 아래와 같이 PG.00 line을 gpio-383으로 인식하는데, 383은 port offset 35에 gpiochip0 base index 값(= 348)을 더한 결과이다. 즉, 348 + 35 + 0 = 383.

📌 tegra234-gpio(gpiochip0)의 base index 348이고, tegra234-gpio-aon(gpiochip1) 316을 사용한다.

따라서 kernel에서 인식하는 gpio number는 아래의 공식을 기반으로 한다고 이해하면 된다.
base index + port_offset + pin_offset

지금까지 Jetson Orin Nano Dev Kit의 GPIO 구성에 대한 내용을 대략적으로 살펴 보았다. 이제부터는 간단한 GPIO 테스트를 진행해 보기로 하자.

<시험 내용>
gpio-383(Factory Recovery pin)에 아래와 같은 GPIO 설정 시험을 진행해 보고 싶다.

Hi(default state) -> Lo(0 설정) -> Hi(1 설정)

<시험 방법>
  -> libgpiod project에서 제공하는 gpioset 명령을 이용한다.

chyi@jetsonkit:~$ gpioset 0 35=0
gpioset: error setting the GPIO line values: Device or resource busy
chyi@jetsonkit:~$ gpioset 0 35=1
gpioset: error setting the GPIO line values: Device or resource busy

어라, 그런데 어찌된 일인지 명령이 안먹힌다. 💤 왜 그럴까 ?

(다른 숨겨진 이유가 있을 수도 있으니) 그렇다면, 다른 GPIO port에 대해 동일한 시험을 해보면 어떨까 ? 아래 그림은 J12 40 pin 확장 헤더를 나타내는데, 이 중 7번 pin(GPIO09)를 대상으로 동일한 시험을 진행해 보기로 하자.

[그림 6.12] J12 40-pin 확장 헤더 [출처 - 참고문헌 5]

그런데, 7번 pin은 Raspberry Pi 확장 헤더와 비슷한 개념으로 정의된 번호이며, GPIO09는 Orin module의 pin name으로 보인다. 그렇다면, 우리에게 실제로 필요한 정보인 SoC내의 GPIO port number는 어떻게 알 수가 있을까 ? 
(결론 부터 얘기하면) 이를 위해 [참고문헌 5]에서 아래 테이블을 찾았는데, 아래 내용을 보면 위의 7번 pin에 해당하는 SoC GPIO Port#는 GPIO PAC.06임을 알 수가 있다(결국 문서를 들여다 보아야 한다는 얘기다). 🔍

[그림 6.13] J12 확장 핀 - pin 7 (GPIO) [출처 - 참고문헌 5]


[그림 6.14] J12 확장 핀 - pin 7 (GPIO) [출처 - 참고문헌 27]
(좌측 엑셀 71 행 참조)

한편 GPIO PAC.06은 gpioinfo 명령으로 확인한 결과, line 144(port offset)에 해당하는 것을 알 수 있다.

line 144:     "PAC.06"       unused   input  active-high

<GPIO Pin number 추론(?) 과정>
J12 40핀 확장 헤더 7번 pin -> GPIO09(Orin Module pin name) -> GPIO PAC.06 (SoC GPIO port) -> 144 (port offset)

따라서, 아래와 같이 gpioset 명령으로 gpio 설정 변경을 시도해 보면 된다.

chyi@jetsonkit:~$ gpioset --mode=wait $(gpiofind "PAC.06")=1
chyi@jetsonkit:~$ gpioget 0 144
0

chyi@jetsonkit:~$ gpioset --mode=wait $(gpiofind "PAC.06")=0
gpioget: invalid GPIO offset: 144=0
chyi@jetsonkit:~$ gpioget 0 144
0

하지만 gpioset 설정이 여전히 먹히질 않는다. 도대체 뭐가 문제일까 ? gpio mode가 output이 아닌 input으로 표현되는 것도 이상하고 도무지 이해가 안된다. 😈 

(내용이 길어지는 관계로) 정답은 다음 장에서 공개하기로 하자. 😋



7. GPIO and DTB Overlay
문제의 원인을 찾던 중, 아래 동영상을 하나 발견했다. 세상에는 참으로 훌륭한 분들이 많이 있는 것 같다. 아래 동영상 파일과 JetsonHacks site의 운영자인 Jim에게 이 자리를 빌어 감사의 마음을 전한다. 👍
I salute you for your efforts.


이번 장에서 소개하는 내용은 위의 동영상과 아래 site의 내용을 기초로 하였다. 

7.1 GPIO patch code 실행
먼저, 위의 github에서 code를 내려 받는다.

<Ubuntu 22.04 LTS desktop>
  -> 물론 아래 작업을 target board에서 직접 수행해도 된다.
$ git clone https://github.com/jetsonhacks/jetson-orin-gpio-patch
$ cd jetson-orin-gpio-patch
dtc -O dtb -o pin7_as_gpio.dtbo pin7_as_gpio.dts
  -> pin7_as_gpio.dtbo 파일을 target board /boot 디렉토리로 복사하자.

<Target board>
chyi@jetsonkit:~$ sudo cp pin7_as_gpio.dtbo /boot
chyi@jetsonkit:~$ sudo /opt/nvidia/jetson-io/jetson-io.py
  -> Jetson Dev Kit에서 제공하는 위 명령을 사용하여 device tree overlay 설정을 추가하도록 한다.

[그림 7.1] jetson-io.py 명령 실행 (1)

이어서, 새로 추가된 Pin 7 gpio bidirectional 메뉴를 선택한다.

[그림 7.2] jetson-io.py 명령 실행 (2)

이후, /boot/extlinux/extlinux.conf 파일이 자동 수정되었다는 문구가 출력된다.

[그림 7.3] jetson-io.py 명령 실행 (3)

(나중에) 위에서 자동으로 수정된 extlinux.conf 파일의 내용을 확인해 보니, 후반부에 아래의 내용이 추가되어 있음을 알 수 있다.

[그림 7.4] 자동으로 수정된 /boot/extlinux/extlinux.conf 파일 - 후반부 내용만 발췌

참고로, extlinux.conf 파일의 전체 내용은 다음과 같다.
_____________________________________________________________
LABEL primary
     MENU LABEL primary kernel
     LINUX /boot/Image
     INITRD /boot/initrd
     APPEND ${cbootargs} root=PARTUUID=757cb550-ca70-4888-993d-ff7fddaa1de6 rw   
rootwait rootfstype=ext4 mminit_loglevel=4 console=ttyTCU0,115200 firmware_classs
.path=/etc/firmware fbcon=map:0 nospectre_bhb video=efifb:off console=tty0

LABEL JetsonIO
       MENU LABEL Custom Header Config: <HDR40 Pin 7 gpio bidirectional>
       LINUX /boot/Image
       FDT /boot/dtb/kernel_tegra234-p3768-0000+p3767-0005-nv-super.dtb    //dtb 적용 대상 지정
       INITRD /boot/initrd
       APPEND ${cbootargs} root=PARTUUID=757cb550-ca70-4888-993d-ff7fddaa1de6 rr
w rootwait rootfstype=ext4 mminit_loglevel=4 console=ttyTCU0,115200 firmware_claa
ss.path=/etc/firmware fbcon=map:0 nospectre_bhb video=efifb:off console=tty0
       
OVERLAYS /boot/pin7_as_gpio.dtbo   //새로 추가한 dtb overlay 파일 지정
_____________________________________________________________
📌 위의 내용대로라면, kernel_tegra234-p3768-0000+p3767-0005-nv-super.dtb 파일이 적용되고, 이어 pin7_as_gpio.dtbo에 정의한 기능이 그 위에 override 된다.
📌 주의: kernel_tegra234-p3768-0000+p3767-0005-nv-super.dtb 파일은 /boot가 아니라 /boot/dtb 디렉토리 아래에 있다.


이후, target board를 재부팅하면, 아래와 같은 booting option이 출력되고, 1을 선택하면, 새로 추가한 DTB overlay 설정이 적용된다.

LT4 boot options
0: primary kernel
1: Custom Header Config: <HDR40 Pin 7 gpio bidrectional>
Press 0-1 to boot selection within 3.0 seconds.
Press any other key to boot default (Option: 1)

[그림 7.5] booting option 선택 화면

그런데, Taget board 재부팅 후, GPIO line 144(GPIO PAC.06) 상태를 확인한 결과는 기존과 다르지 않다. 즉, 아무런 변경 없이, 기존과 동일하게 Input mode로 표시된다.

$ gpioinfo gpiochip0

[그림 7.6] GPIO 테스트 code 실행 전 확인 내용

이 상태에서 examples/simple_out.py code를 실행한 후, GPIO 144 line의 결과를 확인해 보면, 이전과는 확연히 달라진 결과를 마주하게 된다. 😋 

<Prerequisites>
$ sudo apt update
$ sudo apt install python3 python3-pip -y
$ sudo pip install --upgrade Jetson.GPIO
  -> 아래 python code를 실행하기 전에 Jetson.GPIO package를 미리 설치해 주어야 한다.
$ sudo usermod -a -G gpio $USER
  -> gpio group에 자신의 계정을 추가한다(이유: 이후 실행하는 python code를 root로 실행하지 않게 하기 위함).
  -> 이후 logout -> login을 하거나, reboot을 해 주어야 위의 내용이 반영된다.

$ cd examples
$ python3 ./simple_out.py
  -> 7번 pin을 output mode로 설정하고, gpio value를 1 -> 0 -> 1 -> 0으로 반복 설정하는 간단한 코드이다.

[그림 7.7] simple_out.py 코드 실행 결과

gpioinfo gpiochip0
  -> gpio mode가 Output으로 바뀌어 있으며, 이제는 Jetson-gpio(used)로 표시된다.

[그림 7.8] GPIO 테스트 code 실행 후 확인 내용 - 정상 동작

7.2 GPIO patch code 분석
그럼, 도대체 어떻게 해서, 위와 같이 정상 동작하게 된 것일까 ? 해답은 아래에 보이는 dts overlay file을 새로 추가했기 때문이다.

[그림 7.9] 새로 추가된 dts overlay file - pin7_as_gpio_dts 파일

참고로, 아래 내용은 target board 상에서 fdtdump 명령으로 pin7_as_gpio.dtbo binary 내용을 확인해 본 것이다.

$ fdtdump /boot/pin7_as_gpio.dtbo

[그림 7.10] fdtdump /boot/pin7_as_gpio.dtbo 결과
📌 fdtdump 명령을 기억해 두면 나중에 유용하게 사용할 수가 있다.

문법이 다소 복잡해 보이는데, 위의 overlay file이 어떤 원리로 만들어지는 지를 따져보기 위해, 이것 저것 파일을 찾다 보니, 아래 file이 눈에 들어 온다. 이 파일은 40 pin header의 설정을 overlay 형식으로 정의한 것으로 보이는데, 이 내용 중에는 7번 pin에 대한 내용도 담겨 있다.

source/hardware/nvidia/t23x/nv-public/overlay/tegra234-p3767-0000-common-hdr40.dtsi

[그림 7.11] tegra234-p3767-0000-common-hdr40.dtsi 파일 - overlay 파일

내용을 좀 더 파악해 보니, 위의 dts 파일은 Jetson Orin Nano Dev Kit에서 현재 사용되지 않는 것 같다. 따라서 위의 내용을 참조하여 새로운 overlay 파일을 하나 만들어 추가하면 되는데, 그 내용이 앞서 소개한 pin7_as_gpio.dts 파일로 이해하면 된다. 😋

        hdr40-pin7 {   //현재는 audio codec용으로 설정되어 있음.
                nvidia,pins = "soc_gpio59_pac6";
                nvidia,function = "aud";               //audio
                nvidia,pin-label = "aud_mclk";   //audio codec master clock
                nvidia,tristate = <TEGRA_PIN_DISABLE>;
                nvidia,enable-input = <TEGRA_PIN_DISABLE>;
        };
      
=>
    
    jetson_io_pinmux: exp-header-pinmux {
        hdr40-pin7 {
                nvidia,pins = "soc_gpio59_pac6";
                nvidia,tristate = <0x0>;
                nvidia,enable-input = <0x1>;
                nvidia,pull = <0x0>;
        };


(device tree overlay 내용을 살펴 보았으니) 다음으로, simple_out.py 파일의 내용을 분석해 보기로 하자.

simple_out.py code가 제대로 동작하기 위해서는, 사전에 아래 jetson-gpio package를 설치해야만 한다(앞서 이미 설치하였음).


[그림 7.12] https://github.com/NVIDIA/jetson-gpio/tree/master/samples

<simple_out.py 코드에서 수행하는 내용>
1) gpio pin 지정(7번)  ............................................................ (A
2) output mode로 지정
3) 초기 값 (= HIGH) 지정
4) while loop를 도면서 1초 간격으로 curr_value 값 출력(curr_value는 매 loop 마다 toggle 됨).

[그림 7.13] simple_out.py 파일

그렇다면, 앞서 표시해 두었던 (A) 부분은 내부적으로 어떻게 처리되는 것일까 ? 답은 아주 간단하다. 우리는 이미 6장에서 GPIO Pin number 추론(?) 과정을 살펴 본 바가 있다. 즉, 다음과 같이 말이다.

J12 40핀 확장 헤더 7번 pin -> GPIO90(Orin Module pin name) -> GPIO PAC.06(SoC GPIO port) -> 144 (port offset)

jetson-gpio package 내에 포함된 python code(gpio_pin_data.py)를 보면, 위의 개념을 반영하기 위해 아래와 같은 tuple 정보를 담은 list가 정의되어 있음을 알 수가 있다. 이쯤되면, 나머지 과정은 따로 설명하지 않아도 무슨 말인지 금방 이해가 가리라고 본다. 😋

(144, 'PAC.06', "tegra234-gpio", 7, 4, 'GPIO09', 'GP167', None, None)

[그림 7.14] jetson-gpio/lib/python/Jetson/GPIO/gpio_pin_data.py 파일

7.3 Kernel patch 적용
이번 장에서 끝으로 소개할 내용은 pinmux code에 대한 kernel patch 부분이 되겠다. Patch할 파일은 아래 2개의 파일이다.

drivers/pinctrl/tegra/pinctrl-tegra.c
drivers/pinctrl/tegra/pinctrl-tegra.h
📌 tegra soc의 pinmux 설정 관련 드라이버 코드다.

<Patch를 하는 이유>
이 패치는 Tegra pinctrl 드라이버의 GPIO 핀 다중화 처리 능력을 다음과 같이 향상시켜준다.

1) 원래 핀 상태 유지하기: 이전에는 GPIO를 요청하면 sfsel 비트가 지워졌고(GPIO 모드 강제), 해제되면 항상 설정되었다(특수 기능 모드 강제). 이제 드라이버는 원래 상태를 기억하고 GPIO가 해제되면 복원한다.
2) 구성 추적 추가: pingroup_configs 배열은 그룹별 상태를 저장하는 메커니즘을 도입하여 향후 향상을 위해 드라이버를 더욱 유연하게 만든다.
3) 불필요한 변경 방지: sfsel 비트의 조건부 복원은 불필요한 레지스터 쓰기를 방지하여 효율성을 높이고 부작용을 줄인다.
_______________________________________________________________

<Patch 방법>
$ cp pinctrl-tegra-sfsel.patch <your_path>/Linux_for_Tegra/source/kernel/kernel-jammy-src
$ cd Linux_for_Tegra/source/kernel/kernel-jammy-src
$ patch -p1 < ./pinctrl-tegra-sfsel.patch
patching file drivers/pinctrl/tegra/pinctrl-tegra.c
patching file drivers/pinctrl/tegra/pinctrl-tegra.h

<Kernel build 하기>
export ARCH=arm64
export CROSS_COMPILE=/mnt/hdd/workspace/nvidia/jetson/toolchain/aarch64--glibc--stable-2022.08-1/bin/aarch64-buildroot-linux-gnu-
$ export INSTALL_MOD_PATH=/mnt/hdd/workspace/nvidia/jetson/06222025/Manual/Linux_for_Tegra/rootfs
export KERNEL_HEADERS=/mnt/hdd/workspace/nvidia/jetson/06222025/Manual/Linux_for_Tegra/source/kernel/kernel-jammy-src
  -> kernel build에 필요한 몇가지 환경 설정을 한다(자신의 환경에 맞게 적절히 조절한다).

cd Linux_for_Tegra/source/
make -C kernel
sudo -E make install -C kernel
cp kernel/kernel-jammy-src/arch/arm64/boot/Image ../kernel/Image

(반복되는 부분이므로) 나머지 과정(Image -> /boot 디렉토리 복사)은 이전 posting을 참고하도록 하자.

이상으로 BSP work 중에서 가장 기초적인 내용이라고 할 수 있는 GPIO에 관하여 2개의 장(6, 7장)에 걸쳐서 나름 상세히 파악해 보았다. GPIO가 아무리 기초적인 내용이라고 할지라도, 결코 쉽게 무시하고 넘어갈 수 있는 부분이 아니라는 점을 강조하고 싶다. 💢


8. I2C and SPI Device Tree and Device Drivers
이번 장에서는 i2c 및 SPI 장치를 각각 하나씩 장착하고, 이를 인식하는 과정을 소개해 보고자 한다. 

내용이 길어지는 관계로, 나머지 내용은 다음 posting을 통해 확인하기로 하자. Bye~ 😎


To be continued...

May the source be with you~

References
[1] jetson-orin-datasheet-nano-developer-kit-3475392-r2.pdf
  -> 제품 brochure
[2] https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/jetson-orin/nano-super-developer-kit/
  -> Jetson Orin Nano Super Developer Kit 공식 site
[3] https://docs.nvidia.com/jetson/archives/r36.4.3/DeveloperGuide/
  -> NVIDIA Jetson Linux developer guide 문서 *****
[4] https://www.jetson-ai-lab.com/initial_setup_jon.html
  -> Initial setup guide for etson Orin Nano Developer Kit *****
[5] Jetson Orin Nano Developer Kit Carrier Board, SP-11324-001_v1.3 pdf
[6] Jetson Orin NX Series and Jetson Orin Nano Series Product Design Guide
[7] Jetson Orin NX Series and Jetson Orin Nano Series Pin and Function Names Guide
[8] NVIDIA Orin Series System-on-Chip Technical Reference Manual
[9] NVIDIA Jetson Orin Nano Series Modules Data Sheet - Ampere GPU + Arm Cortex-A78AE CPU + LPDDR5
  -> Jetson Orin Nano Developer Kit 관련 h/w 문서
[10] https://docs.nvidia.com/jetson/archives/r35.4.1/DeveloperGuide/text/AR/BootArchitecture/JetsonOrinSeriesBootFlow.html
  -> Jetson Orin Nano Boot Flow
[11] https://www.jetson-ai-lab.com/index.html
[12] https://www.jetson-ai-lab.com/initial_setup_jon.html
[13] https://www.jetson-ai-lab.com/tutorial-intro.html
  -> ai-lab & Initial setup guide

[14] https://docs.nvidia.com/deeplearning/tensorrt/latest/getting-started/quick-start-guide.html
  -> TensorRT guide

[15] CUDA C++ Programming Guide, Release 12.9, NVIDIA Corportation
[16] https://developer.ridgerun.com/wiki/index.php/Yocto_Support_for_NVIDIA_Jetson_Platforms_-_Setting_up_Yocto
[17] https://github.com/OE4T/tegra-demo-distro#tegra-demo-distro

[18] https://jetsonhacks.com/
[19] https://github.com/jetsonhacks
[20] https://jetsonhacks.com/2025/03/13/build-jetson-orin-kernel-and-modules/
[21] https://jetsonhacks.com/2025/04/07/device-tree-overlays-on-jetson-scary-but-fun/
   -> Cool site~

[22] https://developer.ridgerun.com/wiki/index.php/NVIDIA_Jetson_-_Device_Tree_Overlay
[23] https://github.com/TechNexion-Vision/TEV-JetsonOrin-Nano_device-tree
[24] https://echomav.github.io/docs/latest/echopilot_ai/
[25] https://developer.nvidia.com/embedded/develop/software

[26] https://nvidia-jetson.piveral.com/jetson-orin-nano/configuring-gpio-output-on-nvidia-jetson-orin-nano/
    -> gpio configurations

[27] Jetson_Orin_NX_Orin_Nano_Pin_Descriptiosn.xlsx
    ->Jetson Orin Nano pin description 엑셀 문서

[28] https://bootlin.com/blog/enabling-new-hardware-on-raspberry-pi-with-device-tree-overlays/
[29] https://wikidocs.net/3205
   -> device tree overlay

[30] https://jetsonhacks.com/nvidia-jetson-orin-nano-gpio-header-pinout/

[31] And, Google & Gemini~


Slowboot

2025년 6월 23일 월요일

NVIDIA Jetson Orin Nano Developer Kit와 AI Programming(#2)

이번 시간에는 지난 시간에 이어 NVIDIA Jetson Orin Nano Developer Kit를 해부(2번째 시간)해 보고, 느낀 점을 독자 여러분과 공유해 보고자 한다. 😎

[출처 - https://namu.wiki/w/NVIDIA%20Tegra]
The 2nd time 🚀🚀

목차
4. SDK Manager 없이 OS 설치하기
5. Deep Dive into Jetson Linux Kernel
6. Device Tree and Device Drivers
7. Jetson AI - LLM 돌려 보기
References


BSP(Board Support Package) 관련 내용은 chip 제조사마다 조금씩 차이가 있게 마련이다. NVIDIA Jetson Kit의 경우도 예외가 아닌데, 그 난이도가 어느 정도나 되는지 이번 posting을 통해 확인해 보도록 하자. 😋


4. SDK Manager 없이 OS 설치하기
BSP 관련 작업 시 제일 먼저 맞닥뜨리는 문제는, 아무래도 "bootloader, kernel, rootfs 등을 어떤 식으로 boot media(NOR/NAND flash, eMMC, SDCard, NVMe, USB storage 등)에 적절히 설치(flashing)할 것인가"에 관한 것이 아닐까 싶다.

우리는 이미 3장에서 SDK Manager를 통해 OS image를 설치하는 과정을 상세히 살펴 보았다. SDK Manager는 매우 편리한 방법이지만, BSP code를 수정할 경우 이를 반영할 방법이 없어 보인다. 언뜻 생각하기에는 SDK Manager를 동작시키는 과정에서 생성된 디렉토리에 새로 수정한 kernel, rootfs 등을 적절히 복사한 상태에서 다시 설치를 진행하면, 수정 사항이 반영될 것 같기도 하지만 말이다(단, 아직 이렇게 해보지는 않았다 😋).

JetPack_6.2_Linux_JETSON_ORIN_NANO_TARGETS/Linux_for_Tegra/
        kernel/Image
        kernel/dtb/*
        rootfs/*

하지만 이 방법이 안먹힐 수도 있고, shell script를 이용한 방법이 이미 제공되고 있으니, 지금부터는 이 방법을 소개해 보고자 한다. 여기서 소개하는 내용은 아래 site의 내용을 기초로 하였다.


Shell script를 이용한 설치 방법은 대략 아래와 같은 방식으로 동작하는 것으로 보면 될 듯하다.
[그림 4.1] Recovery mode에서 USB-C를 이용한 flash writing 방법
📌 그림에는 표현되지 않았지만, 실제로 설치 막판에는 initrd를 구동한 상태에서 scp로 파일 복사 후, 각종 debian package를 설치하는 부분도 있는 것 같다. 다시말해 bootloader를 통해 한방에 image를 설치하지는 않는다는 뜻이다(왜냐, OS image가 꽤나 덩치가 크기 때문이다).

<Ubuntu 22.04 LTS Desktop PC>
[1] 설치 image 준비 단계
  -> 먼저, 아래 site로 부터 몇가지 BSP file을 download하도록 한다.


tar xvjf Jetson_Linux_R36.4.3_aarch64.tbz2
  -> 압축을 풀면, Linux_for_Tegra/ 디렉토리가 생성된다. 이 아래에 OS image를 구성하는 모든 내용이 들어가게 된다.
  • bootloader: Bootloader plus flashing tools, such as TegraFlash, CFG, and BCT
  • kernel: A kernel image /Image, DTB files, and kernel modules
  • rootfs: The root file system that you downloaded
  • nv_tegra: User space binaries and sample applications
  • 📌 때로는 영문 원문이 의미를 제대로 전달하는 경우가 있다.

$ tar xvjf ./public_sources.tbz2
   -> Linux_for_Tegra/source 아래에 압축을 푼다.
$ cd Linux_for_Tegra/source/
$ tar xvjf ./kernel_src.tbz2
   -> kernel/kernel-jammy-src 아래에 kernel source를 푼다.
$ tar xvjf ./kernel_oot_modules_src.tbz2
   -> nvidia에서 제공하는 out-of-tree kernel module code를 푼다.
$ tar xvjf ./nvidia_kernel_display_driver_source.tbz2
   -> nvdisplat code를 푼다.

tar xpf Tegra_Linux_Sample-Root-Filesystem_R36.4.3_aarch64.tbz2 -C Linux_for_Tegra/rootfs/
  -> prebuilt root file system을 rootfs 디렉토리로 복사한다.

$ cd Linux_for_Tegra/source
  -> l4t는 linux for tegra를 의미한다.
$ ls -la
  -> 아래와 같은 파일이 존재해야 한다.
합계 221620
drwxr-xr-x 10 chyi chyi      4096  6월 22 17:53 .
drwxr-xr-x 10 chyi chyi      4096  1월  8 10:41 ..
-rw-r--r--  1 chyi chyi      7842  1월  8 10:11 Makefile
-rw-r--r--  1 chyi chyi      9355  1월  8 10:41 argus_cam_libavencoder_src.tbz2
-rw-r--r--  1 chyi chyi       118  1월  8 10:41 argus_cam_libavencoder_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi   6575350  1월  8 10:41 atf_src.tbz2
-rw-r--r--  1 chyi chyi        99  1월  8 10:41 atf_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi    137992  1월  8 10:41 dtc-1.4.5.tbz2
-rw-r--r--  1 chyi chyi       101  1월  8 10:41 dtc-1.4.5.tbz2.sha1sum
-rwxr-xr-x  1 chyi chyi      6652  1월  8 10:11 generic_rt_build.sh
-rw-r--r--  1 chyi chyi    648021  1월  8 10:41 gst-nvarguscamera_src.tbz2
-rw-r--r--  1 chyi chyi       113  1월  8 10:41 gst-nvarguscamera_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi    630289  1월  8 10:41 gst-nvcompositor_src.tbz2
-rw-r--r--  1 chyi chyi       112  1월  8 10:41 gst-nvcompositor_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi     49554  1월  8 10:41 gst-nvipcpipeline_src.tbz2
-rw-r--r--  1 chyi chyi       113  1월  8 10:41 gst-nvipcpipeline_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi    620844  1월  8 10:41 gst-nvtee_src.tbz2
-rw-r--r--  1 chyi chyi       105  1월  8 10:41 gst-nvtee_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi     36851  1월  8 10:41 gst-nvunixfd_src.tbz2
-rw-r--r--  1 chyi chyi       108  1월  8 10:41 gst-nvunixfd_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi    627068  1월  8 10:41 gst-nvv4l2camera_src.tbz2
-rw-r--r--  1 chyi chyi       112  1월  8 10:41 gst-nvv4l2camera_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi    648706  1월  8 10:41 gst-nvvidconv_src.tbz2
-rw-r--r--  1 chyi chyi       109  1월  8 10:41 gst-nvvidconv_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi    175846  1월  8 10:41 gst-nvvideo4linux2_src.tbz2
-rw-r--r--  1 chyi chyi       114  1월  8 10:41 gst-nvvideo4linux2_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi     49420  1월  8 10:41 gstegl_src.tbz2
-rw-r--r--  1 chyi chyi       102  1월  8 10:41 gstegl_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi   1405331  1월  8 10:41 gstjpeg_src.tbz2
-rw-r--r--  1 chyi chyi       103  1월  8 10:41 gstjpeg_src.tbz2.sha1sum
drwxrwxr-x  3 chyi chyi      4096  6월 22 17:53 hardware
drwxr-xr-x  4 chyi chyi      4096  1월  8 10:11 hwpm
drwxrwxr-x  3 chyi chyi      4096  6월 22 17:52 kernel
drwxr-xr-x  5 chyi chyi      4096  1월  8 10:11 kernel-devicetree
-rw-r--r--  1 chyi chyi   8450197  1월  8 10:41 kernel_oot_modules_src.tbz2
-rw-r--r--  1 chyi chyi       114  1월  8 10:41 kernel_oot_modules_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi 156611109  1월  8 10:41 kernel_src.tbz2
-rw-r--r--  1 chyi chyi       102  1월  8 10:41 kernel_src.tbz2.sha1sum
-rwxr-xr-x  1 chyi chyi      1916  1월  8 10:11 kernel_src_build_env.sh
-rw-r--r--  1 chyi chyi      4333  1월  8 10:41 libgstnvcustomhelper_src.tbz2
-rw-r--r--  1 chyi chyi       116  1월  8 10:41 libgstnvcustomhelper_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi     15394  1월  8 10:41 libgstnvdrmvideosink_src.tbz2
-rw-r--r--  1 chyi chyi       116  1월  8 10:41 libgstnvdrmvideosink_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi     26745  1월  8 10:41 libgstnvvideosinks_src.tbz2
-rw-r--r--  1 chyi chyi       114  1월  8 10:41 libgstnvvideosinks_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi     24471  1월  8 10:41 libv4l2_nvargus_src.tbz2
-rw-r--r--  1 chyi chyi       111  1월  8 10:41 libv4l2_nvargus_src.tbz2.sha1sum
-rwxr-xr-x  1 chyi chyi      2951  1월  8 10:41 nv_public_src_build.sh
-rwxr-xr-x  1 chyi chyi      4704  1월  8 10:41 nv_public_src_build_tos.sh
-rwxrwxr-x  1 chyi chyi      2545  1월  8 10:42 nv_src_build.sh
-rwxr-xr-x  1 chyi chyi      7836  1월  8 10:11 nvbuild.sh
-rwxr-xr-x  1 chyi chyi      1788  1월  8 10:11 nvcommon_build.sh
drwxr-xr-x  5 chyi chyi      4096  1월  8 10:41 nvdisplay
drwxr-xr-x  6 chyi chyi      4096  1월  8 10:11 nvethernetrm
drwxrwxr-x  5 chyi chyi      4096  6월 22 17:53 nvgpu
-rw-r--r--  1 chyi chyi     59543  1월  8 10:41 nvgstapps_src.tbz2
-rw-r--r--  1 chyi chyi       105  1월  8 10:41 nvgstapps_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi   8042293  1월  8 10:41 nvidia-jetson-optee-source.tbz2
-rw-r--r--  1 chyi chyi       118  1월  8 10:41 nvidia-jetson-optee-source.tbz2.sha1sum
drwxr-xr-x  9 chyi chyi      4096  1월  8 10:11 nvidia-oot
-rw-r--r--  1 chyi chyi    110578  1월  8 10:41 nvidia-xconfig_src.tbz2
-rw-r--r--  1 chyi chyi       110  1월  8 10:41 nvidia-xconfig_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi   2670187  1월  8 10:41 nvidia_kernel_display_driver_source.tbz2
-rw-r--r--  1 chyi chyi       127  1월  8 10:41 nvidia_kernel_display_driver_source.tbz2.sha1sum
-rw-r--r--  1 chyi chyi   2670073  1월  8 10:41 nvidia_kernel_display_driver_source_without_root_dir.tbz2
-rw-r--r--  1 chyi chyi       144  1월  8 10:41 nvidia_kernel_display_driver_source_without_root_dir.tbz2.sha1sum
-rw-r--r--  1 chyi chyi      7199  1월  8 10:41 nvsample_cudaprocess_src.tbz2
-rw-r--r--  1 chyi chyi       116  1월  8 10:41 nvsample_cudaprocess_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi     70182  1월  8 10:41 nvsci_headers.tbz2
-rw-r--r--  1 chyi chyi       105  1월  8 10:41 nvsci_headers.tbz2.sha1sum
-rw-r--r--  1 chyi chyi     35176  1월  8 10:41 nvsci_samples_src.tbz2
-rw-r--r--  1 chyi chyi       109  1월  8 10:41 nvsci_samples_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi      6473  1월  8 10:41 opencv_gst_samples_src.tbz2
-rw-r--r--  1 chyi chyi       114  1월  8 10:41 opencv_gst_samples_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi      6647  1월  8 10:41 openwfd_headers.tbz2
-rw-r--r--  1 chyi chyi       107  1월  8 10:41 openwfd_headers.tbz2.sha1sum
-rw-r--r--  1 chyi chyi      4777  1월  8 10:41 public_sources_sha.txt
-rwxrwxr-x  1 chyi chyi     11019  1월  8 10:42 source_sync.sh
-rw-r--r--  1 chyi chyi   2644275  1월  8 10:41 spe-freertos-bsp.tbz2
-rw-r--r--  1 chyi chyi       108  1월  8 10:41 spe-freertos-bsp.tbz2.sha1sum
-rw-r--r--  1 chyi chyi    189692  1월  8 10:41 v4l2_libs_src.tbz2
-rw-r--r--  1 chyi chyi       105  1월  8 10:41 v4l2_libs_src.tbz2.sha1sum
-rw-r--r--  1 chyi chyi  33373436  1월  8 10:41 webrtc_argus_camera_app_src.tbz2
-rw-r--r--  1 chyi chyi       119  1월  8 10:41 webrtc_argus_camera_app_src.tbz2.sha1sum

-----------------------------------------------------------------------------

[2] Kernel code build 하기

$ export ARCH=arm64
$ export CROSS_COMPILE=/mnt/hdd/workspace/nvidia/jetson/toolchain/aarch64--glibc--stable-2022.08-1/bin/aarch64-buildroot-linux-gnu-
$ export INSTALL_MOD_PATH=/mnt/hdd/workspace/nvidia/jetson/06222025/Manual/Linux_for_Tegra/rootfs
$ export KERNEL_HEADERS=/mnt/hdd/workspace/nvidia/jetson/06222025/Manual/Linux_for_Tegra/source/kernel/kernel-jammy-src
  -> kernel build에 필요한 몇가지 환경 설정을 한다(자신의 환경에 맞게 적절히 조절한다).

$ cd Linux_for_Tegra/source/
$ make -C kernel
$ sudo -E make install -C kernel
$ cp kernel/kernel-jammy-src/arch/arm64/boot/Image ../kernel/Image
  -> kernel과 (in-tree) kernel module을 build한 후, kernel module은 rootfs에 설치하도록 한다.
  -> Image도 kernel/Image로 복사한다.

$ make modules
$ sudo -E make modules_install
  -> out-of-tree kernel module을 build 후, rootfs 아래에 설치한다.

$ cd Linux_for_Tegra
$ sudo ./tools/l4t_update_initrd.sh
Set LDK_DIR to /mnt/hdd/workspace/nvidia/jetson/06222025/Manual/Linux_for_Tegra
Using rootfs directory: /mnt/hdd/workspace/nvidia/jetson/06222025/Manual/Linux_for_Tegra/rootfs
Updating the initrd: /mnt/hdd/workspace/nvidia/jetson/06222025/Manual/Linux_for_Tegra/bootloader/l4t_initrd.img
Copy /mnt/hdd/workspace/nvidia/jetson/06222025/Manual/Linux_for_Tegra/bootloader/l4t_initrd.img to /mnt/hdd/workspace/nvidia/jetson/06222025/Manual/Linux_for_Tegra/rootfs/boot/initrd
Preparing virtual env
chroot: failed to run command 'nv-update-initrd': No such file or directory
ERROR: nv-update-initrd failed!
Cleaning up virtual env
---------------------> 명령에 실패했으나, (대세에 지장이 없는 듯 하니) 일단 얘는 pass하자.

$ cd source/
$ make dtbs
$ cp kernel-devicetree/generic-dts/dtbs/* ../kernel/dtb/
   -> device tree를 compile하고, binary를 적당한 위치로 복사한다.

[3] Ubuntu package 설치하기
$ cd ..
sudo ./tools/l4t_flash_prerequisites.sh
  -> 이후 작업에 필요한 몇가지 ubuntu package를 설치한다.

[4] 설치 image 만들기
sudo ./apply_binaries.sh 
  -> 다양한 deb package 등을 rootfs에 설치한다.
Using rootfs directory of: /mnt/hdd/workspace/nvidia/jetson/Linux_for_Tegra/rootfs
Installing extlinux.conf into /boot/extlinux in target rootfs
/mnt/hdd/workspace/nvidia/jetson/Linux_for_Tegra/nv_tegra/nv-apply-debs.sh
Root file system directory is /mnt/hdd/workspace/nvidia/jetson/Linux_for_Tegra/rootfs
Copying public debian packages to rootfs
Skipping installation of nvidia-igx-oem-config_36.4.3-20250107174145_arm64.deb ....
Skipping installation of nvidia-igx-systemd-reboot-hooks_36.4.3-20250107174145_arm64.deb ....
Skipping installation of nvidia-l4t-dgpu-apt-source_36.4.3-20250107174145_arm64.deb ....
Skipping installation of nvidia-l4t-dgpu-config_36.4.3-20250107174145_arm64.deb ....
Skipping installation of nvidia-l4t-dgpu-tools_36.4.3-20250107174145_arm64.deb ....
Skipping installation of nvidia-l4t-dgpu-x11_36.4.3-20250107174145_arm64.deb ....
Skipping installation of nvidia-l4t-factory-service_36.4.3-20250107174145_arm64.deb ....
Skipping installation of nvidia-igx-bootloader_36.4.3-20250107174145_arm64.deb ....
Skipping installation of nvidia-l4t-jetson-orin-nano-qspi-updater_36.4.3-20250107174145_arm64.deb ....
Start L4T BSP package installation
QEMU binary is not available, looking for QEMU from host system
...
...
Add config /etc/modprobe.d/denylist-ramoops.conf
Add config /etc/modprobe.d/denylist-tegra-safety.conf
Add config /etc/modprobe.d/denylist-tpm-ftpm-tee.conf
Add config /etc/modprobe.d/iwlwifi.conf
Add config /etc/modprobe.d/nvgpu.conf
Add config /etc/modprobe.d/nvidia-display.conf
Add config /etc/modprobe.d/tegra-udrm.conf
Add config /lib/modprobe.d/aliases.conf
Add config /lib/modprobe.d/fbdev-blacklist.conf
Add config /lib/modprobe.d/systemd.conf
Cleaning up the temporary directory for updating the initrd..
/mnt/hdd/workspace/nvidia/jetson/Linux_for_Tegra
Removing QEMU binary from rootfs
Removing stashed Debian packages from rootfs
L4T BSP package installation completed!
Disabling NetworkManager-wait-online.service
Disable the ondemand service by changing the runlevels to 'K'
Success!

여기까지 준비가 되었다면, 이후 아래와 같은 절차를 따라 flash writing을 진행하도록 하자.

[5] Target board를 recovery mode로 전환시킨다.
  -> 3장에서 소개한 내용(그림 3.5, 3.6 참조)을 참고하자.

[6] Target board와 Host Linux PC간에 USB-C cable을 연결 시킨다.

[7] 아래 명령을 실행하여 NVMe SSD에 image 설치를 한다.
  -> 여기에서도 편의상 microSD를 제거한 상태에서 NVMe에 image를 설치하도록 하자.

$ sudo ./tools/kernel_flash/l4t_initrd_flash.sh --external-device nvme0n1p1 \
  -c tools/kernel_flash/flash_l4t_t234_nvme.xml -p "-c bootloader/generic/cfg/flash_t234_qspi.xml" \
  --showlogs --network usb0 jetson-orin-nano-devkit-super internal

  -> xml 파일을 보면 flashing을 위한 partition layout이 기술되어 있다.
  -> 정말, 한참 동안 설치가 진행된다. 😂


...
...
[그림 4.2] Recovery mode에서 NVMe SSD로 OS image 설치하기(1)

[그림 4.3] Recovery mode에서 NVMe SSD로 OS image 설치하기(2) - minicom에서 확인
📌 Recovery mode에서는 FAN이 돌아가지 않는 관계로, board가 매우 hot하니 주의를 요한다. 🌋

아래 파일은 l4t_initrd_flash.sh 설정시 지정했던 partition layout 파일들인데, 꽤나 복잡하고 많은 파티션들로 이루어져 있음을 알 수 있다. 왜 이리 복잡한 것일까 ? 😓

[그림 4.4] bootloader 파티션 layout 파일(QSPI flash용) - flash_t234_qspi.xml

[그림 4.5] external device용 파티션 layout 파일(efl, kernel, rootfs 등 배치) - flash_l4t_t234_nvme.xml

참고로, 설치 과정은 아래 파일에 로그로 남겨지게 된다.

initrdlog/flash_1-9_0_20250619-134647.log

[8] 설치 완료 후, 자동 reboot(target board)한다.
  -> 이후, 모니터 화면에서 Ubuntu 설정을 진행한 후, 재부팅하자.
  -> 재부팅 시에는 당연히 recovery mode를 해제해 주어야 한다.

[그림 4.6] Jetson Kit 자동 reboot 모습
📌 지금까지 설명한 방법은 Jetson Linux Image만을 설치하는 것이므로, Jetson Runtime Components는 (Ubuntu login 후) 별도로 설치해 주어야 한다.
_____________________________________________________

Jetson Linux BSP의 경우, (Yocto project와 같은) 일반적인 Build system을 이용한 방법이 아니다 보니, flash writing 방법(shell script 실행)도 다소 복잡한 느낌이다. 자세한 사항은 아래 내용을 참조하기 바란다.
예를 들어, kernel 파티션만을 교체하고자 한다면, 아래와 같이 하면 된다.

<Recovery mode 전환 상태에서>
$ sudo ./tools/kernel_flash/l4t_initrd_flash.sh -k A_kernel jetson-orin-nano-devkit-super nvme0n1p1
📌 이 방법은 최종적으로 initrd로 부팅한 상태(kernel 상태)에서 flash writing을 하는 방법이다. 파티션명은 앞서 언급했던 2개의 xml 파일을 참조해야 한다.

or

$ sudo ./flash.sh -k A_kernel jetson-orin-nano-devkit-super nvme0n1p1
  -> 문서에는 이렇게 하는 방법도 언급하고 있다.
  -> 앞서의 명령과는 달리, 이 방법은 initrd 없이 하는 것인데, hmm... 동작을 안한다. 일정 시간 경과 후 먹통이 된다... 왜 그럴까 ?


5. Deep Dive into Jetson Linux Kernel
이번 장에서는 BSP의 핵심이라고 할 수 있는 linux kernel에 관한 이야기를 좀 더 해보고자 한다. Bootloader 또한 BSP의 핵심 내용이지만, 이 부분은 이전 posting에서도 언급한 것 처럼, 어찌해 볼 수 있는 여지가 별로 없어 보이니, (이번 시간에는) Kernel과 rootfs에만 집중하도록 하자. 💢


5.1 Linux kernel Build 하기
먼저 kernel source를 download해야 하는데, 4장의 방법과는 다르게 git으로 직접 내려 받는 방법을 살펴 보기로 한다.

<Jetson BSP code 설치하기>
$ tar xvjf Jetson_Linux_R36.4.3_aarch64.tbz2
$ cd Linux_for_Tegra/source

<kernel source git에서 받기>
chyi@earth:/mnt/hdd/workspace/nvidia/jetson/Linux_for_Tegra/source$ ./source_sync.sh -k -t jetson_36.4.3
Downloading default kernel/kernel-jammy-src source...
'/mnt/hdd/workspace/nvidia/jetson/Linux_for_Tegra/source/kernel/kernel-jammy-src'에 복제합니다...
remote: Enumerating objects: 8591594, done.
remote: Counting objects: 100% (8591594/8591594), done.
remote: Compressing objects: 100% (1249958/1249958), done.
chyi@earth:/mnt/hdd/workspace/nvidia/jetson/Linux_for_Tegra/source$ ./source_sync.sh -k -t jetson_36.4.3
Downloading default kernel/kernel-jammy-src source...
'/mnt/hdd/workspace/nvidia/jetson/Linux_for_Tegra/source/kernel/kernel-jammy-src'에 복제합니다...
remote: Enumerating objects: 8591594, done.
remote: Counting objects: 100% (8591594/8591594), done.
remote: Compressing objects: 100% (1249958/1249958), done.
...
델타를 알아내는 중: 100% (60/60), 완료.
The default dtc-src/1.4.5 source is downloaded in: /mnt/hdd/workspace/nvidia/jetson/Linux_for_Tegra/source/dtc-src/1.4.5
Syncing up with tag jetson_36.4.3...
새로 만든 'mybranch_2025-06-18-1750225695' 브랜치로 전환합니다
/mnt/hdd/workspace/nvidia/jetson/Linux_for_Tegra/source/dtc-src/1.4.5 source sync'ed to tag jetson_36.4.3 successfully!
📌 source_sync.sh 파일을 열어 보면, 결국 (아래 git repo를 포함한 다양한 URL로 부터)git clone을 하고 있는 것을 알 수 있다.


$ ls -la
합계 88
drwxrwxr-x 11 chyi chyi  4096  6월 22 17:37 .
drwxrwxr-x 10 chyi chyi  4096  1월  8 10:56 ..
-rw-rw-r--  1 chyi chyi  7842  1월  8 10:42 Makefile
drwxrwxr-x  3 chyi chyi  4096  6월 22 17:37 dtc-src
-rwxrwxr-x  1 chyi chyi  6652  1월  8 10:42 generic_rt_build.sh
drwxrwxr-x  3 chyi chyi  4096  6월 22 17:37 hardware
drwxrwxr-x  5 chyi chyi  4096  6월 22 17:37 hwpm
drwxrwxr-x  3 chyi chyi  4096  6월 22 17:30 kernel
drwxrwxr-x  6 chyi chyi  4096  6월 22 17:37 kernel-devicetree
-rwxrwxr-x  1 chyi chyi  1888  1월  8 10:42 kernel_src_build_env.sh
-rwxrwxr-x  1 chyi chyi  2545  1월  8 10:42 nv_src_build.sh
-rwxrwxr-x  1 chyi chyi  7808  1월  8 10:42 nvbuild.sh
drwxrwxr-x  6 chyi chyi  4096  6월 22 17:37 nvdisplay
drwxrwxr-x  7 chyi chyi  4096  6월 22 17:37 nvethernetrm
drwxrwxr-x 10 chyi chyi  4096  6월 22 17:37 nvgpu
drwxrwxr-x 10 chyi chyi  4096  6월 22 17:37 nvidia-oot
-rwxrwxr-x  1 chyi chyi 11019  1월  8 10:42 source_sync.sh
📌 4장에서 수동으로 설치한 내용보다 내용이 적어 보이지만, 핵심적인 내용은 동일함을 알 수 있다.

위의 명령 실행 결과, 실제 kernel source는 아래 위치에 내려지게 된다.
Linux_for_Tegra/source/kernel/kernel-jammy-src

<kernel build 환경 설정>
$ export CROSS_COMPILE=/mnt/hdd/workspace/nvidia/jetson/toolchain/aarch64--glibc--stable-2022.08-1/bin/aarch64-buildroot-linux-gnu-
  -> toolchain path를 지정한다(아래 link로 부터 toolchain을 받아 두어야 한다).

$ export ARCH=arm64
  -> architecture type을 지정한다.

$ export INSTALL_MOD_PATH=/mnt/hdd/workspace/nvidia/jetson/Linux_for_Tegra/rootfs
  -> kernel module을 설치하기 위해 rootfs 디렉토리 위치를 지정한다.
$ export KERNEL_HEADERS=/mnt/hdd/workspace/nvidia/jetson/Linux_for_Tegra/source/kernel/kernel-jammy-src
  -> kernel header 위치를 지정한다.

<kernel & in-tree module build>
$ make -C kernel
  -> kernel을 build 한다(내부적으로는 아래 내용이 실행된다).

make \
ARCH=arm64 \
-C /mnt/hdd/workspace/nvidia/jetson/Linux_for_Tegra/source/kernel/kernel-jammy-src  \
LOCALVERSION=-tegra \
defconfig
📌 LOCALVERSION=-tegra를 지정하는 이유는 아래와 같은 version명을 만들기 위해서이다.
chyi@jetsonkit:~$ uname -a
Linux jetsonkit 5.15.148-tegra #2 SMP PREEMPT Sun Jun 22 19:18:47 KST 2025 aarch64 aarch64 aarch64 GNU/Linux

$ sudo -E make install -C kernel
  -> kernel (in-tree) module을 rootfs로 설치(복사)한다.
$ cp kernel/kernel-jammy-src/arch/arm64/boot/Image ../kernel/Image
  -> kernel image 파일을 복사한다. 이는 아마도 전체 image 생성 시 이 위치의 파일을 이용하기 위해서 필요한 절차인 듯하다.

참고로, kernel build 전에 kernel menuconfig를 하고 싶다면 아래와 같이 한다.

make -C kernel/kernel-jammy-src defconfig
  -> 위에서 이 과정을 하지 않을 경우 실행해 준다.
📌 defconfig 파일로 초기화한 kernel(Image)로 부팅에 실패할 경우에는 Target board의 /proc/config.gz 파일을 가져다가 사용하는 방법도 있다. 즉
$ gzip -d config.gz; cp config arch/arm64/configs/defconfig

make -C kernel/kernel-jammy-src menuconfig

[그림 5.1] make menuconfig
📌 menuconfig 수정 사항을 반영하려면, cp .config arch/arm64/configs/defconfig 명령을 수행해야 한다. 혹은 아래와 같이 할 수도 있다.
$ make savedefconfig
$ mv defconfig arch/arm64/configs/defconfig

<out-of-tree module build>
$ cd <install-path>/Linux_for_Tegra/source
$ make modules
  -> nvidia에서 추가한 out-of-tree module을 build 한다.
sudo -E make modules_install
  -> 이어서 (rootfs 디렉토리에) 설치한다.

<initramfs 만들기>
$ cd <install-path>/Linux_for_Tegra
sudo ./tools/l4t_update_initrd.sh
  -> initramfs(=> l4t_initrd.img)를 update한다.
...
Cleaning up the temporary directory for updating the initrd..
nv-update-initrd successful!
Cleaning up virtual env
Update /mnt/hdd/workspace/nvidia/jetson/Linux_for_Tegra/rootfs/boot/initrd back to /mnt/hdd/workspace/nvidia/jetson/Linux_for_Tegra/bootloader/l4t_initrd.img
update_initrd.sh success!

<dtb file build하기>
$ cd <install-path>Linux_for_Tegra/source
$ make dtbs
  -> dtb file을 만든다(build 한다).
...
make[1]: 디렉터리 '/mnt/hdd/workspace/nvidia/jetson/Linux_for_Tegra/source' 나감
================================================================================
DTBs compiled successfully.
================================================================================

$ cp kernel-devicetree/generic-dts/dtbs/* ../kernel/dtb
  -> dtb 파일을 복사한다.

<Kernel build 절차 요약>
  -> kernel build 과정만을 요약 정리해 보면 다음과 같다.
$ cd <install-path>Linux_for_Tegra/source

$ make -C kernel/kernel-jammy-src/ ARCH=arm64 LOCALVERSION=-tegra CROSS_COMPILE=${CROSS_COMPILE} defconfig

$ make -C kernel/kernel-jammy-src/ ARCH=arm64 LOCALVERSION=-tegra CROSS_COMPILE=${CROSS_COMPILE} menuconfig

$ make -C kernel/kernel-jammy-src/ ARCH=arm64 LOCALVERSION=-tegra CROSS_COMPILE=${CROSS_COMPILE} Image

$ make -C kernel/kernel-jammy-src/ ARCH=arm64  LOCALVERSION=-tegra CROSS_COMPILE=${CROSS_COMPILE} dtbs

$ make -C kernel/kernel-jammy-src/ ARCH=arm64 LOCALVERSION=-tegra CROSS_COMPILE=${CROSS_COMPILE} modules

$ make -C kernel/kernel-jammy-src/ ARCH=arm64 LOCALVERSION=-tegra INSTALL_MOD_PATH=$MODULES_OUT modules_install
__________________________________________________________

5.2 Linux kernel 교체 테스트하기
Kernel 수정 후, 교체된 Kernel을 (flash writing 과정 없이) 간단한 방법으로 시험해 보고자 한다면, 아래와 같은 절차를 따르면 된다.

kernel/kernel-jammy-src/arch/arm64/boot/Image

[그림 5.2] Target board /boot 디렉토리 내용
📌 여기에는 uefi, kernel Image, dtb 파일, initrd 등과 관련 내용이 담겨 있다.

[1] Target board의 Image 파일 backup
sudo cp /boot/Image /boot/Image.backup

[2] 수정된 Image 파일 교체 : custom kernel image -> /boot/Image
$ scp ./kernel/kernel-jammy-src/arch/arm64/boot/Image chyi@192.168.55.1:~/workspace
$ ssh chyi@192.168.55.1
chyi@jetsonkit2:~$ cd workspace/
chyi@jetsonkit2:~/workspace$ sudo cp Image /boot/Image

[3] /boot/extlinux/extlinux.conf 파일 수정(dual booting 가능하도록 설정)
# LABEL backup
#    MENU LABEL backup kernel
#    LINUX /boot/Image.backup
#    INITRD /boot/initrd
#    APPEND ${cbootargs}

->
LABEL backup
   MENU LABEL backup kernel
    LINUX /boot/Image.backup
   INITRD /boot/initrd
   APPEND ${cbootargs} root=PARTUUID=db9e9382-5fc2-487f-871f-0c0c07d743f5 rw   
rootwait rootfstype=ext4 mminit_loglevel=4 console=ttyTCU0,115200 firmware_classs
.path=/etc/firmware fbcon=map:0 nospectre_bhb video=efifb:off console=tty0



[그림 5.3] /boot/extlinux/extlinux.conf 파일 수정 모습

[4] reboot하여, 동작하는지 시험한다.

L4T boot options
0: primary kernel
1: backup kernel
Press 0-1 to boot selection within 3.0 secons.
Press any other key to boot default (Option: 0)

[그림 5.4] Console에서 L4T boot option 선택 가능 - 0, 1 중 선택

OK, 정상적으로 부팅이 되는 것을 알 수 있다. 😎


그런데, 만일, 새로 교체한 Image 파일이 문제를 일으켜 아래와 같이 [ENTER]를 입력하여 recovery mode로 진입(bash 실행)한 경우에는, 문제 해결 후 UEFI 설정을 변경하여, L4T boot mode로 다시 돌아오게 만들 수 있다.

[   18.470709] ttyTCU0: Press [ENTER] to start bash in 30 seconds...
[   21.471156] ttyTCU0: Press [ENTER] to start bash in 27 seconds...
[   24.471526] ttyTCU0: Press [ENTER] to start bash in 24 seconds...
[   27.471892] ttyTCU0: Press [ENTER] to start bash in 21 seconds...
[   30.472259] ttyTCU0: Press [ENTER] to start bash in 18 seconds...
[   33.472626] ttyTCU0: Press [ENTER] to start bash in 15 seconds...

즉, recovery 모드로 진입한 경우에는 아래와 같이 (문제가 있는 Image 파일을 제거하기 위해) Image.backup 파일을 Image로 교체하고, UEFI에서 Normal mode로 변경 후, 다시 부팅을 시도하면 된다.

<Recovery mode에서 Image 파일 교체 방법>
# mount -t ext4 /dev/nvme0n1p1 /mnt
# cd /boot
# cp Image.backup Image

<Recovery Mode -> Normal Mode로 전환하기>
1) 부팅 시, UEFI Menu에 진입하기 위해 ESC 키 입력
2) 이후 아래 순서로 메뉴 선택
    Device Manager → NVIDIA Configuration → L4T Configuration → OS chain A status →  Unbootable 대신 Normal 선택
3) Save and exit, reboot

->
[그림 5.5] Recovery Mode -> Normal mode로 전환하기

5.3 Linux kernel module 시험하기
앞서 kernel Image 파일 교체 시험을 해 보았으니, 이번에는 kernel module을 테스트해 볼 차례이다. (본 posting의 내용과는 다소 거리가 있지만) 편의상 이번에 시험에 사용할 kernel module은 wireguard 이다. 😍 
먼저, WireGuard 동작에 필요한 kernel requirement는 다음과 같다(아래의 kernel feature가 enable되어 있는지 확인해야 한다).

[그림 5.6] WireGuard kernel requirements

만일, 해당 feature 중 하나라도 enable되어 있지 않다면, menuconfig를 통해 enable 시켜 주도록 하자.

$ cd <install-path>Linux_for_Tegra/source
$ make -C kernel/kernel-jammy-src/ menuconfig

[그림 5.7] kernel menuconfig - WireGuard 선택

이후 kernel & module을 다시 build 하도록 한다.

make -C kernel
sudo -E make install -C kernel
  -> kernel (in-tree) module을 rootfs로 설치(복사)한다.

마지막으로 wireguard.ko 등 신규로 build된 kernel module을 target 보드로 복사하자.

$ cd <install-path>Linux_for_Tegra
$ cd rootfs/lib/modules/5.15.148-tegra/kernel/drivers/net/wireguard
$ ls -la
합계 796
drwxr-xr-x  2 root root   4096  6월 22 19:20 .
drwxr-xr-x 13 root root   4096  6월 22 19:20 ..
-rw-r--r--  1 root root 803409  6월 22 19:20 wireguard.ko

<Target board>


Target board에서 wireguard를 구동시킨 모습은 다음과 같다.

$ sudo modprobe wireguard
$ ls mod | grep wireguard

[그림 5.8] wireguard module 구동 모습
📌 여기에서는 편의상 wireguard 구동에 필요한 나머지 module에 대해서는 소개하지 않기로 한다. 이의 내용이 원하는 대로 되지 않을 경우에는 아래와 같이 5.15.148-tegra 디렉토리를 통째로 묶어 target board로 복사하는 방법도 생각해 볼 수 있다.
Linux_for_Tegra/rootfs/lib/modules/5.15.148-tegra

이후 wireguard 관련 설정을 진행하도록 한다. 자세한 사항은 아래 link(2장)를 참조하도록 하자.


5.4 root file system
지금까지는 prebuilt root file system을 이용하여 테스트를 진행하였다. 이 절에서는 root file system을 신규로 생성하는 방법을 간단히 알아보도록 하겠다.


<root file system을 만드는 3가지 방법>
$ sudo ./nv_build_samplefs.sh --abi aarch64 --distro ubuntu --flavor desktop --version jammy
  -> desktop 용
$ sudo ./nv_build_samplefs.sh --abi aarch64 --distro ubuntu --flavor minimal --version jammy
  -> minimal 용
$ sudo ./nv_build_samplefs.sh --abi aarch64 --distro ubuntu --flavor basic --version jammy
  -> basic 용 
_____________________________________

이중, desktop용 root file system을 만들어 보도록 하자.

cd Linux_for_Tegra/tools/samplefs
sudo ./nv_build_samplefs.sh --abi aarch64 --distro ubuntu --flavor desktop --version jammy
...
...
done.
Processing triggers for initramfs-tools (0.140ubuntu13.5) ...
Processing triggers for libgdk-pixbuf-2.0-0:arm64 (2.42.8+dfsg-1ubuntu0.3) ...
Processing triggers for rygel (0.40.3-1ubuntu2) ...
Processing triggers for sgml-base (1.30) ...
nv_build_samplefs.sh - save_samplefs
********************************************
   ubuntu samplefs Creation Complete     
********************************************
Samplefs - /mnt/hdd/workspace/nvidia/jetson/Linux_for_Tegra/tools/samplefs/sample_fs.tbz2 was generated.
nv_build_samplefs.sh - cleanup

ls -la
합계 1771520
drwxrwxr-x  2 chyi chyi       4096  6월 16 21:36 .
drwxrwxr-x 13 chyi chyi       4096  6월 16 15:07 ..
-rwxrwxr-x  1 chyi chyi       6490  1월  8 10:42 nv_build_samplefs.sh
-rw-rw-r--  1 chyi chyi        158  1월  8 10:42 nvubuntu-jammy-aarch64-samplefs
-rw-rw-r--  1 chyi chyi       4717  1월  8 10:42 nvubuntu-jammy-basic-aarch64-packages
-rw-rw-r--  1 chyi chyi      30119  1월  8 10:42 nvubuntu-jammy-desktop-aarch64-packages
-rw-rw-r--  1 chyi chyi      13153  1월  8 10:42 nvubuntu-jammy-minimal-aarch64-packages
-rwxrwxr-x  1 chyi chyi       4124  1월  8 10:42 nvubuntu_samplefs.sh
-rw-r--r--  1 root root 1813945944  6월 16 21:35 sample_fs.tbz2

OK, root file system이 만들어 졌다.


<여기서 잠깐 ! Jetson Dev Kit를 위한 Yocto Project 소개>
  -> 아래 site의 내용을 참조하여 Yocto 기반으로 Jetson Kit용 image를 만들어 보자.


$ git clone https://github.com/OE4T/tegra-demo-distro.git
$ cd tegra-demo-distro
$ git branch
* master
$ git checkout scarthgap
$ git branch
   master
* scarthgap

git submodule update --init

$ .  ./setup-env --machine jetson-orin-nano-devkit-nvme
...
You can now run 'bitbake <target>'
Targets for building Tegra demo images with test applications:
    core-image-minimal  - minimally bootable image (no demo apps, no graphics)
    demo-image-base     - basic image with no graphics
    demo-image-egl      - basic image with DRM/EGL, no window manager
    demo-image-sato     - X11 image with 'sato' UI
    demo-image-weston   - Wayland with Weston compositor
    demo-image-full     - X11/sato UI plus docker, openCV, VPI, TensorRT and multimedia API samples

$ bitbake core-image-minimal
Loading cache: 100% |                                                                     | ETA:  --:--:--
Loaded 0 entries from dependency cache.
Parsing recipes: 100% |####################################################################| Time: 0:00:22
Parsing of 3111 .bb files complete (0 cached, 3111 parsed). 5121 targets, 132 skipped, 0 masked, 0 errors.
NOTE: Resolving any missing task queue dependencies

Build Configuration:
BB_VERSION           = "2.8.0"
BUILD_SYS            = "x86_64-linux"
NATIVELSBSTRING      = "ubuntu-22.04"
TARGET_SYS           = "aarch64-oe4t-linux"
MACHINE              = "jetson-orin-nano-devkit-nvme"
DISTRO               = "tegrademo"
DISTRO_VERSION       = "5.0.10+snapshot-7500a08bd1eb77421364b661afc63d4042a6aa8c"
TUNE_FEATURES        = "aarch64 armv8a crc"
TARGET_FPU           = ""
meta                 = "HEAD:7500a08bd1eb77421364b661afc63d4042a6aa8c"
meta-tegra           = "HEAD:e4379e5131b0f0df3949c023a13f648506a3084d"
meta-oe              
meta-python          
meta-networking      
meta-filesystems     = "HEAD:491671faee11ea131feab5a3a451d1a01deb2ab1"
meta-virtualization  = "HEAD:9e040ee8dd6025558ea60ac9db60c41bfeddf221"
meta-tegra-community = "HEAD:241d1073ba8e610ef8da3fe8470b0a4d0567521f"
meta-tegra-support   
meta-demo-ci         
meta-tegrademo       = "scarthgap:973413b96c12b512509b34a9fd2e7a685a7fdd80"

NOTE: Fetching uninative binary shim http://downloads.yoctoproject.org/releases/uninative/4.7/x86_64-nativesdk-libc-4.7.tar.xz;sha256sum=5800d4e9a129d1be09cf548918d25f74e91a7c1193ae5239d5b0c9246c486d2c (will check PREMIRRORS first)
Sstate summary: Wanted 2424 Local 0 Mirrors 0 Missed 2424 Current 0 (0% match, 0% complete)| ETA:  0:00:00
Initialising tasks: 100% |#################################################################| Time: 0:00:02
NOTE: Executing Tasks
WARNING: libconfig-1.7.3-r0 do_fetch: Failed to fetch URL https://hyperrealm.github.io/libconfig/dist/libconfig-1.7.3.tar.gz, attempting MIRRORS if available
WARNING: edk2-firmware-tegra-36.4.3-r0 do_fetch: Failed to fetch URL gitsm://github.com/Zeex/subhook.git;protocol=https;name=UnitTestFrameworkPkg/Library/SubhookLib/subhook;subpath=UnitTestFrameworkPkg/Library/SubhookLib/subhook;nobranch=1;lfs=True;bareclone=1;nobranch=1, attempting MIRRORS if available
Setscene tasks: 2424 of 2424
Currently 14 running tasks (3932 of 5149)  76% |###########################################              |
0: gcc-13.4.0-r0 do_compile - 3m34s (pid 1575915)
1: gnutls-3.8.4-r0 do_configure - 2m41s (pid 1658164)
2: linux-jammy-nvidia-tegra-5.15.148+git-r0 do_configure - 2m41s (pid 1657909)
3: socat-1.8.0.0-r0 do_configure - 1m37s (pid 1725340)
4: curl-8.7.1-r0 do_configure - 1m37s (pid 1727816)
5: python3-3.12.11-r0 do_configure - 1m36s (pid 1728592)
6: linux-libc-headers-6.6-r0 do_package - 1m30s (pid 1736564)
7: tzdata-2025b-r0 do_package - 1m28s (pid 1737937)
8: rust-llvm-native-1.75.0-r0 do_install - 1m0s (pid 1783755)
9: desktop-file-utils-0.27-r0 do_prepare_recipe_sysroot - 52s (pid 1795936)
10: perl-5.38.4-r0 do_compile - 52s (pid 1798998)
11: libdnf-native-0.73.2-r0 do_prepare_recipe_sysroot - 50s (pid 1798204)
12: e2fsprogs-1.47.0-r0 do_install_ptest_base - 48s (pid 1802080)
13: cairo-1.18.0-r0 do_configure - 48s (pid 1802198)
...

$ cd tmp/deploy/images/jetson-orin-nano-devkit-nvme
$ ls -la
합계 515572
drwxr-xr-x 3 chyi chyi      4096  6월 23 15:15 .
drwxr-xr-x 3 chyi chyi      4096  6월 23 12:53 ..
lrwxrwxrwx 2 chyi chyi        82  6월 23 14:56 Image -> Image--5.15.148+git0+8dc079d5c8-r0-jetson-orin-nano-devkit-nvme-20250623033113.bin
-rw-r--r-- 2 chyi chyi  42304000  6월 23 14:56 Image--5.15.148+git0+8dc079d5c8-r0-jetson-orin-nano-devkit-nvme-20250623033113.bin
lrwxrwxrwx 2 chyi chyi        82  6월 23 14:56 Image-jetson-orin-nano-devkit-nvme.bin -> Image--5.15.148+git0+8dc079d5c8-r0-jetson-orin-nano-devkit-nvme-20250623033113.bin
lrwxrwxrwx 2 chyi chyi        85  6월 23 14:56 Image.gz -> Image.gz--5.15.148+git0+8dc079d5c8-r0-jetson-orin-nano-devkit-nvme-20250623033113.bin
-rw-r--r-- 2 chyi chyi  14224772  6월 23 14:56 Image.gz--5.15.148+git0+8dc079d5c8-r0-jetson-orin-nano-devkit-nvme-20250623033113.bin
lrwxrwxrwx 2 chyi chyi        85  6월 23 14:56 Image.gz-jetson-orin-nano-devkit-nvme.bin -> Image.gz--5.15.148+git0+8dc079d5c8-r0-jetson-orin-nano-devkit-nvme-20250623033113.bin
-rw-r--r-- 2 chyi chyi       432  6월 23 12:53 L4TConfiguration-RootfsRedundancyLevelABEnable.dtbo
-rw-r--r-- 2 chyi chyi       966  6월 23 13:03 L4TConfiguration-rcmboot.dtbo
-rw-r--r-- 2 chyi chyi       978  6월 23 13:03 L4TConfiguration.dtbo
-rw-r--r-- 2 chyi chyi 196169728  6월 23 15:15 core-image-minimal-jetson-orin-nano-devkit-nvme.rootfs-20250623033113.ext4
-rw-r--r-- 2 chyi chyi      9541  6월 23 15:15 core-image-minimal-jetson-orin-nano-devkit-nvme.rootfs-20250623033113.manifest
-rw-r--r-- 2 chyi chyi    471024  6월 23 15:15 core-image-minimal-jetson-orin-nano-devkit-nvme.rootfs-20250623033113.spdx.tar.zst
-rw-r--r-- 2 chyi chyi 132305997  6월 23 15:15 core-image-minimal-jetson-orin-nano-devkit-nvme.rootfs-20250623033113.tegraflash.tar.gz
-rw-r--r-- 2 chyi chyi    474137  6월 23 15:15 core-image-minimal-jetson-orin-nano-devkit-nvme.rootfs-20250623033113.testdata.json
lrwxrwxrwx 2 chyi chyi        74  6월 23 15:15 core-image-minimal-jetson-orin-nano-devkit-nvme.rootfs.ext4 -> core-image-minimal-jetson-orin-nano-devkit-nvme.rootfs-20250623033113.ext4
lrwxrwxrwx 2 chyi chyi        78  6월 23 15:15 core-image-minimal-jetson-orin-nano-devkit-nvme.rootfs.manifest -> core-image-minimal-jetson-orin-nano-devkit-nvme.rootfs-20250623033113.manifest
lrwxrwxrwx 2 chyi chyi        82  6월 23 15:15 core-image-minimal-jetson-orin-nano-devkit-nvme.rootfs.spdx.tar.zst -> core-image-minimal-jetson-orin-nano-devkit-nvme.rootfs-20250623033113.spdx.tar.zst
lrwxrwxrwx 2 chyi chyi        87  6월 23 15:15 core-image-minimal-jetson-orin-nano-devkit-nvme.rootfs.tegraflash.tar.gz -> core-image-minimal-jetson-orin-nano-devkit-nvme.rootfs-20250623033113.tegraflash.tar.gz
lrwxrwxrwx 2 chyi chyi        83  6월 23 15:15 core-image-minimal-jetson-orin-nano-devkit-nvme.rootfs.testdata.json -> core-image-minimal-jetson-orin-nano-devkit-nvme.rootfs-20250623033113.testdata.json
drwxr-xr-x 2 chyi chyi     12288  6월 23 14:30 devicetree
-rw-r--r-- 2 chyi chyi  63237493  6월 23 14:58 modules--5.15.148+git0+8dc079d5c8-r0-jetson-orin-nano-devkit-nvme-20250623033113.tgz
lrwxrwxrwx 2 chyi chyi        84  6월 23 14:58 modules-jetson-orin-nano-devkit-nvme.tgz -> modules--5.15.148+git0+8dc079d5c8-r0-jetson-orin-nano-devkit-nvme-20250623033113.tgz
-rw-r--r-- 2 chyi chyi  67108864  6월 23 15:03 tegra-espimage-jetson-orin-nano-devkit-nvme-20250623033113.esp
-rw-r--r-- 2 chyi chyi        49  6월 23 15:03 tegra-espimage-jetson-orin-nano-devkit-nvme-20250623033113.manifest
-rw-r--r-- 2 chyi chyi     28025  6월 23 15:03 tegra-espimage-jetson-orin-nano-devkit-nvme-20250623033113.spdx.tar.zst
-rw-r--r-- 2 chyi chyi    471225  6월 23 15:03 tegra-espimage-jetson-orin-nano-devkit-nvme-20250623033113.testdata.json
lrwxrwxrwx 2 chyi chyi        62  6월 23 15:03 tegra-espimage-jetson-orin-nano-devkit-nvme.esp -> tegra-espimage-jetson-orin-nano-devkit-nvme-20250623033113.esp
lrwxrwxrwx 2 chyi chyi        67  6월 23 15:03 tegra-espimage-jetson-orin-nano-devkit-nvme.manifest -> tegra-espimage-jetson-orin-nano-devkit-nvme-20250623033113.manifest
lrwxrwxrwx 2 chyi chyi        71  6월 23 15:03 tegra-espimage-jetson-orin-nano-devkit-nvme.spdx.tar.zst -> tegra-espimage-jetson-orin-nano-devkit-nvme-20250623033113.spdx.tar.zst
lrwxrwxrwx 2 chyi chyi        72  6월 23 15:03 tegra-espimage-jetson-orin-nano-devkit-nvme.testdata.json -> tegra-espimage-jetson-orin-nano-devkit-nvme-20250623033113.testdata.json
-rw-r--r-- 2 chyi chyi  72935424  6월 23 15:14 tegra-initrd-flash-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.cpio.gz.cboot
-rw-r--r-- 2 chyi chyi      7932  6월 23 15:14 tegra-initrd-flash-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.manifest
-rw-r--r-- 2 chyi chyi    232966  6월 23 15:14 tegra-initrd-flash-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.spdx.tar.zst
-rw-r--r-- 2 chyi chyi    483615  6월 23 15:14 tegra-initrd-flash-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.testdata.json
lrwxrwxrwx 2 chyi chyi        86  6월 23 15:14 tegra-initrd-flash-initramfs-jetson-orin-nano-devkit-nvme.cboot -> tegra-initrd-flash-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.cpio.gz.cboot
lrwxrwxrwx 2 chyi chyi        86  6월 23 15:14 tegra-initrd-flash-initramfs-jetson-orin-nano-devkit-nvme.cpio.gz.cboot -> tegra-initrd-flash-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.cpio.gz.cboot
lrwxrwxrwx 2 chyi chyi        81  6월 23 15:14 tegra-initrd-flash-initramfs-jetson-orin-nano-devkit-nvme.manifest -> tegra-initrd-flash-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.manifest
lrwxrwxrwx 2 chyi chyi        85  6월 23 15:14 tegra-initrd-flash-initramfs-jetson-orin-nano-devkit-nvme.spdx.tar.zst -> tegra-initrd-flash-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.spdx.tar.zst
lrwxrwxrwx 2 chyi chyi        86  6월 23 15:14 tegra-initrd-flash-initramfs-jetson-orin-nano-devkit-nvme.testdata.json -> tegra-initrd-flash-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.testdata.json
-rw-r--r-- 2 chyi chyi   5192592  6월 23 15:13 tegra-minimal-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.cpio.gz
-rw-r--r-- 2 chyi chyi  47501312  6월 23 15:13 tegra-minimal-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.cpio.gz.cboot
-rw-r--r-- 2 chyi chyi      1502  6월 23 15:13 tegra-minimal-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.manifest
-rw-r--r-- 2 chyi chyi    112415  6월 23 15:13 tegra-minimal-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.spdx.tar.zst
-rw-r--r-- 2 chyi chyi    479450  6월 23 15:13 tegra-minimal-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.testdata.json
lrwxrwxrwx 2 chyi chyi        81  6월 23 15:13 tegra-minimal-initramfs-jetson-orin-nano-devkit-nvme.cboot -> tegra-minimal-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.cpio.gz.cboot
lrwxrwxrwx 2 chyi chyi        75  6월 23 15:13 tegra-minimal-initramfs-jetson-orin-nano-devkit-nvme.cpio.gz -> tegra-minimal-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.cpio.gz
lrwxrwxrwx 2 chyi chyi        81  6월 23 15:13 tegra-minimal-initramfs-jetson-orin-nano-devkit-nvme.cpio.gz.cboot -> tegra-minimal-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.cpio.gz.cboot
lrwxrwxrwx 2 chyi chyi        76  6월 23 15:13 tegra-minimal-initramfs-jetson-orin-nano-devkit-nvme.manifest -> tegra-minimal-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.manifest
lrwxrwxrwx 2 chyi chyi        80  6월 23 15:13 tegra-minimal-initramfs-jetson-orin-nano-devkit-nvme.spdx.tar.zst -> tegra-minimal-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.spdx.tar.zst
lrwxrwxrwx 2 chyi chyi        81  6월 23 15:13 tegra-minimal-initramfs-jetson-orin-nano-devkit-nvme.testdata.json -> tegra-minimal-initramfs-jetson-orin-nano-devkit-nvme-20250623033113.testdata.json
-rw-r--r-- 2 chyi chyi   1607664  6월 23 15:12 tos-jetson-orin-nano-devkit-nvme-36.4.3-r0.img
lrwxrwxrwx 2 chyi chyi        46  6월 23 15:12 tos-jetson-orin-nano-devkit-nvme.img -> tos-jetson-orin-nano-devkit-nvme-36.4.3-r0.img
-rw-r--r-- 2 chyi chyi   3276800  6월 23 13:03 uefi_jetson.bin
-rw-r--r-- 2 chyi chyi   1769472  6월 23 13:03 uefi_jetson_minimal.bin

예상한 대로, 상당히 많은 결과물이 만들어진다. 💢
___________________________________________________________

이상으로 Jetson Linux kernel과 module을 build한 후, 테스트해 보기까지의 전 과정을 가볍게 살펴 보았다. (Yocto project의 build 결과물을 테스트해 보지 못한 아쉬움은 좀 남지만, 이를 뒤로 하고) 이어지는 장에서는 device tree와 device driver에 관한 내용을 소개하도록 하자. 😋



6. Device Tree and Device Drivers
이번 장에서는Jetson Linux BSP 관련 내용 중, Device Tree와 Device Driver에 관한 내용을 살펴 보고자 한다. 내용이 길어지는 관계로, 다음 번 posting에서 설명을 이어가기로 하자.  🌌

To be continued...



References
[1] jetson-orin-datasheet-nano-developer-kit-3475392-r2.pdf
  -> 제품 brochure
[2] https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/jetson-orin/nano-super-developer-kit/
  -> Jetson Orin Nano Super Developer Kit 공식 site
[3] https://docs.nvidia.com/jetson/archives/r36.4.3/DeveloperGuide/
  -> NVIDIA Jetson Linux developer guide 문서 *****
[4] https://www.jetson-ai-lab.com/initial_setup_jon.html
  -> Initial setup guide for etson Orin Nano Developer Kit *****
[5] Jetson Orin Nano Developer Kit Carrier Board, SP-11324-001_v1.3 pdf
[6] Jetson Orin NX Series and Jetson Orin Nano Series Product Design Guide
[7] Jetson Orin NX Series and Jetson Orin Nano Series Pin and Function Names Guide
[8] NVIDIA Orin Series System-on-Chip Technical Reference Manual
[9] NVIDIA Jetson Orin Nano Series Modules Data Sheet - Ampere GPU + Arm Cortex-A78AE CPU + LPDDR5
  -> Jetson Orin Nano Developer Kit 관련 h/w 문서
[10] https://docs.nvidia.com/jetson/archives/r35.4.1/DeveloperGuide/text/AR/BootArchitecture/JetsonOrinSeriesBootFlow.html
  -> Jetson Orin Nano Boot Flow
[11] https://www.jetson-ai-lab.com/index.html
[12] https://www.jetson-ai-lab.com/initial_setup_jon.html
[13] https://www.jetson-ai-lab.com/tutorial-intro.html
  -> ai-lab & Initial setup guide

[14] https://docs.nvidia.com/deeplearning/tensorrt/latest/getting-started/quick-start-guide.html
  -> TensorRT guide

[15] CUDA C++ Programming Guide, Release 12.9, NVIDIA Corportation
[16] https://developer.ridgerun.com/wiki/index.php/Yocto_Support_for_NVIDIA_Jetson_Platforms_-_Setting_up_Yocto
[17] https://github.com/OE4T/tegra-demo-distro#tegra-demo-distro

[18] https://jetsonhacks.com/
[19] https://github.com/jetsonhacks
[20] https://jetsonhacks.com/2025/03/13/build-jetson-orin-kernel-and-modules/
   -> Cool site~

[21] And, Google & Gemini ~


Slowboot