*너무 오래;나는 Linux/임베디드 Linux 세계가 어떻게 작동하는지에 대한 개요를 얻고 싶습니다. 메인라인 Linux를 사용하여 처음부터 시작하고 이를 다른 프로세서와 주변 장치가 있는 마더보드에 컴파일/배포하려면 어떻게 해야 합니까?
현재 작동하는 방식은 다음과 같습니다.
모든 보드에서 Linux를 실행하는 단계:
- uBoot(내장형) 또는 GRUB(데스크탑/x86 SOM)용 소스 코드 받기
- 특정 시스템에 맞게 uBoot 또는 GRUB를 수정하고, 특정 칩을 초기화하고 시작 및 실행에 필요한 메모리 및 콘솔 인터페이스를 가져오는 코드를 작성합니다.
- 위에 작성된 코드를 구성하려면 uBoot/GRUB config.txt를 수정하세요.
- 이를 컴파일하고 보드에 배포하고, 부트로더 콘솔이 나타나고 상호 작용할 수 있는지 확인합니다.
- 커널 메인라인 소스 얻기
- "make config"를 사용하여 사용 가능한 드라이버 및 모듈을 선택합니다(이 시점에서 이러한 선택은 소스를 변경합니다. 이러한 설정이 저장되는 위치에 상관없이 더 이상 메인라인의 git clone과 일치하지 않습니다)(이를 소스 제어 .config 파일에서 추적) 향후 참고)
- Busybox와 같은 도구를 구하시거나 데스크탑을 대체하시겠습니까? 소스 디렉터리에 설치
- ucLibc 또는 기타 라이브러리를 가져와 소스 디렉터리에 설치합니다.
- 크로스 컴파일 툴체인을 사용하여 특정 칩에 대한 커널 소스 코드 컴파일
- 보드에 대한 장치 트리 파일 .dtb를 만듭니다(임베디드/데스크탑? 또는 데스크톱이 사용되지 않습니까?). 이렇게 하면 드라이버가 물리적 핀에 연결됩니다.
- Uboot/GRUB 및 TFTP/직렬 콘솔이나 메모리 카드를 사용하여 컴파일된 커널 이미지를 로드합니다.
- 드라이버 및 장치 트리 구성을 기반으로 직렬/SSH 등을 통해 셸 액세스 실행 및 확인
- 보드별 구성을 위해 uEnv.txt(내장형) 또는 mymyfile.txt(데스크톱)를 수정하시겠습니까? 이것은 본질적으로 커널 부팅 단계를 차단하거나 추가하는 스크립트입니까? 데스크탑과 동등한 것은 무엇입니까?
- apt-get 필수 패키지 및 드라이버
- 드라이버 및 애플리케이션 코드 작성 및 테스트(드라이버 수동 로드)
- 위에 구현된 하드웨어 및 드라이버를 설명하는 장치 트리 파일을 추가합니다(이 파일은 생성된 초기 BSP와 별개입니다).
- 이를 커널 이미지에 포함하려면 커널을 빌드하고 이러한 모든 소스 및 구성 파일 수정 사항(Linux 메인라인 추가/수정 사항)이 포함된 파일 구조를 폴더 구조에 포함합니다.
- Linux 메인라인과 모드용으로 별도의 폴더를 생성하고 모드를 세 번째 스테이징 폴더의 메인라인에 직접 복사할 수 있습니다. 이를 통해 추가된 모든 콘텐츠와 메인라인이 아닌 모드에 대한 별도의 소스 제어가 가능해집니다.
SSH를 통해 연결할 수 있는 기본 시스템을 얻을 수 있고 이 시점에서 모든 공통 구성 요소(비디오, USB, 마우스 등)에 대한 드라이버가 있는 경우 이 시점에서 거의 모든 작업을 수행할 수 있습니다(X11 서버 설치). , LXDE, 네트워크 대기)? 부트로더/BIOS에서 처리해야 하는 드라이버는 무엇이며, 커널 도메인에만 있는 드라이버는 무엇입니까?
커널 빌드를 구성하기 위한 Kconfig 파일이 있습니다. 이는 타당하며, 내가 본 커널 모듈 개발 문서는 이에 대해 꽤 잘 설명하는 것 같습니다.
런타임 구성과 로드해야 하는 장치를 처리하는 uEnv.txt 및 config.txt와 같은 파일도 있습니다. 그리고 장치 트리 blob은 어떤 장치를 로드해야 하는지도 결정합니까?
이 파일의 매직 스트링은 어떻게 커널에 연결되어 있으며 특정 보드의 메인라인에 이러한 수정이 이루어졌습니까? HDMI를 활성화해야 하는지 여부를 결정하려면 이를 읽어야 하며 이는 Linux 데스크톱 버전의 코드와 정확히 동일할 가능성이 없습니다.
드라이버가 메인라인에 진입한 후에도 여전히 메인라인과 독립적으로 개발됩니까? 예를 들어, 제가 사용해 온 몇 가지 드라이버가 있지만 이제 메인라인에 포함되었다는 메모가 있습니다. 이는 더 이상 직접 다운로드할 수 없다는 의미입니까? 내가 수행한 단계에서는 내 보드의 헤더와 소스 코드를 다운로드한 다음 컴파일하고 설치했습니다. 메인라인에 있다면 지금 거기에서 추출해야 합니까?
배경 및 구체적인 아이디어
저는 마이크로 컨트롤러 및 Windows 개발 경험이 있는 EE이지만 Linux 경험은 많지 않습니다. 내 질문의 틀은 "이 임의의(Linux 컴파일러 사용 가능) 프로세서와 이러한 주변 장치를 사용하기 시작하면 Linux 버전을 어떻게 구축합니까(및 내 옵션은 무엇입니까)"입니다.
부트로더:
RPI2 및 BBB(Beaglebone Black)에 대한 구체적인 문서와 방법을 찾을 수 있었지만 부트로더와 같은 고급 주제에 들어가면 무슨 일이 일어나고 있는지 모호하게 설명하는 스크랩만 있을 뿐입니다. 예를 들어, RPI2에는 3단계 부트로더(읽어보니 완전히 uBoot 기반으로 들리지는 않음)가 있는 반면, BBB에는 좀 더 "전통적인" uBoot 기반 부트로더가 있습니다. 새로운 BBx15에는 이제 부팅할 위치를 선택할 수 있는 점퍼가 있습니다.
데스크탑 시스템은 GRUB(IIRC)를 사용하고, 임베디드 시스템은 일반적으로 uBoot를 사용합니다. RPI는 부팅 중에 GPU를 사용하고 별도의 ROM에서 첫 번째 단계 부트로더를 읽는다는 내용을 읽었습니다. 이것이 이용 가능한 모든 정보입니다. 자신만의 보드 버전을 가동하고 싶다면(토론 목적으로는 실용적이지 않음) uBoot 외에 또 어떤 일이 벌어지고 있을까요? 점퍼 부팅 선택을 허용하기 위해 BBx15용 uBoot에 추가 수정 사항이 없습니까?
Linux는 부팅 단계에 대해 알고 있습니까? 아니면 일단 실행되면 이를 잊어버리나요? BBB는 uBoot를 사용하여 eMMC에서 RAM으로 이미지를 로드하고, RPI2는 3단계 부트로더를 사용합니다. BBB는 ARM 프로세서를 사용하지만 RPI2는 GPU를 사용하는 것 같습니다. 전원을 켜면 ARM 프로세서가 실행되기 시작합니다. 이러한 로딩 프로세스를 준비하려면 무엇을 수정해야 합니까? GPU는 ROM 코드가 완료될 때까지 ARM을 재설정 상태로 유지합니까? GPU가 부팅 프로세스의 일부이기 때문에 GPU가 실행하는 코드가 uBoot 코드에서 제거되고 GPU가 없는 다른 시스템이 uBoot 코드에서 실행되어야 한다는 의미입니까? 이 모든 것이 나에게 무엇을 의미합니까? 두 번째 단계 또는 세 번째 단계 부트로더를 수정하면 GPU와 완전히 독립적으로 Linux를 실행할 수 있습니다(커널이 GPU 툴체인으로 컴파일된 경우).
세 번째 단계의 부트로더와 config.txt는 실제로 uBoot인가요?
사용 중인 보드에 대한 헤더입니다. 이것은 드라이버가 포함된 메인라인의 헤더입니까, 아니면 다른 것이 있습니까? 이미 달리고 있다면 '제목'이 바로 메인라인 제목인가요?
임베디드 마이크로컨트롤러 개발에는 HAL 레이어를 사용하는 데 익숙합니다. HAL에는 주변 장치를 설정한 다음 드라이버가 이러한 리소스를 가리키도록 할 수 있는 기능 스텁이 있습니다. 보드 지원 패키지에는 일반적으로 관련 보드에 대해 이미 코딩된 이러한 HAL 스텁이 있습니다. Linux 개발과 몇 가지 유사점이 있다고 확신하지만 차이점이 어디에 있는지 잘 모르겠습니다.
Buildroot 및 Yocto와 같은 패키지가 있습니다. 포함할 ARM 프로세서와 드라이버를 자동으로 선택하는 인터페이스를 갖춘 Linux 메인라인인가요?
답변1
라우터 하드웨어에 대한 나의 작은 경험을 통해 나는 이것이 한 가지 일을 하기 위해 선택되는 어리석고 작은 하드웨어라고 말할 수 있습니다.
하드웨어 수준에서는 간단합니다.
U-Boot는 부트로더일 뿐만 아니라 PC 용어로는 BIOS이기도 합니다. 그래서 이것은 아니다오직부트로더이며 모든 하드웨어도 초기화합니다. 시작 시 CPU는 이를 직접(예: FLASH에서) 실행하고 다음에 수행할 작업을 결정하지만 일반적으로 CPU는 메모리에 재배치됩니다. 그런 다음 필요한 작업을 수행합니다. 즉, 플래시 메모리에서 구성을 읽은 다음 지정된 주소에 이미지를 로드하고 그곳으로 제어를 전송합니다. 특별한 것은 없지만 알아두는 것이 중요합니다.
U-Boot(라우터 하드웨어에 내장되어 있음)는 루트 파일 시스템에 전혀 액세스하지 않습니다. 대신 전체 커널 이미지를 위한 전용 공간(보통 압축됨)이 있습니다. 따라서 적어도 라우터에는 /boot/vmlinuz 파일이 없습니다.
RPI는 자체 독점 부팅 시퀀스를 사용합니다. 그들은 사용자가 SD 플래시 메모리에 넣을 수 있는 비공개 소스 바이너리를 가지고 있습니다. 첫 번째 단계 초기화 코드는 CPU나 보드 어딘가에 하드코딩되어 있습니다. GPU 후에 ARM 코어를 시작하고 GPU에 대한 전체 코드가 완료됩니다. 더 많은 정보를 원하시면 찾으셨을 수도 있지만, 그렇지 않은 경우:https://raspberrypi.stackexchange.com/questions/10489/how-does-raspberry-pi-boot
따라서 라우터를 사용하여 몇 가지 재미있는 작업을 수행하고 소스에서 완전히 소규모 서버로 다시 구축했으므로 나만의 빌드 순서를 배치할 수 있습니다.
- 플랫폼용 u-boot 획득 및 구축
- 리눅스 커널 빌드
- 사용자 공간 구축(커널과 사용자 공간은 일반적으로 플래시에서도 분리되어 있음)
- 프로그래머의 플래시에 u-boot 굽기
- 보드에 플래시 납땜을 납땜합니다.
- UART를 통해 개발 보드에 연결
- 이를 시작하고 u-boot가 모든 하드웨어를 올바르게 초기화하는지 확인하십시오.
- 온보드 플래시 메모리에 기록되는 tftp 커널
- tftp rootfs, 온보드 플래시 메모리에 쓰기
- 재설정하고 모든 것이 정상인지 확인하세요.
- rootfs 미세 조정: 권한 설정, tftp를 통해 기본 구성 미리 로드
- 전체 이미지를 덤프하고 여러 장치에서 새로 고침
Linux 커널은 마더보드를 지원할 수도 있고 지원하지 않을 수도 있습니다. 확인 부탁합니다. 예를 들어, 최신 커널을 가져와서 라우터용으로 구축할 수는 없습니다. RPi도 마찬가지입니다. 자체 커널 트리가 있습니다. 이는 Linux 커널이 직접적으로 지원하는 소수의 플랫폼(일반적으로 범용)이 포함된 임베디드 환경에서 자주 발생합니다. 이에 대비하십시오.
사용자 공간의 경우, 필요한 것과 남은 공간 사이에서 요구 사항의 균형을 맞추면서 원하는 것을 선택할 수 있습니다. 일반적으로 삽입에서는 무엇이든 압축하거나 원하지 않는 콘텐츠를 제거하거나 둘 다를 수행합니다.
이것이 깨달음을 얻기를 바랍니다. 더 궁금한 점이 있으시면 언제든지 댓글을 남겨주세요! :-)