본 발표는 마이컴 환경에서 루비 언어를 구현한 Picoruby를 Espressif Systems의 ESP32 마이컴에 성공적으로 포팅하는 방법에 대한 심층적인 분석을 제공합니다. Picoruby는 라즈베리 파이 피코와 같은 소형 마이컴 보드에서 루비를 실행할 수 있도록 설계된 경량화된 루비 구현체입니다. ESP32는 저렴한 비용과 낮은 전력 소비를 특징으로 하며, Wi-Fi 및 Bluetooth 통신 기능을 내장하여 IoT(사물 인터넷) 프로젝트에 매우 적합한 마이컴 모듈입니다. 이번 포팅 작업에서는 RISC-V 아키텍처를 사용하는 M5Stack CoreS3와 Xtensa 아키텍처를 사용하는 ESP32-DevKitC 두 가지 상이한 장치를 활용하여, 다양한 마이컴 아키텍처에 대한 Picoruby의 포팅 가능성을 입증하고자 했습니다.
Picoruby를 ESP32로 포팅하는 과정은 크게 네 가지 단계로 진행됩니다. 첫 번째 단계는 Picoruby의 핵심 소스 코드를 빌드하여 libmrb.a
라이브러리 파일을 생성하는 것입니다. 이 과정에서는 C 언어의 컴파일, 링크, 아카이브 개념을 이해하고, ESP32에 특화된 크로스 컴파일러를 사용하는 것이 필수적입니다. ESP-IDF 개발 환경을 구축하고, 루비로 작성된 build_config
파일을 통해 컴파일러 및 링커 설정을 정의한 후, rake
명령어를 사용하여 libmrb.a
를 생성합니다. 두 번째 단계에서는 생성된 libmrb.a
파일을 ESP32용 R2P2 프로젝트에 링크하여 최종 실행 가능한 바이너리 파일을 만듭니다. ESP-IDF의 프로젝트 구조를 따르며, main
함수에서 Picoruby VM을 초기화하고 실행하는 코드를 작성하고, CMakeLists.txt
파일에 libmrb.a
의 링크 경로를 지정하여 idf.py build
명령어를 통해 R2P2_ESP32.bin
파일을 출력합니다. 세 번째 단계는 마이컴 환경에서 필수적인 표준 입출력 기능을 구현하는 것입니다. puts
메서드 호출 경로를 추적하여 Picoruby-machine
젬 내의 hal_write
함수가 핵심 역할을 함을 파악하고, build_config
에 해당 젬을 추가합니다. 특히, ports
디렉터리 아래에 ESP32
전용 디렉터리를 생성하여 hal_write
함수를 print_f
와 f_flush
기반으로 구현하여 시리얼 통신을 통한 입출력을 가능하게 합니다. 마지막 네 번째 단계는 Picoruby의 다양한 MRB Gems를 포팅하는 작업입니다. 목표로 설정한 ‘ESP32에서 셸을 실행하고 echo
명령어를 동작시키는 것’을 위해 필요한 젬들을 식별하고, 루비로만 구성된 젬이나 ports
디렉터리가 없는 젬은 추가 포팅 없이 사용하며, Picoruby-IO
및 Picoruby-console
과 같이 라즈베리 파이 피코용 코드를 재활용할 수 있는 젬은 활용합니다. Picoruby-filesystem-fat
과 같이 복잡한 젬의 경우, 초기에는 빈 함수를 정의하여 링크 오류를 회피하는 전략을 사용했습니다.
포팅 과정에서는 다양한 기술적 난관에 직면했습니다. 첫 번째는 ‘Watchdog Timer 오류’로, ESP32의 실시간 운영체제(RTOS)가 Picoruby VM의 독자적인 태스크 전환 메커니즘(TCB)을 단일 태스크의 장시간 점유로 오인하여 발생했습니다. 이는 Watchdog Timer를 비활성화하여 Picoruby VM에 태스크 전환을 위임함으로써 해결했습니다. 두 번째는 ‘require
미작동’ 문제였습니다. Picoruby-shell
과 Picoruby-require
젬이 빌드 시 동적으로 생성하는 C 언어 함수를 main
함수에서 호출하지 않아 발생했으며, 해당 함수를 명시적으로 호출하도록 수정하여 해결했습니다. 세 번째는 ‘스택 오버플로우’로, 복잡한 루비 코드를 실행할 때 기본 할당된 스택 메모리(3584바이트)가 부족하여 발생했습니다. SDKConfig.defaults
파일에서 스택 크기를 8KB로 증설하여 문제를 해결했습니다. 마지막으로 ‘CSI 명령어 미작동’ 문제는 R2P2가 터미널 에뮬레이터 상태 확인을 위해 사용하는 CSI 명령어가 초기 hal_write
구현의 버퍼링 및 n
바이트 무시 문제로 인해 정상적으로 처리되지 못하여 발생했습니다. for
루프를 통해 정확히 n
바이트를 출력하고 f_flush
를 사용하여 버퍼를 비우는 방식으로 수정하여 해결했습니다.
발표에서는 ESP32 개발 보드에 매트릭스 LED, 조이스틱, 압전 소자가 장착된 자작 기판을 연결하여 Picoruby의 기능을 시연했습니다. 셸에서 echo
명령어를 실행하고, IRB 환경에서 배열 및 문자열 조작을 수행했으며, pwd
, ls
와 같은 파일 시스템 명령어도 성공적으로 실행했습니다. 특히, Picoruby로 구현된 블록 깨기 게임을 통해 LED 디스플레이 제어(Picoruby-SPI
), 조이스틱 입력 처리(Picoruby-ADC
), 소리 출력(Picoruby-PWM
) 등 임베디드 시스템의 핵심 기능을 성공적으로 시연하여 Picoruby의 강력한 활용 가능성을 보여주었습니다.
본 세션은 Picoruby를 ESP32 마이컴에 포팅하는 전반적인 과정과 그 과정에서 발생할 수 있는 주요 기술적 난관 및 효과적인 해결책을 상세히 설명했습니다. 제시된 포팅 방법론은 ESP32뿐만 아니라 STM32, NRF52와 같은 다른 마이컴 플랫폼에도 충분히 응용될 수 있음을 강조하며, 이는 Picoruby의 확장성과 범용성을 시사합니다. 발표자는 ESP32에 대한 Picoruby 포팅 작업에 여전히 많은 기여 기회가 남아있음을 역설하며, 관심 있는 개발자들의 적극적인 참여를 독려했습니다. 모든 구현 상세 내용은 GitHub 리포지토리에서 확인할 수 있습니다.