- PetaLinux는 Zynq/ZynqMP에서 사용자 정의가 가능한 커널, 장치 트리, 루트 파일 시스템을 제공합니다.
- 실제 워크플로는 Vivado(XSA), PetaLinux(이미지), Vitis/SDK(앱)를 결합합니다.
- 장치 트리는 Vivado에 정의된 주소와 인터럽트 맵을 반영합니다.
- UIO/드라이버는 IP에 대한 액세스를 용이하게 하고, FPGA 관리자는 PL 반복을 간소화합니다.
PetaLinux 사용에 어려움을 겪고 계신가요? 걱정하지 마세요. 당신만 그런 게 아닙니다. PetaLinux는 학습 곡선이 가파르 지만, Vivado, PetaLinux, Vitis가 어떻게 함께 작동하고 각 구성 요소가 어떤 역할을 하는지 이해하는 명확한 방법이 있습니다. 이 글에서는 Vivado 설계에서 Zynq 또는 Zynq UltraScale+에서 첫 번째 Linux 애플리케이션을 실행하는 단계까지 , 복잡하지 않고 차근차근 진행할 수 있도록 실용적이고 체계적인 설명을 제공합니다.
많은 사람들이 Vitis만으로 시스템을 구축하는 것이 가능한지 궁금해합니다. 커널, 디바이스 트리, 루트 파일 시스템을 위해서는 PetaLinux가 필요합니다 . 실제 시스템에서 흔히 볼 수 있는 워크플로는 다음과 같습니다. Vivado에서 .xsa 파일을 생성하고, PetaLinux 프로젝트를 생성 및 구성(때로는 BSP에서)한 다음, 이미지를 컴파일하고 패키징(SD 카드의 경우 WIC 사용)합니다. 마지막으로 시스템 루트를 내보내 Vitis 또는 외부 툴체인을 사용하여 애플리케이션을 개발합니다. 나중에는 대안, 무한 재빌드를 방지하는 팁, FPGA Manager 또는 TCF Agent와 같은 도구 사용법에 대해 설명하겠습니다.
PetaLinux란 무엇이고 기본적으로 무엇이 포함되어 있나요?
PetaLinux는 AMD의 SoC 및 MPSoC용으로 설계된 레퍼런스 배포판으로, 최적화된 부트로더 및 커널 , 라이브러리 및 유틸리티, C/C++ 지원, 디버깅 도구를 갖춘 사용자 정의 가능한 Linux 환경을 제공합니다 . 또한 스레딩 옵션, FPU 지원, 간편한 네트워크 및 펌웨어 구성을 위한 웹 기반 관리 서버도 포함되어 있습니다.
공식 BSP(부팅 및 구성 서비스 패키지)에는 일반적으로 미리 만들어진 부팅 및 구성 이미지가 포함되어 있습니다. 실제 하드웨어 또는 PetaLinux에 포함된 전체 시스템 에뮬레이터인 QEMU에서 바이너리를 배포하고 실행하세요 . 이렇게 하면 초기 테스트 속도가 빨라지고 앱 이나 드라이버 작업을 시작하기 전에 프로젝트가 제대로 부팅되는지 확인하는 데 이상적입니다.
권장되는 하드웨어-소프트웨어 워크플로
전문적인 환경에서는 두 가지 버전의 Linux 워크플로가 사용됩니다. 하나는 PetaLinux 명령 줄에 초점을 맞춘 것이고, 다른 하나는 애플리케이션 개발을 위해 Vitis를 통합하여 .xsa 파일 과 필요한 경우 비트스트림을 생성하는 것입니다.
Vitis에서 모든 걸 할 수 있나요? 리눅스에서는 불가능합니다. Vitis는 사용자 정의 커널, 디바이스 트리, 루트 파일 시스템이 필요한 플랫폼을 구축하는 데 유용합니다 . 일반적인 접근 방식은 PetaLinux를 사용하여 시스템을 빌드하고 SDK/sysroot를 내보낸 다음, Vitis 또는 외부 툴체인을 사용하여 애플리케이션을 컴파일하고 디버깅하는 것입니다.
XSA에서 부트 시스템으로
최소한의 실행 가능한 절차는 일반적으로 다음과 같습니다. Vivado에서 .xsa 파일을 생성하고 , petalinux-create를 사용하여 프로젝트를 생성하거나(또는 BSP에서 시작), 해당 .xsa 파일을 사용하여 PetaLinux에서 하드웨어를 업데이트하고, 구성(커널, 장치 트리 및 루트 파일 시스템)을 조정합니다. 그런 다음 컴파일하고 .wic 형식으로 패키징한 후 SD 카드에 플래싱합니다.
시스템 부팅이 완료되면 애플리케이션을 추가할 차례입니다. PetaLinux에서 sysroot/SDK를 내보내고 , Vitis에서 .xsa 파일을 사용하여 플랫폼을 생성합니다. 그런 다음, sysroot를 가리키도록 C/C++ 애플리케이션 프로젝트를 생성하여 rootfs 라이브러리와 올바르게 링크하고, tcf-agent, gdbserver 또는 원하는 방법을 사용하여 대상 시스템에서 애플리케이션을 실행합니다.
실제 사용 시 발생할 수 있는 작은 문제점을 알려드리겠습니다 . Vivado/Vitis/PetaLinux 버전 마다 특이한 점이 있습니다. 예를 들어, Vitis Unified 2023.2 버전에서 tcf-agent에 연결할 수 없는 문제가 보고되었는데, 빠른 해결책은 2024.1 버전으로 업그레이드하는 것이었습니다. 항상 릴리스 노트를 확인하고, 가능하다면 프로젝트 진행 중에는 사용하는 도구 스택을 고정(floating)해 두는 것이 좋습니다.
Vivado(Zynq-7000 및 Zynq UltraScale+)의 하드웨어 설계
Vivado의 블록 디자인을 기반으로 기술을 구현하십시오. "ZYNQ7 처리 시스템" 블록 (또는 ZynqMP의 해당 블록)을 추가하고 블록 자동화 실행을 통해 DRAM과 클럭을 연결하십시오. 그 후 필요한 부분을 조정하십시오.
- 외부 인터럽트 활성화: PS 사용자 정의에서 PL 주변 장치 간에 IRQ 라인을 공유하려는 경우 PS-PL 인터럽트 및 공유 인터럽트를 활성화합니다.
- 클록 동기화: 일반적인 관행은 FCLK_CLK0을 M_AXI_GP0_ACLK 포트에 연결하여 AXI 버스 클록이 PS 클록과 일치하도록 하는 것입니다.
PL IP를 사용할 때는 자동화 기능을 활용하세요. 연결 자동화(Connection Automation)를 실행하면 AXI 상호 연결 및 중재가 설정되지만, 인터럽트나 모든 클록 트리를 연결하지는 않는다는 점에 유의하십시오. IRQ의 경우, 연결 블록(concat block)을 사용하고 해당 출력을 PS로 라우팅하세요.
- 주변 장치 IP의 각 IRQ 라인을 Concat 블록에 연결합니다.
- Concat 출력을 PS 인터럽트 입력에 연결합니다.
PL에 고속 메모리가 필요한 경우 BRAM을 추가하십시오. BRAM 컨트롤러와 블록 메모리 생성기를 삽입하고 포트 수, 너비 및 용량을 정의한 다음, 가장 중요한 것은 주소 편집기에서 매핑을 확인하는 것입니다.
- 주소 맵을 확인하고 조정합니다. 범위가 겹치면 안 됩니다. 겹치는 경우 Vivado는 충돌 부분을 빨간색으로 표시합니다.
- 다른 마스터(예: PL의 보조 프로세서)를 고려해 보세요. 합성 실패를 방지하려면 주소를 할당하는 것이 필수입니다.
설계를 최종화하려면 .bd 파일에 대한 HDL 래퍼를 생성하고, 이를 합성한 다음 구현하십시오. 비트스트림 생성에는 시간이 다소 걸릴 수 있으며, 완료되면 하드웨어를 내보내십시오. 이때, 시작 시 PL을 프로그래밍하려는 경우 해당 비트도 포함해야 합니다.
몇 가지 유용한 사항: 예를 들어 PYNQ 쉴드를 사용할 경우, GPIO 또는 I2C용 EMIO를 통해 PS 신호를 PL에 노출하는 것이 매우 실용적입니다. 통합 주변 장치는 주의해야 합니다. 이러한 장치는 일반적으로 장치의 고정 핀에 하드웨어적으로 연결되어 있으며, 연결을 변경하지 않고 패브릭 레벨 IP로 교체하는 것이 항상 가능한 것은 아닙니다. 구현에 실패하면 제한 사항(XDC) 및 할당을 확인하십시오.
장치 트리 및 하드웨어 매핑
백만 달러짜리 질문: 리눅스는 어디까지 추상화할까요? 디바이스 트리는 장치 주소, IRQ 및 호환성을 설명합니다. 이 매핑은 오버레이를 사용하지 않는 한 부팅 시 "동적"이지 않고, 일반적으로 Vivado의 주소 편집기와 PetaLinux에서 생성된 DTS를 기반으로 정적으로 유지됩니다.
제어 부분(레지스터)과 데이터 부분(예: DMA 접근)은 개념적으로나 물리적으로 분리되어야 합니다. "reg" 범위와 인터럽트 라인을 사용하십시오 . 드라이버(또는 UIO)는 이 정보를 사용하여 메모리와 인터럽트 로직을 매핑합니다. 범위의 크기와 정렬은 Vivado에서 정의한 것과 일치해야 합니다.
PetaLinux로 컴파일하는 경우, DTS 조각은 일반적으로 .xsa 파일에서 자동으로 생성됩니다. 하드웨어를 변경할 때(새로운 IP 주소 또는 주소) .xsa 파일을 업데이트하고 최소한 디바이스 트리와 커널을 다시 빌드해야 합니다. 루트 파일 시스템(rootfs) 파일은 항상 변경할 필요가 없으므로 사용자 라이브러리가 수정되지 않은 경우 시스템 루트 파일(sysroot)은 계속 작동할 수 있습니다.
C/C++에서 하드웨어에 액세스하기 위한 옵션
정해진 한 가지 방법은 없습니다. 프로젝트 단계와 드라이버 개발에 투자할 노력에 따라 선택하세요. /dev/mem 은 MMIO 매핑에 사용되지만, 보안, 이식성 및 잠재적인 중단 문제 때문에 프로덕션 환경에서는 권장되지 않습니다.
중간 대안으로 UIO(Userspace I/O)를 사용할 수 있습니다. UIO를 사용하면 사용자 공간에서 IP 영역을 매핑하고 선택/폴링 방식으로 인터럽트를 처리할 수 있습니다. 이 방법은 디바이스 트리에 UIO 노드를 추가해야 하지만, 완전한 드라이버를 작성할 필요는 없습니다.
전문적인 방법은 IP용 문자 드라이버 또는 플랫폼 드라이버를 개발하는 것입니다. 문자 드라이버를 사용하면 DMA, IRQ, 전력 관리를 세밀하게 제어할 수 있고, /dev에서 안정적인 인터페이스를 제공하며, 커널 생태계와의 통합도 향상됩니다. IP가 AXI-DMA 또는 표준 프레임워크를 사용하는 경우에는 기존 드라이버를 활용하십시오.
툴체인 관련해서는 Vitis를 사용하거나 PetaLinux에서 제공하는 SDK를 사용하여 컴파일할 수 있습니다. `petalinux-build --sdk`를 실행하고 프로젝트를 해당 시스템 루트에 링크하여 대상 시스템의 루트 파일 시스템에 있는 라이브러리와 동일한 라이브러리에 링크되도록 하십시오. Vitis는 .xsa 파일에서 플랫폼을 빌드하고 원격 디버깅을 시작하는 과정을 간소화합니다.
디버깅 및 원격 실행
대상 시스템에서 앱을 실행하는 방법은 여러 가지가 있습니다. tcf-agent는 Vitis에서 앱을 실행하고 디버깅하는 데 효과적이며, 단 에이전트가 루트 파일 시스템에 설치되어 있어야 합니다(petalinux-config -c rootfs 명령으로 추가). 또한 버전 충돌이 없어야 합니다.
또는 gdbserver는 간단하고 안정적인 방법입니다. 바이너리 파일을 대상 위치에 복사하고 `gdbserver :port ./yourapp` 명령을 실행한 다음, 호스트에서 멀티 아키텍처 gdb를 사용하여 연결하면 됩니다. 많은 팀에서 gdbserver를 VS Code Remote 또는 Python 스크립트와 함께 사용합니다.
printf를 넘어서는 방법으로 커널 프로파일링 및 추적 기법을 살펴보세요. Zynq 커뮤니티는 버그가 명확하지 않을 때 시간을 절약해 줄 효율적인 디버깅 모범 사례를 공유했습니다.
모든 것을 재구축하지 않고 하드웨어 업그레이드
PL 파일을 변경하면 마치 "세상을 완전히 바꿔야 한다"고 생각하기 쉽지만, 실제로는 유연하게 대처할 수 있습니다. 커널에 노출되는 인터페이스 (주소, IRQ, 호환성), 루트 파일 시스템, 시스템 루트는 대개 그대로 유지됩니다. 따라서 PL 파일만 수정하면 문제없이 사용할 수 있습니다.
Linux는 필요에 따라 비트스트림을 로드하기 위해 FPGA 관리자 프레임워크( fpgautil) 또는 사용자 공간에서 PL을 프로그래밍할 수 있는 sysfs/configfs 인터페이스를 제공합니다. 이를 통해 전체 이미지를 다시 생성할 필요가 없어 논리 반복 속도가 향상됩니다.
하드웨어 변경으로 새로운 IP 주소가 도입되거나 범위/IRQ가 수정되는 경우, 디바이스 트리를 다시 빌드 하고 BOOT.BIN/이미지를 재생성해야 합니다. 하지만 이 경우에도 컴파일 과정에서 이미 완료된 작업을 반복하지 않도록 sstate 캐시를 사용하는 것이 좋습니다.
빌드 속도를 높이고 안정성을 확보하기 위한 팁
"모든 것을 다시 빌드"해야 하는 상황을 피하는 가장 좋은 방법은 캐싱과 체계적인 관리입니다. Yocto/PetaLinux용 sstate 미러 와 공유 다운로드 디렉토리를 사용하세요 . 이렇게 하면 변경되지 않은 패키지를 다시 컴파일하는 것을 방지할 수 있습니다. 이는 대규모 시스템이나 사내 환경에서 특히 효과적입니다.
재현성을 유지하세요: Vivado/Vitis/PetaLinux 버전을 고정 하고 패치를 문서화하세요. 가능하면 심각한 버그가 확인된 경우가 아니면 프로젝트 중간에 버전을 변경하지 마세요. 그리고 새 버전으로 넘어가기 전에 브랜치에서 테스트하세요.
QEMU는 여러분의 든든한 지원군입니다. SD 카드를 플래싱할 필요 없이 QEMU에서 이미지를 부팅하여 루트 파일 시스템과 커널이 예상대로 작동하는지 확인할 수 있습니다. 실제 하드웨어를 교체하는 것은 아니지만 부팅 시간을 절약해 줍니다.
위에서 설명한 모든 내용을 고려하면, 이제 그림은 더 이상 퍼즐처럼 보이지 않습니다. 완전한 레퍼런스 배포판(부트로더, 커널, 루트 파일 시스템 및 도구)을 사용하면 Vivado가 물리적 맵을 정의하고, Vitis는 앱 개발 및 디버깅 주기를 가속화합니다. 그 후, 디바이스 트리, UIO 또는 드라이버를 활용하는 것이 "Hello World" 예제와 하드웨어를 원활하게 활용하는 강력한 애플리케이션 사이의 차이를 만들어냅니다.
바이트와 기술 전반에 관한 세계에 대한 열정적인 작가입니다. 나는 글쓰기를 통해 내 지식을 공유하는 것을 좋아하며 이것이 바로 이 블로그에서 할 일이며 가젯, 소프트웨어, 하드웨어, 기술 동향 등에 관한 가장 흥미로운 모든 것을 보여 드리겠습니다. 제 목표는 여러분이 간단하고 재미있는 방식으로 디지털 세계를 탐색할 수 있도록 돕는 것입니다.