RP2040에서 RTOS로의 전환
(blog.brixit.nl)- Raspberry Pi Pico 기반 비디오 장비 컨트롤러가 동시 작업을 많이 요구하면서, pico-sdk와 듀얼코어 분리만으로는 소프트웨어 구조가 감당하기 어려워짐
- 컨트롤러는 RS-485 VISCA, Ethernet, 9개 RGB 버튼, 조이스틱, 디스플레이를 함께 다루며 DHCP, mDNS, UDP 기반 ATEM 프로토콜 처리까지 필요함
- FreeRTOS는 스케줄러와 태스크 간 통신으로 일부 구현이 가능했지만, printf 중단 문제와 하드웨어 추상화 부족 때문에 디버깅과 코드 재사용이 어려웠음
- Apache NuttX는 셸, 파일시스템,
/dev/i2c0같은 장치 추상화와 Kconfig 설정을 제공했지만, I2C 문제는 이후 설정 실수로 정정돼 당시 평가 상당 부분이 무효일 수 있음 - Zephyr는 5GB 규모 저장소와 SDK, 보드 정의, 빌드 복잡성에 막혔고, 최종적으로 기존 환경에 가장 단순히 붙일 수 있는 FreeRTOS를 계속 시도하는 쪽으로 기울어짐
왜 RTOS가 필요해졌나
- 여러 소형 마이크로컨트롤러 프로젝트가 Raspberry Pi Pico 보드를 중심으로 만들어지고 있음
- Pico는 적절한 SDK, 저렴한 하드웨어, gdb/openocd 디버깅 지원 덕분에 IDE 통합이 쉬움
- 현재 프로젝트는 여러 비디오 장비를 제어하는 하드웨어 컨트롤러임
- 제어 대상은 모터가 달린 PTZ 카메라 2대, 고정 카메라 1대, 연결된 비디오 스위칭 장비임
- 기존 PTZ 카메라 제어기는 Marshall VS-PTC-200과 비슷하게 생긴 무명 패널임
- 몇 년 전 가격이 €650였지만, 버튼 감촉과 아날로그 조이스틱 품질이 좋지 않음
- 많은 버튼이 현재 사용 중인 카메라에서는 동작하지 않으며, 보안 카메라에 최적화된 것으로 보임
- 카메라와는 RS-485 버스로 연결됨
- ATEM 비디오 스위처 제어는 현재 컴퓨터의 소프트웨어 패널로만 수행됨
- Blackmagic Design의 하드웨어 패널은 매우 비쌈
컨트롤러 하드웨어 구성
- 최소 설계는 9개 버튼, 조이스틱, 사용자 인터페이스용 디스플레이로 잡힘
- 1년 동안 여러 차례 하드웨어 설계를 반복한 뒤 PCB를 확보함
- 9개 RGB 버튼
- Marshall 복제 패널에도 들어 있던 $10 조이스틱
- PTZ 카메라와 RS-485로 통신하기 위한 TP8485E
- Ethernet으로 비디오 스위처와 통신하기 위한 Wiznet W5500 모듈
- 보드 수정 끝에 하드웨어 부품은 모두 동작하게 됐지만, 더 어려운 부분은 소프트웨어였음
pico-sdk만으로 버거워진 소프트웨어
- 기존 RP2040 프로젝트처럼 cmake 프로젝트에서 pico-sdk를 가져오는 방식으로 시작함
- 동작 가능한 수준을 만들기 위해 Pico의 두 번째 코어를 Wiznet 모듈 처리에 할당하고, 첫 번째 코어는 사용자 인터페이스 I/O를 처리하게 함
- LED 점멸과 두 번째 코어에서 실행되는 DHCP 클라이언트 구현까지는 가능했음
- 나머지 시스템 구현은 훨씬 복잡해짐
- 동시에 처리해야 할 작업이 빠르게 늘어남
- 디스플레이에 어느 정도 부드러운 사용자 인터페이스 그리기
- RS-485 인터페이스로 VISCA 명령 보내기
- 버튼 입력에 반응하기
- 여러 연결을 포함한 네트워크 스택 유지하기
- 네트워크 쪽은 별도 백그라운드 작업을 요구함
- 표준에 맞는 DHCP 지원은 만료 시간을 추적하고, 임대 상태 유지를 위해 DHCP 서버와 가끔 통신해야 함
- mDNS는 ATEM 비디오 스위처 IP 자동 발견에 필요하며, 컨트롤 패널 존재도 알릴 수 있으면 좋음
- ATEM 프로토콜은 단순하지만, Wiznet 모듈 버퍼 크기를 넘는 데이터를 받을 때가 있고 UDP 데이터그램 전송이 멈추면 연결 해제 타임아웃이 매우 짧음
- 이런 조건에서는 직접 루프를 더 쌓기보다 RTOS로 작업을 나누는 편이 더 적절해 보임
FreeRTOS: 단순하지만 추상화가 부족함
- FreeRTOS는 pico-sdk 안에 기술적으로 포함돼 있지만, 튜토리얼들은 새 복사본을 내려받는 방식을 사용해 그대로 따름
- 검토한 RTOS 중 가장 단순해 보였고, 주로 스케줄러와 태스크 간 통신을 제공함
xTaskCreate로 태스크를 만들고vTaskStartScheduler로 스케줄러를 시작하는 구조임- 큐를 사용해 버튼 상태를 LED 태스크로 전달하는 형태의 IPC를 사용할 수 있음
- 며칠간 사용한 결과, 코드베이스는 아직 실제 기능이 적은데도 여러 태스크로 나뉨
buttonsTask: I2C GPIO 확장기를 폴링해 버튼 입력을 확인하고 버튼 큐에 메시지를 넣음ledTask:ledQueue메시지로 특정 버튼의 RGB 색상을 설정함mainTask: 버튼 입력에 따라 프로젝트 상태를 갱신하는 메인 루프를 실행함networkTask: Wiznet 모듈과 통신함dhcpTask: 네트워크 케이블 연결 시networkTask가 생성함mdnsTask: IP 주소 획득 뒤dhcpTask가 생성함atemTask: mDNS가 ATEM 장치 응답을 받으면 생성함viscaTask: 아직 아무것도 하지 않지만 RS-485 포트로 데이터를 보내야 함
- 하드웨어가 아직 네트워크에 나타나는 것 외에는 아무 동작도 하지 않는데도 태스크 수가 많아짐
- 가장 불편한 문제는 printf가 매번 멈춤을 일으킨다는 점임
- gdb 디버거는 동작하지만, DHCP 트래픽을 출력해 확인하는 방식에는 적합하지 않음
- FreeRTOS는 하드웨어 추상화를 제공하지 않아, 여러 칩과 통신하기 위해 작성한 코드를 쉽게 재사용하기 어려움
- 이후 깨끗한 FreeRTOS 프로젝트를 새로 만들고 기능을 옮기려 했지만, 시리얼 출력 없이 눈먼 디버깅을 해야 하는 불편함 때문에 다른 선택지를 살펴봄
Apache NuttX: Unix식 구조와 설정 실수
- Apache NuttX는 일반 운영체제에 더 가까워 보이며, 마이크로컨트롤러를 Unix 시스템처럼 다룸
- 튜토리얼은 pico-sdk를 가져오고 환경 변수를 설정하라고 안내함
- 이미
/usr/share에 SDK가 있고 환경 변수도 있었지만, NuttX가 pico-sdk의version.h파일을 덮어쓰려 하면서 권한 문제로 빌드가 실패함
- 이미
- 최소 NuttX 펌웨어를 빌드한 뒤 시리얼 포트에 연결하자 실제 셸이 나타남
uptime,uname,uname -a같은 명령이 동작함- 표시된 버전은
NuttX 12.5.1이며 대상은arm raspberrypi-pico임
- Unix 방식을 따르기 때문에 애플리케이션을 작성해 부팅 시 자동 실행할 수 있을 것처럼 보임
- 파일시스템이 있고 하드웨어는
/dev/i2c0,/dev/adc0같은 추상화로 노출됨
- 파일시스템이 있고 하드웨어는
- 마음에 들었던 부분은 menuconfig/Kconfig 기반 구성임
- Linux 개발에서 익숙한 방식임
- 실제 하드웨어 드라이버 시스템이 있고, 버튼에 사용한 GPIO 확장기 칩 드라이버도 이미 존재함
- RP2040 핀 mux 설정도 menuconfig에서 지정할 수 있어 핀 번호 상수를 따로 유지하거나 I2C 버스 초기화 코드를 많이 작성하지 않아도 됨
- I2C 테스트 유틸리티도 펌웨어에 포함할 수 있음
- 처음에는 I2C 기본 동작이 안 되는 것처럼 보였음
- 이후 업데이트에서 실제로는 잘 동작했고, 설정 실수로 I2C 버스가 깨졌다고 정정됨
- 해당 NuttX 섹션의 나머지 평가는 대부분 무효일 가능성이 있다고 명시됨
- 당시에는 GPIO 버튼이 GPIO 확장기 뒤에 있다는 사실을 NuttX에 어떻게 알려야 하는지, GPIO 확장기를 I2C 버스와 어떻게 연결해야 하는지도 파악하지 못함
configure.sh실패 후 저장소가 일관성 없는 상태가 되어 NuttX 저장소를 여러 번 다시 클론해야 했음distclean도 같은 이유로 제대로 동작하지 않는 상황이 있었음
- Unix-like 접근은 처음에는 좋아 보였지만, 마이크로컨트롤러에서 가짜 파일시스템 경로를 다루고 싶지는 않음
- 프로덕션 시스템에 셸도 필요 없고, 코드만 실행되면 됨
Zephyr: 큰 SDK와 보드 정의 장벽
- 다음 선택지는 Zephyr였고, 프로젝트 설정을 위한 Python 유틸리티를 제공함
- 첫 단계에서 약 5GB의 Git 저장소를 가져옴
- 여기에는 많은 칩용 HAL 라이브러리가 포함됨
- 사용자 전역 cmake 설정에도 영향을 줌
- 튜토리얼은 Zephyr SDK 설치를 요구함
- Zephyr SDK에는 지원 아키텍처별 툴체인, 컴파일러, 어셈블러, 링커, 빌드 도구가 포함됨
- QEMU와 OpenOCD 같은 호스트 도구도 포함됨
- 이미 여러 ARM 툴체인이 있으므로 모든 아키텍처용 컴파일러를 빌드하거나 미리 빌드된 것을 가져오고 싶지 않았음
- Zephyr SDK 없이 빌드하기 위해 크로스 컴파일 옵션을 설정함
ZEPHYR_TOOLCHAIN_VARIANT=cross-compileCROSS_COMPILE=/usr/bin/arm-none-eabi-west build -p always -b sparkfun_pro_micro_rp2040 samples/basic/blinky
- Raspberry Pi Pico는 실제로 지원되지 않고, 같은 SoC를 쓰는 다른 보드만 지원됨
- 같은 SoC라 실질적으로 비슷한 보드라고 보고 진행함
- 곧바로
blinky데모가 빌드되지 않는 문제가 발생함- 데모는 깜박일 대상인
led0정의를 요구함 - Sparkfun Pro Micro RP2040에는 단순 GPIO LED가 아니라 WS2812B 주소 지정 LED가 있음
- 데모는 깜박일 대상인
- 커스텀 보드 매뉴얼을 따라 다른 보드 정의를 복사하는 방식으로 진행했지만, 빌드 오류와 경고를 고친 뒤에도 대상 보드 빌드에 성공하지 못함
결국 다시 FreeRTOS로
- 세 RTOS 중 실제 애플리케이션 일부를 빌드한 것은 FreeRTOS뿐임
- printf 문제는 온라인 지침처럼 다른 printf 구현으로 교체하고, 필요한 곳에서 다른 함수를 호출하는 방식으로 해결해야 할 가능성이 있음
- 앞으로는 FreeRTOS를 계속 시도할 계획임
- 다른 RTOS처럼 개발 환경을 RTOS에 맞추기보다, 기존 환경에 비교적 단순하게 통합할 수 있는 유일한 선택지였기 때문임
댓글과 토론
Hacker News 의견들
-
이 글쓴이는 RTOS가 Arduino 환경과 같거나, 대충 만져보며 돌아가길 기대해도 되는 대상으로 본 듯함. 대부분은 그렇지 않음
요즘 Arduino 상당수는 내부에 mbed나 FreeRTOS가 깔려 있고 이를 노출하는 방법도 있으니, 글쓴이 스타일에는 그쪽이 더 나았을 수 있음
Zephyr는 쓰기 쉽고 CLion 지원도 좋지만, 도구 체인을 설치하지 않고도 전부 동작하길 기대할 수는 없음. Pi Pico도 확실히 지원하며, 직접 써봤을 때 문제 없었음
간단히 정리하면 FreeRTOS는 거의 모든 곳에서 지원되지만 드라이버는 대체로 SoC/장치별이라 번거롭고, API도 친절하진 않지만 익숙해질 수 있음. Bluetooth를 쓰려면 스택을 직접 찾아야 함
Zephyr는 실제 하드웨어 추상화를 지원하고 대부분의 SoC를 지원하지만, 보드 작업을 조금 해야 할 수 있음. Bluetooth 스택은 제공되며 HCI 지원을 약간 추가해야 할 수 있음
NuttX는 지원이 훌륭하진 않지만, 동작하게 만들 수 있다면 꽤 멋진 선택지임. 아직 업계 지원은 강하지 않음. mbed도 있지만 여기서는 생략함
실제 RTOS 쪽에서는 보통 SoC 벤더가 지원하는 것을 고름. Nordic이면 Zephyr, NXP면 FreeRTOS 같은 식이고, 그래야 지원을 잘 받을 수 있음- 빠르게 묻자면, 프로토타이핑 보드용으로 개발하는 건지 아니면 OEM 장치 펌웨어를 만드는 건지 궁금함
OEM 장치용 펌웨어 프로젝트에서 개발자들이 Zephyr로 고생하지 않은 경우를 한 번도 못 봤음. 출시 제품의 실제 펌웨어를 만드는 개발자 중 Zephyr의 하드웨어 추상화가 도움이 된다고 생각하는 사람도 아직 못 만났음
그런 사람이 없다는 뜻은 아니지만, 지난 5년쯤 동안은 마주친 적이 없음 - “Zephyr는 쓰기 쉽다”는 내 경험과는 다름
내가 보기엔 Zephyr는 마케팅 자료가 아주 예쁨. 하지만 그 화려함 뒤에는 과도한 비대함, 매우 느린 컴파일, 시작하기 어려운 환경이 있음 - 왜 mbed는 생략함? 그게 “최고”인 부분인데
- 빠르게 묻자면, 프로토타이핑 보드용으로 개발하는 건지 아니면 OEM 장치 펌웨어를 만드는 건지 궁금함
-
전통적인 UNIX 방식처럼 도구 체인을 시스템 전체에 설치하는 건 고통스럽고, 솔직히 그다지 똑똑한 접근도 아님
혼자 잘 돌아가면 좋지만, 여러 개발자가 여러 대상이 다른 프로젝트를 다루면 빌드와 설정 문제를 파악하는 데 시간을 많이 쓰게 됨
도구에 Python을 계속 쓰는 것도 도움이 안 됨. 자체 버전 문제를 가져오고 개발자 컴퓨터마다 다르게 동작하는 언어를 왜 굳이 쓰려는지 모르겠음
임베디드 개발을 취미와 직업으로 10년쯤 해왔는데, 프로젝트에서 모두의 환경을 같게 맞추느라 일주일을 쓰고도 그게 문제라고 보지 않는 태도가 이해되지 않음
이건 실제 문제고, 짜증 나며, 시간을 낭비하고, 불필요함
도구는 정적 링크된 바이너리여야 함. Rust, Go, C, C++ 무엇으로 작성하든 상관없지만, 임시방편 개발보다 컴퓨터에 설치된 것과 무관하게 같은 방식으로 동작한다고 믿을 수 있는 견고한 도구를 우선했으면 함
Python은 그렇게 해주지 못하고, 이 문제를 더 진지하게 받아들이기보다 화내고 방어적으로 구는 것도 도움이 안 됨
그래도 PlatformIO 같은 것은 올바른 방향임. Python 프로젝트라는 점은 알고 있고 가끔 문제가 되지만, 다른 도구보다 덜한 편이며 발상은 맞음
도구 체인, SDK, 라이브러리는 관리되어야 하고, 프로젝트 설정은 단순해야 하며, 빌드는 어디서나 언제나 재현 가능해야 함
임베디드 업계가 공통된 구조화 노력의 가치에 더 눈떴으면 좋겠음. 주요 MCU 제조사에서 일하는 사람들을 많이 아는데, 대체로 자기 당장의 문제 해결에 바빠 개발자 요구에는 시야가 좁아 보여 늘 실망스럽다- 이제는 Python 도구가 들어간 것은 쓰지 않음. 첫 시도에 잘 동작하는 경우가 너무 드묾
RP2040에서 동작하는 키보드 프로젝트가 있고 펌웨어는 Rust로 되어 있음. 저장소만 있고 Rust 도구 체인이 없는 상태에서 플래시하는 절차는 다음과 같음
(rustup 설치)
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ rustup target add thumbv6m-none-eabi
$ cargo install elf2uf2-rs
* 키보드를 부트로더 모드로 전환 *
$ cargo run --release
여기서는 rustup과 Cargo가 도구 체인 관리와 빌드를 대부분 처리하고, 이 둘은 정말 훌륭함. Python 프로젝트는 근처에도 못 감 - Docker나 다른 컨테이너 도구가 좋은 후보가 되지 않을까? 도구 체인을 로컬에 설치하는 대신, 필요한 정확한 도구 체인이 들어간 이미지 기반 컨테이너에서 빌드하면 됨
- Android 앱 개발을 하다 보니 이 부분에서는 눈이 높아졌음
명령 하나만 실행하면 로컬이든 CI든 같은 버전의 빌드 도구와 라이브러리로 완전히 같은 방식으로 설정되고 동작함
그래서 다시 CMake와 Make를 다루며 라이브러리를 설치하려고 씨름할 때마다 괴로움.compile 'library-name-here'같은 방식과는 너무 다름 - 사람들이 Python을 도구 언어로서의 장점 때문에 고르는 건 아니라고 봄. 그 관점에서는 훌륭하지 않고, 정적 링크 바이너리가 더 나음
대신 라이브러리 생태계 때문에 고르는 것임. 데이터 분석, 시각화, 과학 계산에서는 다른 언어에 견줄 만한 선택지가 없음
이런 것들은 처음부터 다시 구현하고 싶지 않은 영역임. 수치 안정성 같은 부분에서 버그를 넣기 쉬워서, 99%는 맞는 결과를 내다가 1%는 그럴듯하지만 완전히 틀린 결과를 낼 수 있음 - 2011년에 C#으로 작성한 명령줄 도구가 있는데 아직도 그냥 잘 동작함
- 이제는 Python 도구가 들어간 것은 쓰지 않음. 첫 시도에 잘 동작하는 경우가 너무 드묾
-
개인적으로 RP2040 프로젝트를 Rust와 Embassy로 옮기기 시작했음
Rust는 적응이 좀 필요했지만 꽤 마음에 듦. RTOS는 아니지만, RTOS가 필요하게 만드는 많은 요구를 충족해 줌- 이 길로 간다면 처음에는 rp2040-hal 크레이트로 시작하고, 여러 작업을 관리하는 데 고통이 생기면 Embassy나 RTIC를 살펴보는 걸 추천함
Rust와 Cargo는 RP2040, 또는 STM32 빌드와 플래시의 고통을 없애 줌. 지금까지 써본 임베디드 환경 중 가장 쾌적했음 - 나도 비슷하게 봄. 사람들이 RTOS로 가는 이유는 대체로 라이브러리와 의존성 관리인데, Rust, Cargo, crates.io를 쓰면 그런 것들이 거의 기본으로 따라옴
많은 애플리케이션은 MPU를 쓰지 않음. 여기에 Rust의 메모리 안전성과 RTOS 없이 줄어드는 펌웨어 전체 복잡도를 고려해 보면 됨 - 전적으로 동의함. 전반적으로 임베디드 Rust는 내게 훌륭한 경험이었음
Embassy executor의 비동기도 아주 잘 동작해서, RTOS 설계 과정의 고통을 많이 덜어 줌 - 100% 동의함. Embassy는 훌륭하고 정말 마음에 듦
RP2040용 PIO 인터페이스까지 추가하면 코드가 아주 단순하고 아름다워지며, 다른 프로세서로는 달성하기 어려운 구성이 됨
- 이 길로 간다면 처음에는 rp2040-hal 크레이트로 시작하고, 여러 작업을 관리하는 데 고통이 생기면 Embassy나 RTIC를 살펴보는 걸 추천함
-
Pi Pico는 Zephyr에서 100% 지원됨. https://github.com/zephyrproject-rtos/zephyr/tree/main/board... 문서를 확인하지 않은 걸까? https://docs.zephyrproject.org/latest/boards/raspberrypi/rpi...
추가로, 많은 상황에서는 하나의 “main” Zephyr 설치를 쓰는 게 아니라 프로젝트의west.yml에 필요한 외부 모듈을 포함하는 방식이 의도된 사용법임
여러 프로젝트가 같은 Zephyr 설치를 공유하는 건 별도 논의지만, 가능한 모든 도구 체인과 HAL을 설치하는 것만이 유일한 방법은 아님- Zephyr SDK를 설치하고 싶지 않았다면 GNU Arm Embedded 도구 체인으로 빌드하는 것도 사소해야 할 텐데, 왜 안 됐는지 잘 모르겠음
-
요즘은 오픈 소스인 ThreadX가 언급되지 않았음
https://github.com/eclipse-threadx/threadx/- RIOT도 다른 대안이 될 수 있음
https://github.com/RIOT-OS/RIOT - 이런 목록에서 ThreadX가 왜 더 자주 언급되지 않는지 모르겠음. 비교적 사용하고 이해하기가 단순함
- RIOT도 다른 대안이 될 수 있음
-
RTOS 선택지 비교가 좋았음
개인적으로는 MicroPython이 더 쉬운 길이라고 봄.async/await기반 협력적 다중 작업이 나에게는 잘 맞음
최근 프로젝트에서는 스테퍼 모터 6개, 여러 LED, 버튼 스캔을 모두 처리했는데 사용자에게는 실시간처럼 보였음- 이런 미니 컴퓨터들은 8비트와 16비트 가정용 컴퓨터보다 훨씬 강력해서, MicroPython은 초기 시스템의 BASIC 사용 사례를 충분히 대체할 수 있음
당시 우리가 사용할 수 있던 자원이 얼마나 적었는지, 그런데도 고수준 언어를 썼다는 사실을 아직도 많은 사람이 제대로 이해하지 못하는 게 놀라움 - PTZ 컨트롤러처럼 강한 실시간 요구가 없고 애플리케이션 메모리 사용량이 적은 경우라면 MicroPython은 생산적인 선택으로 보임
ESP32에서 MicroPython을 써봤을 때, 인터럽트 핸들러를 Python답게 지원하는 점이 마음에 들었음. RP2040도 비슷하게 지원된다고 봄 - 이 경우 스테퍼 모터 신호는 Python 코드가 직접 만드는 게 아니라 ESP32의 RMT 같은 하드웨어 주변장치가 생성한다고 봐야 하지 않을까?
내 현미경에서는 거의 실시간에 가까운 스테퍼 모터 제어를 FluidNC 보드가 담당하고, 나는 가벼운 직렬 프로토콜로 제어함
다만 https://pypi.org/project/micropython-stepper/를 보고 있는데, 이건 하드웨어 타이머와 Python 코드를 쓰는 것처럼 보임 - 맞음, 이건 간단한 MicroPython 프로젝트가 될 것 같음
- 이런 미니 컴퓨터들은 8비트와 16비트 가정용 컴퓨터보다 훨씬 강력해서, MicroPython은 초기 시스템의 BASIC 사용 사례를 충분히 대체할 수 있음
-
제대로 된 프로젝트에서 Hubris를 한번 써보고 싶음 (https://hubris.oxide.computer/reference/)
아키텍처 접근 방식은 내가 임베디드 영역에서 지향하는 것과 꽤 잘 맞음. 다만 나는 C로 더 고통스럽게 하고 있음
호스팅 환경에서 Erlang/Elixir로 하는 방식과도 크게 다르지 않음
메모리가 더 제한되어 여러 스택을 감당할 수 없는 상황에서는 Embassy가 좋은 선택으로 보임 -
새 임베디드 프로젝트는 언제나, 정말 언제나, 가상 머신에서 시작해야 함. 같은 시스템에 도구를 섞지 말아야 함
내 상용 프로젝트에서 품질 문제의 1순위 원인이 바로 이것이었음
새 칩셋, 새 벤더로 프로젝트를 시작한다면 새 VM을 만들고, 그 VM에 벤더 도구만 설치한 뒤 거기서 빌드해야 함
실험적인 개발은 자기 로컬 비 VM 머신에서 해도 괜찮음. 하지만 릴리스는 반드시 VM에서 해야 함. 그리고 제발 VM과 개발 워크스테이션을 동기화해 둬야 함
현재 원 개발자가 휴가 중인 상태에서 반드시 고쳐야 하는 펌웨어 빌드를 처리하느라 엄청난 고통을 겪고 있음. 아무도 그 사람 워크스테이션에 접근할 수 없고, 준비된 VM은 6개월이나 뒤처져 있으며, 고객은 왜 지구상에서 단 한 명의 특별한 프로그래머만 할 수 있는 일을 위해 팀 전체 비용을 내야 하는지 묻고 있음- 더 낫게는 컨테이너를 쓰면 됨. 몇 년째 가상 머신을 쓰지 않았고, 전혀 그립지 않음
- Nix와 flakes가 재현 가능한 빌드 환경에 도움이 될까?
- 그 고통이 느껴짐
릴리스는 CI 시스템이 빌드해야 한다고 봄. git에서 릴리스 태그를 달면 테스트 통과 후 바이너리가 나오는 식이어야 함
-
FreeRTOS를 고르면 크게 틀리기 어려움. 이 시점에서는 사실상 업계 표준임
printf()가 동작하게 만드는 문제에는 어떤 해법이 있을까?
꽤 골치 아파 보임
-
원 글과 비슷한 경험이 있었음
그래서 간단한 그린 스레드 타이머를 직접 만들었음
진짜 커널처럼 실제 프로세스 관리를 지원하지도 않고 어떤 보장도 하지 않지만, 베어메탈 스케줄링보다 더 멀리 가게 해줬고 RTOS라는 난장판을 피하게 해줬음
C에서 선택적 컨텍스트 구조체를 받는 JavaScript 타이머 콜백 같은 것으로 보면 됨
다양한 센서를 질의하고, 들어오는 신호를 처리하고, 제어 결정을 내리고, 명령을 내보내는 일을 각각 다른 주기로 처리할 수 있었음
이런 느리고 추상적인 아키텍처로 삶을 망치기 전에, 먼저 이런 방식을 시도해 보길 강력히 추천함