콘텐츠로 이동

펌웨어 플래싱

Pico(UF2), Arduino(arduino-cli), Nucleo(probe-rs) 펌웨어 플래싱 방법과 보드에서 코드를 읽고 쓰고 실행하는 방법을 설명합니다.

이 페이지에서는 Revka가 마이크로컨트롤러에 펌웨어를 올리는 방법과, 보드가 온라인 상태가 된 이후 에이전트가 코드를 읽고 쓰고 실행하는 방법을 설명합니다. 보드 계열마다 플래싱 툴체인이 다릅니다. Raspberry Pi Pico는 대용량 저장소 드라이브를 통해 UF2를 플래시하고, Arduino Uno는 arduino-cli를, STM32 Nucleo는 내장 ST-Link를 통해 probe-rs를 사용합니다. Arduino Uno Q는 별도의 방식으로, 펌웨어를 플래시하는 대신 Bridge 앱을 실행합니다.

모든 하드웨어 기능은 빌드 시 hardware Cargo 피처가 필요합니다:

Terminal window
cargo build --release --features hardware

보드를 플래시한 후에는 GPIO 도구가 해당 보드에 접근할 수 있도록 등록해야 합니다. GPIO 도구지원 보드 레퍼런스를 참고하세요. 하드웨어 스택이 처음이라면 하드웨어 빠른 시작부터 시작하세요.

Pico는 LLM이 호출 가능한 pico_flash 도구로 플래시합니다. 이 도구는 내장된 Revka MicroPython 펌웨어(UF2 이미지)를 BOOTSEL 모드의 Pico에 복사하고, mpremotemain.py를 배포한 뒤, 시리얼 포트가 다시 나타날 때까지 기다린 후 디바이스 트랜스포트를 재연결합니다. 따라서 데몬을 재시작하지 않아도 GPIO 명령을 즉시 사용할 수 있습니다.

  • hardware 피처가 컴파일에 포함되어 있어야 합니다.

  • mpremote가 설치되어 있어야 합니다:

    Terminal window
    pip install mpremote
  1. BOOTSEL 버튼을 누른 채로 Pico를 연결합니다. RPI-RP2 드라이브가 마운트됩니다(macOS/Linux에서는 볼륨으로, Windows에서는 드라이브 문자로 표시됩니다).

  2. 에이전트에게 보드를 플래시하도록 지시합니다. 예: “Pico를 플래시해 줘.”

  3. 에이전트는 안전 게이트를 설정하여 도구를 호출합니다:

    pico_flash(confirm=true)
  4. 도구는 UF2를 복사하고, 최대 20초간 시리얼 포트를 기다린 후, main.py를 배포하고 트랜스포트를 재연결합니다. 성공 시 다음과 같은 메시지가 출력됩니다:

    Pico flashed and main.py deployed successfully. Firmware is online at
    /dev/cu.usbmodem101. pico0 is ready — you can use gpio_write immediately.

파라미터

파라미터타입필수 여부설명
confirmboolean진행하려면 true이어야 합니다. 안전 게이트입니다.

디바이스 코드 읽기 / 쓰기 / 실행

섹션 제목: “디바이스 코드 읽기 / 쓰기 / 실행”

MicroPython(또는 CircuitPython) 디바이스가 온라인 상태가 되면, 세 가지 도구로 에이전트가 실행 중인 프로그램을 관리할 수 있습니다. 세 도구 모두 mpremote를 사용하므로 pip install mpremote가 필요합니다. device 파라미터는 디바이스가 하나만 등록되어 있으면 자동으로 선택됩니다.

디바이스에서 현재 main.py를 읽습니다. 디바이스 동작을 수정하기 전에 먼저 실행하세요.

device_read_code()
device_read_code(device="pico0")

내부적으로 mpremote connect <port> cat :main.py를 실행하여 파일 내용을 반환합니다. main.py가 존재하지 않으면 오류 대신 “아직 프로그램이 없습니다”라는 친절한 메시지를 반환합니다.

파라미터타입필수 여부설명
devicestring아니오디바이스 별칭. 디바이스가 하나만 등록된 경우 자동 선택됩니다.

완전한 Python 프로그램을 main.py로 디바이스에 쓴 후 보드를 리셋합니다.

device_write_code(
device="pico0",
code="import machine, time\nled = machine.Pin(25, machine.Pin.OUT)\nwhile True:\n led.toggle()\n time.sleep(0.5)\n"
)

내부적으로 mpremote를 통해 코드를 main.py에 복사하고 디바이스를 리셋한 뒤, 최대 15초간 시리얼 포트가 다시 나타나기를 기다리고 재연결 성공 여부를 보고합니다.

파라미터타입필수 여부설명
devicestring아니오디바이스 별칭. 디바이스가 하나뿐이면 자동 선택됩니다.
codestringmain.py로 쓸 완전한 프로그램. 빈 값은 거부됩니다.

main.py를 수정하지 않고 디바이스에서 Python 스니펫을 실행합니다. 스니펫 실행이 완료된 후에도 디바이스는 현재 프로그램을 계속 실행합니다. 센서 읽기, 빠른 테스트, 블링크 루프 등에 사용하세요.

device_exec(code="print(machine.Pin(25).value())")

내부적으로 mpremote connect <port> run <snippet>을 실행하고 캡처된 출력(예외 등 MicroPython stderr 포함)을 반환합니다. 타임아웃은 30초이며, 응답 없는 디바이스는 타임아웃 오류 메시지를 출력합니다. 빈 코드는 거부됩니다.

파라미터타입필수 여부설명
devicestring아니오디바이스 별칭. 디바이스가 하나뿐이면 자동 선택됩니다.
codestring실행할 Python 스니펫. 출력이 캡처되어 반환됩니다.

Arduino는 Revka 펌웨어 플래시와 스케치 업로드 모두에 arduino-cli를 사용합니다.

Revka 펌웨어 플래시 (revka peripheral flash)

섹션 제목: “Revka 펌웨어 플래시 (revka peripheral flash)”

이 CLI 명령은 내장된 Revka 펌웨어 스케치를 Arduino Uno에 플래시합니다. arduino-cli 설치(macOS에서는 Homebrew를 통해), AVR 코어 설치, 스케치 컴파일 및 업로드를 모두 처리합니다. 이 펌웨어는 시리얼을 통해 capabilities, gpio_read, gpio_write 명령을 활성화합니다.

Terminal window
# 포트를 명시적으로 지정
revka peripheral flash --port /dev/cu.usbmodem14301
# 또는, 보드가 이미 config.toml에 있는 경우
revka peripheral flash
플래그타입필수 여부설명
--portstring아니오시리얼 포트. 생략하면 config.toml에서 자동으로 해석됩니다.

플래시 후 ~/.revka/config.toml에 보드를 추가합니다:

[peripherals]
enabled = true
[[peripherals.boards]]
board = "arduino-uno"
transport = "serial"
path = "/dev/cu.usbmodem14301"
baud = 115200

커스텀 스케치 업로드 (arduino_upload)

섹션 제목: “커스텀 스케치 업로드 (arduino_upload)”

arduino_upload는 에이전트가 생성한 Arduino 스케치를 컴파일하고 업로드하는 LLM 호출 가능 도구로, 위의 Revka 펌웨어 플래시와는 별개입니다. arduino-uno라는 이름으로 보드가 설정되면 자동으로 추가되며, 해당 보드의 path 설정 값을 시리얼 포트로 사용합니다.

에이전트는 setup()loop()이 모두 포함된 완전한 .ino 스케치를 작성하여 code로 전달합니다. Revka는 스케치를 임시 디렉토리에 쓴 뒤 arduino:avr:uno 보드를 대상으로 arduino-cli compilearduino-cli upload를 실행합니다.

arduino_upload(code="void setup() {\n pinMode(13, OUTPUT);\n}\nvoid loop() {\n digitalWrite(13, HIGH);\n delay(500);\n digitalWrite(13, LOW);\n delay(500);\n}\n")

“Arduino에 블링크 스케치를 업로드해 줘” 와 같은 자연어 요청을 받으면 에이전트가 스케치를 생성하고 도구를 호출합니다.

파라미터타입필수 여부설명
codestring완전한 .ino 스케치 내용(전체 파일). 빈 값은 거부됩니다.

Nucleo-F401RE는 보드에 내장된 ST-Link 디버거를 통해 probe-rs로 플래시합니다. 별도의 디버그 프로브가 필요 없습니다. CLI 명령은 Embassy Rust 펌웨어를 빌드하고 플래시합니다. 플래시 후 보드는 USART2(PA2/PA3)에서 Revka 시리얼 JSON 프로토콜로 통신하며, 이는 ST-Link 가상 COM 포트로 브리지됩니다.

probe-rs CLI 도구를 설치합니다(크레이트 이름은 probe-rs가 아닌 probe-rs-tools입니다):

Terminal window
cargo install probe-rs-tools --locked

Revka를 통한 플래시 (revka peripheral flash-nucleo)

섹션 제목: “Revka를 통한 플래시 (revka peripheral flash-nucleo)”
Terminal window
revka peripheral flash-nucleo

firmware/nucleo를 빌드하고 probe-rs run --chip STM32F401RETx를 실행합니다. 펌웨어는 플래시 직후 바로 동작합니다.

Terminal window
cd firmware/nucleo
cargo build --release --target thumbv7em-none-eabihf
probe-rs run --chip STM32F401RETx target/thumbv7em-none-eabihf/release/nucleo

주요 상수: 칩 STM32F401RETx, 타깃 트리플 thumbv7em-none-eabihf.

플래시 후 Nucleo는 시리얼 디바이스로 나타납니다:

/dev/cu.usbmodem* 또는 /dev/tty.usbmodem* (예: /dev/cu.usbmodem101).

~/.revka/config.toml에 보드를 추가합니다:

[peripherals]
enabled = true
[[peripherals.boards]]
board = "nucleo-f401re"
transport = "serial"
path = "/dev/cu.usbmodem101" # adjust to your port
baud = 115200

핀 13 = PA5 = Nucleo-F401RE의 사용자 LED(LD2).

probe 피처(cargo build --features hardware,probe)로 빌드하고 revka hardware info를 실행하면, 타깃에 펌웨어가 없는 상태에서도 USB/SWD를 통해 Nucleo의 칩 정보와 메모리 맵을 읽을 수 있습니다. 자세한 내용은 지원 보드를 참고하세요.

Arduino Uno Q는 일반적인 방식으로 플래시하지 않습니다. Linux 측에서 Revka가 실행되며, GPIO 제어는 Bridge 앱을 통해 이루어집니다. Bridge 앱은 TCP 포트 9999에서 수신 대기하는 Python + MCU 소켓 서버로, Linux 측의 gpio_read / gpio_write를 MCU의 GPIO에 연결합니다. revka peripheral setup-uno-q 명령은 scp + arduino-app-cli를 통해 Bridge 앱을 배포합니다.

Terminal window
# Mac에서 (revka 저장소와 함께)
revka peripheral setup-uno-q --host 192.168.0.48
# Uno Q에서 직접 (SSH로 접속한 경우) — 기본값은 localhost
revka peripheral setup-uno-q

이 명령은 Bridge 앱(firmware/uno-q-bridge/에서)을 ~/ArduinoApps/uno-q-bridge로 복사하고 시작합니다.

플래그타입필수 여부설명
--hoststring아니오Uno Q의 IP 주소. 기본값은 localhost입니다.

설정 후 config.tomlbridge 트랜스포트로 보드를 등록합니다:

[peripherals]
enabled = true
[[peripherals.boards]]
board = "arduino-uno-q"
transport = "bridge"

이 설정을 마치면 표준 gpio_read / gpio_write 도구가 시리얼 포트 대신 Bridge TCP 소켓(127.0.0.1:9999)을 통해 투명하게 동작합니다. 에이전트는 동일한 도구 이름을 사용합니다. Bridge가 실행 중이어야 이 도구들이 동작합니다. setup-uno-q가 Bridge를 시작합니다. 연결 타임아웃은 5초, 응답 타임아웃은 3초이며, Bridge의 오류 응답은 error:로 시작합니다.