소개
이 책의 목표는 Espressif 장치에서 Rust 프로그래밍 언어의 포괄적인 사용 가이드를 제공하는 것입니다.
Espressif 장치의 Rust 프로그래밍 언어의 지원이 현재 빠르게 진행 중에 있습니다. 이 때문에 이 문서의 일부가 빠르게 변경될수 있으며 오래되어있을수있습니다.
Rust on ESP 관련 툴과 라이브러리는 Gihtub의 esp-rs organization를 참고하세요. 이 organization은 Espressif 직원 뿐만 아니라 커뮤니티 구성원도 관리합니다
모든 기술적 질문과 이슈에 대해 자유롭게 esp-rs
community on Matrix 에 참여하세요! 이 커뮤니티는 모두에게 열려있습니다!
이 책의 독자층
이 책은 Rust에 대한 경험이 있는 사람들을 대상으로 하며, 임베디드 개발 및 전자제품에 대한 초보적인 지식을 전제로 합니다. 위 경험이 없는 사람들에게는 먼저 가정 및 전제조건과 리소스섹션을 읽어보고 최신 정보를 얻도록 권장합니다
가정 및 전제조건
- Rust 프로그래밍 언어를 편하게 사용할 수 있으며 데스크톱 환경에서 응용 프로그램을 작성하고 실행했습니다.
- 이 책은 Rust 2021년 에디션을 기준으로 하므로 코드 관용구를 숙지해야합니다.
- C또는 C++ 등과 같은 언어로 임베디드 시스템을 개발하는데 편안하고 다음 개념에 익숙해야합니다
- cross-compilation
UART
,SPI
,I2C
, 등과 같은 일반적인 디지털 인터페이스.- Memory-mapped peripherals
- Interrupts
리소스
위에서 언급한 내용에 대해 잘 모르거나 경험이 부족한 경우 또는 이 책에서 언급한 특정 주제에 대해 더 많은 정보를 원하시면 도움이 될 수 있습니다.
Resource | Description |
---|---|
The Rust Programming Language | Rust에 대해 잘 모르신다면 이 책을 먼저 읽으시는것이 좋습니다. |
The Embedded Rust Book | 여기서 Rust's Embedded Working Group에서 제공하는 여러 리소스를 찾을 수 있습니다. |
The Embedonomicon | Rust 임베디드 프로그래밍에서 중요한 세부내용들 |
Embedded Rust (std) on Espressif | Espressif SoCs를 위한 std 사용 가이드 |
Embedded Rust (no_std) on Espressif | Espressif SoCs를 위한 no_std 사용 가이드 |
Translations
이 책은 자발적으로 번역되었습니다. 번역이 아래 리스트에 포함되길 원한다면 Pull Request 열어서 추가해주세요.
사용법
이 책은 계단식 챕터로 구성된 책입니다. 따라서 이전 챕터에 내용을 이해하지 못한채 다음 챕터로 넘어간다면 이해에 어려움이 있습니다.
이 책에 컨트리뷰팅하기
이 책에 대한 작업은 이 저장소에 저장됩니다.
이 책을 따라가는데 어려움이 있거나 책의 일부분이 명확하지않다면 그것은 버그입니다.
이 책 리포지토리의 이슈탭에 제보해주세요.
오타 수정 및 번역 이슈의 경우 한국어 리포지토리 이슈탭에 제보해주시면 빠르게 응답하겠습니다.
자료의 재사용
이 책은 다음 라이선스로 배포됩니다:
- 이 책에 수록된 코드 샘플 및 독립 Cargo 프로젝트는 MIT License 와 Apache License v2.0의 조건에 따라 라이센스가 부여됩니다.
- 이 책에 수록된 산문, 그림, 도표는 Creative Commons CC-BY-SA v4.0 조건에 따라 라이센스가 부여됩니다..
요약하면, 작업에 당사의 텍스트 또는 이미지를 사용하려면 다음과 같은 작업이 필요합니다:
- 출처를 명시해야 합니다.(예: 슬라이드에 이 책을 언급하고 관련 페이지 링크를 제공합니다)
- CC-BY-SA v4.0 license에 대한 링크를 제공해야 합니다.
- 어떤 내용을 변경했는지 표시하고 동일한 라이센스에 따라 당사의 내용을 변경할 수 있습니다
이 책이 유용하다고 생각되면 알려주세요!
개발 접근 방식의 개요
Espressif chips에서 Rust를 사용하는 방법은 다음과 같습니다.:
std
라이브러리, a.k.a. 스탠다드 라이브러리 사용하기.core
라이브러리 (no_std
), a.k.a. 배어메탈 개발 사용하기.
두 접근 방식 모두 장점과 단점이 있으므로, 프로젝트의 필요에 따라 결정을 내려야 합니다. 이 장에는 두 가지 접근 방식에 대한 개요가 포함되어 있습니다.
The Embedded Rust Book의 다양한 런타임 비교도 참조하십시오.
GitHub의 esp-rs organization은 Espressif 칩에서 Rust를 실행하는 것과 관련된 여러 저장소의 홈입니다. 필요한 크레이트의 대부분은 여기에 소스 코드를 호스팅하고 있다.
네이밍 컨벤션 레포지토리
esp-rs organization에서, 우리는 다음과 같은 표현을 사용합니다:
esp-
로 시작하는 저장소는no_std
접근 방식에 초점을 맞추고 있다. 예를 들어,esp-hal
no_std
는 베어 메탈 위에서 작동하므로,esp-
는 Espressif chip 이다.
esp-idf-
로 시작하는 저장소는std
접근 방식에 초점을 맞추고 있다. 예를 들어,esp-idf-hal
std
는 베어 메탈을 제외하고esp-idf-
인 추가 레이어가 필요합니다.
Espressif 제품 지원
⚠️ 참고:
- ✅ - 이 기능은 구현되어있거나 지원됩니다.
- ⏳ - 그 기능은 개발 중입니다.
- ❌ - 이 기능은 지원되지 않습니다.
Chip | std | no_std |
---|---|---|
ESP32 | ✅ | ✅ |
ESP32-C2 | ✅ | ✅ |
ESP32-C3 | ✅ | ✅ |
ESP32-C6 | ✅ | ✅ |
ESP32-S2 | ✅ | ✅ |
ESP32-S3 | ✅ | ✅ |
ESP32-H2 | ✅ | ✅ |
ESP8266 | ❌ | ✅ |
⚠️ 참고: ESP8266 시리즈는 이 책의 범위를 벗어난다. ESP8266 시리즈에 대한 Rust 지원은 제한적이며 Espressif에서 공식적으로 지원되지 않습니다.
특정 상황에서 지원되는 제품은 책 전체에서 _지원되는Espressif 제품들_이라고 불릴 것이다.
스탠다드 라이브러리 사용하기 (std
)
Espressif는 ESP-IDF라고 불리는 C 기반 개발 프레임워크를 제공합니다. ESP32로 시작하는 모든 Espressif 칩을 지원하거나 지원할 것입니다. 이 프레임워크는 ESP8266을 _지원하지 않는다_는 점에 유의하십시오.
ESP-IDF는 그 위에 Rust 표준 라이브러리(std
)를 구축하기에 충분한 기능을 갖춘 newlib 환경을 제공한다. 이것은 Epressif 장치에서 std
지원을 활성화하기 위해 취해지고 있는 접근 방식이다.
현재 지원되는 사항
Rust std
개발을 위해 지원되는 Espressif 제품은 ESP-IDF 프레임워크에서 지원하는 제품입니다. 다양한 버전의 ESP-IDF와 Espressif 칩 지원에 대한 자세한 내용은 이 표를 참조하십시오.
std
를 사용할 때, thread, mutex 및 기타 synchronization primitives, collections, 난수 생성, 소켓 등을 포함하여 ESP-IDF에 존재하는 많은 기능에 액세스할 수 있습니다.
esp-rs
관련된 Crate들
리포지토리 | 설명 |
---|---|
embedded-svc | 임베디드 서비스들을 위한 추상화 trait들 (WiFi , Network , Httpd , Logging , etc.) |
esp-idf-svc | esp-idf 드라이버를 사용하는 embedded-svc 구현. |
esp-idf-hal | esp-idf 프레임워크를 사용한 embedded-hal 및 기타 trait들의 구현. |
esp-idf-sys | esp-idf 개발 프레임워크에 대한 Rust 바인딩입니다. 드라이버, Wi-Fi 등에 대한 raw (unsafe ) 액세스를 제공합니다. |
앞서 언급한 crate들은 상호 의존성을 가지고 있으며, 이 관계는 아래에서 볼 수 있다.
graph TD;
esp-idf-hal --> esp-idf-sys & embedded-svc
esp-idf-svc --> esp-idf-sys & esp-idf-hal & embedded-svc
Standard Library(std
)를 사용할 경우
- 풍부한 기능: 임베디드 시스템 요구사항에 네트워킹 프로토콜, 파일 I/O 또는 복잡한 데이터 구조 등의 지원과 같은 많은 기능이 필요한 경우,
std
라이브러리를 사용한다면 광범위한 기능을 제공하여 복잡한 어플리케이션을 만들때 유용합니다. - 이식성:
std
crate는 다양한 플랫폼과 아키텍처에서 사용할 수 있는 표준화된 API 세트를 제공하여 이식 가능하고 재사용 가능한 코드를 더 쉽게 작성할 수 있도록 합니다. - 신속한 개발:
std
crate는 낮은 수준의 세부 사항에 대해 너무 많이 걱정하지 않고 빠르고 효율적으로 애플리케이션을 구축하는 데 사용할 수 있는 풍부한 기능 세트를 제공합니다.
코어 라이브러리 사용하기 (no_std
)
임베디드 Rust 개발자들에게는 no_std
를 사용하는것이 더 친숙할수 있습니다. std
(Rust 스탠다드
라이브러리) 를 사용하지않고 부분집합인 core
라이브러리를 사용합니다. The Embedded Rust Book 에는 훌륭한 세션이 있습니다.
여기서 주의할 점은 no_std
은 Rust core
라이브러리를 사용한다는 것입니다. Rust standard
의 일부이기때문에 no_std
crate는 std
환경에서 컴파일 할 수 있습니다. 하지만, 역은 성립하지않습니다: std
crate는 no_std
환경에서 컴파일 할 수 없습니다. 이 정보는 어떤 라이브러리를 선택할지 결정할 때 기억할 가치가 있습니다.
현재 지원사항들
아래 표는 다양한 Espressif 제품에 대한 현재 no_std
지원에 대해 설명합니다.
HAL | Wi-Fi/BLE/ESP-NOW | Backtrace | Storage | |
---|---|---|---|---|
ESP32 | ✅ | ✅ | ✅ | ✅ |
ESP32-C2 | ✅ | ✅ | ✅ | ✅ |
ESP32-C3 | ✅ | ✅ | ✅ | ✅ |
ESP32-C6 | ✅ | ✅ | ✅ | ✅ |
ESP32-H2 | ✅ | ✅ | ✅ | ✅ |
ESP32-S2 | ✅ | ✅ | ✅ | ✅ |
ESP32-S3 | ✅ | ✅ | ✅ | ✅ |
⚠️ Note:
- ✅ Wi-Fi/BLE/ESP-NOW에서 대상이 적어도 나열된 기술 중 하나를 지원하는 것을 의미합니다. 자세한 내용은 esp-wifi repository의 Current support 표를 참조하십시오.
- ESP8266 HAL은 유지보수 모드이며 이 칩에 대해서는 더 이상 개발이 이루어지지 않습니다.
esp-rs
관련 Crates
Repository | Description |
---|---|
esp-hal | 하드웨어 추상계층 |
esp-pacs | Peripheral 접근crates |
esp-wifi | Wi-Fi, BLE and ESP-NOW 지원 |
esp-alloc | 간단한 Heap 할당자 |
esp-println | print! , println! |
esp-backtrace | 예외상황과 패닉 핸들러 |
esp-storage | 암호화되지 않은 플래시 메모리에 액세스할 수 있는 임베디드 스토리지 traits |
Core Library(no_std
)를 권장하는 예시
- 작은 메모리 사용량: 임베디드 시스템의 리소스가 제한되어있고 메모리 사용량이 적어야 하는 경우
std
기능을 사용하면 컴파일 되는 최종 바이너리 크기와 컴파일 시간이 많이 들기 때문에, bare-matal을 사용할 가능성이 높습니다. - 하드웨어 직접 제어: 임베디드 시스템에서 낮은 수준의 장치 드라이버나 특수 하드웨어 기능에 대한 액세스와 같이 하드웨어에 대한 보다 직접적인 제어가 필요한 경우
std
가 하드웨어와 직접 상호 작용하기 어려울 수 있는 추상화를 추가하기 때문에 베어메탈을 사용하는 것이 좋습니다 - 시간이 중요한 어플리케이션: 임베디드 시스템이 실시간적 퍼포먼스와 빠른 응답속도를 요구한다면,
std
는 예측할 수 없는 지연과 오버헤드를 초래할 수 있으므로no_std
를 사용하는 것이 좋습니다. - 커스텀 요구사항들: 베어메탈을 사용하면 애플리케이션의 동작을 보다 맞춤화하고 세밀하게 제어할 수 있으므로 전문화된 환경이나 비표준 환경에서 유용하게 사용할 수 있습니다.
Setting Up a Development Environment
현재, Espressif SoCs는 RISC-V
and Xtensa
두 가지 아키텍처를 기반으로 하고 있습니다.
두 아키텍처 모두 std
와 no_std
접근 방식을 지원합니다.
개발 환경을 설정하려면 다음을 수행합니다:
- Rust 설치하기
- 대상 장치에 대한 설치 요구사항
대상 아키텍처와 상관없이, std
개발을 위해서 std
개발 요구사항 설치를 잊지마세요.
개발환경은 컨테이너에서 호스팅할 수 있으니 참고하시기 바랍니다..
Rust 설치
Rust가 설치되어있는지 확인하십시오. 설치되어있지 않은경우, rustup웹사이트를 참고하십시오.
🚨 Warning: 유닉스 기반 시스템을 사용할 때 시스템 패키지 관리자(예시.
brew
,apt
,dnf
, etc.)를 통해 설치한다면, 다양한 문제와 비호환성이 발생할 수 있으므로 대신 rustup을 사용하는 것이 가장 좋습니다.
Windows를 사용하는 경우 아래 나열된 ABI 중 하나를 설치했는지 확인합니다. 자세한 내용은 rustup 책의 Windows 챕터를 참고하세요.
- MSVC: 추천하는 ABI,
rustup
기본 요구사항 리스트에 있습니다. Visual Studio에서 만든 소프트웨어와 상호운용하려면 이것을 사용하세요. - GNU: GCC 툴체인을 사용하는 ABI. MinGW/MSYS2 툴체인으로 만들어진 소프트웨어와 함께 사용하려면 직접 설치하세요.
대체 설치방법도 참고하세요.
RISC-V
타겟 only
RISC-V
구조 기반 Espressif chips의 어플리케이션을 빌드하려면 다음을 따라주세요
-
rust-src
component와 함께nightly
툴체인을 설치해주세요:rustup toolchain install nightly --component rust-src
위의 명령은 rust 소스 코드를 다운로드합니다.
rust-src
는 std-lib, core-lib and build-config와 같은 항목들을 포함합니다.
rust-src
를 다운로드하는것은 두 가지 이유때문에 중요합니다:- Determinism(결정론) - core와 std 라이브러리의 내부를 볼 수 있습니다. 높은 수준의 확실성이 필요한 소프트웨어를 작성해야하는 경우, 사용 중인 라이브러리를 확인하는 것이 좋습니다.
- custom targets 빌드하기 -
rustc
는 새 커스텀 타겟의 컴포넌트를 만들때rust-src
를 사용한다. 만약 rust에서 지원을 안하는 triple-target을 타겟으로 할때,rust-src
다운로드는 필수입니다.
For more info on custom targets, read this Chapter from the Embedonomicon.
커스텀 타겟에 대한 자세한 내용은 Embedonomicon의 이 챕터를 읽으세요
-
타겟을 설정합니다:
-
no_std
(베어 메탈) 어플리케이션의 경우 다음을 실행합니다:rustup target add riscv32imc-unknown-none-elf # For ESP32-C2 and ESP32-C3 rustup target add riscv32imac-unknown-none-elf # For ESP32-C6 and ESP32-H2
이 대상은 현재 Tier 2입니다. Rust에서 다양한
RISC-V
extensions을 포함하는riscv32
대상의 다양한 맛을 주목하십시오. -
std
어플리케이션의 경우:
이 대상은 현재 Tier 3이므로
rustup
을 통해 배포되는 사전 빌드된 개체가 없으며no_std
대상과 달리 설치할 필요가 없습니다. 장치에 대한 올바른 대상은 러스트북의 *-esp-idf 섹션을 참조하십시오.riscv32imc-esp-espidf
는 ESP32-C2 및 ESP32-C3 와 같은 atomics을 지원하지않는 SoC 용입니다.riscv32imac-esp-espidf
는 atomics를 지원하는 SoC(ESP32-C6, ESP32-H2, and ESP32-P4 등)용입니다.
-
-
std
프로젝트들을 빌드하려면 다음을 설치하여야합니다:LLVM
컴파일러 인프라- 다른
std
개발 요구사항들 - 프로젝트의 파일
.cargo/config.toml
에서 불안정한 Cargo feature-Z build-std
를 추가합니다. 이 책 뒷부분에서 설명하는 템플릿 프로젝트에는 이미 이 기능이 포함되어있습니다
이제 Espressif의 RISC-V
칩에 프로젝트를 구축하고 실행할 수 있을 것입니다.
RISC-V
와 Xtensa
타겟
espup
는 Xtensa
및 RISC-V
아키텍처를 위한 Rust 어플리케이션을 개발하는 데 필요한 구성 요소의 설치 및 유지 관리를 단순화하는 도구입니다..
1. espup
설치
espup
를 설치하려면, 아래 명령어를 터미널에 실행하세요:
cargo install espup
미리 컴파일된 릴리스 바이너리를 직접 다운로드하거나 cargo-binstall
을 사용할 수도 있습니다.
2. 필수 툴체인 설치
다음을 실행하여 지원되는 모든 Espressif 대상에 대한 Rust 애플리케이션을 개발하는 데 필요한 모든 도구를 설치하십시오:
espup install
⚠️ 참고:
std
애플리케이션은std
개발 요구사항에서 다루는 추가 소프트웨어를 설치해야 합니다.
3. 환경 변수 설정하기
espup
은 프로젝트를 구축하는 데 필요한 몇 가지 환경 변수가 포함된 내보내기 파일을 만들 것이다.
Windows (%USERPROFILE%\export-esp.ps1
)
- 이 파일을 실행할 필요가 없습니다. 수정된 환경변수를 보여주는 용도로 만든것입니다.
유닉스 기반 운영체제 - ($HOME/export-esp.sh
). 파일을 sourcing하기위한 다른 방법들이 있습니다:
-
매 터미널에서 이 파일을 source하기:
- 해당 파일을 source하기:
. $HOME/export-esp.sh
이 방식은 매 새 쉘을 열때마ㅏ 실행해줘야합니다.
- 해당 파일을 source하기:
-
export-esp.sh
를 실행하는 alias 만들기:- 쉘 프로파일 (
.profile
,.bashrc
,.zprofile
, 등.)에 다음 명령어를 복사 붙여넣기 하세요:alias get_esprs='. $HOME/export-esp.sh'
- 터미널 세션을 재시작하시거나
source [프로파일 경로]
명령어를 실행하세요, 예를 들면,source ~/.bashrc
.
이 방식은 매 쉘마다 sourcing을 안해도됩니다,
export-esp.sh
스크립트는 새로운 쉘이 실행될때 자동으로 실행됩니다. - 쉘 프로파일 (
espup
는 무엇을 설치하나요?
Espressif 대상을 지원하기위해, espup
다음과 같은 도구를 설치합니다.
- Espressif 대상 지원을 위한 Espressif Rust fork
RISC-V
대상을 위한nightly
툴체인Xtensa
대상을 위한LLVM
fork- final binary를 링크하는 GCC 툴체인
fork 컴파일러는 표준 Rust 컴파일러와 공존할 수 있으며, 둘 다 시스템에 설치할 수 있습니다. fork 컴파일러는 오버로딩 메소드를 사용할 때 호출됩니다.
⚠️ 참고: 우리는 fork를 업스트림하기위해 노력을 하고있습니다
LLVM
fork에 변화는 이미 진행중입니다, tracking issue를 확인하세요.- Rust 컴파일러 Fork들에 대해, LLVM 변경이 수락되면, 우리는 Rust 컴파일러 변경을 진행할 것입니다.
오류가 발생하면, 문제 해결 장을 확인하세요.
Xtensa
Targets를 위한 다른 설치 방법
rust-build
설치 스크립트 사용. 이것은 과거에 권장되는 방법이었지만, 이제 설치 스크립트는 기능이 frozen되었다. 모든 새로운 기능은espup
에만 포함될 것입니다. 원본 Repository [README][https://github.com/esp-rs/rust-build.git]를 참조하십시오.- 소스에서
Xtensa
Rust 컴파일러를 구축하세요. 이 과정은 계산 비용이 많이 들고 시스템에 따라 완료하는 데 한 시간 이상이 걸릴 수 있습니다. 이 접근 방식을 취할 주요 이유가 없다면 권장되지 않습니다. 여기 소스에서 빌드할 리포지토리가 있습니다:esp-rs/rust
repository.
std
개발 요구사항
대상 아키텍처에 관계없이, std
애플리케이션을 구축하는 데 필요한 다음과 같은 도구가 설치되어 있는지 확인하십시오:
-
ESP-IDF 전제조건:
- 윈도우:
python
와git
- 리눅스: 리눅스 ESP-IDF 전제조건.
- macOS: macOS ESP-IDF prerequisites]esp-idf-macos.
- 윈도우:
-
ldproxy
바이너리 크레이트:ldproxy
에 대한 인수로도 주어진 실제 링커에 링커 인수를 전달하는 도구. 실행하여 설치하세요:cargo install ldproxy
⚠️ 참고: std 런타임은 ESP-IDF (Espressif IoT Development Framework)를 호스팅 환경으로 사용하지만 사용자는 설치할 필요가 없습니다. ESP-IDF는
std
애플리케이션을 구축할 때 모든std
프로젝트가 사용해야 하는 크레이트인esp-idf-sys
에 의해 자동으로 다운로드되고 설치됩니다.
Containers 사용하기
로컬 시스템에 직접 설치하는 대신, 컨테이너 내에서 개발 환경을 호스팅할 수 있습니다. Espressif는 RISC-V
와 Xtensa
대상 아키텍처를 모두 지원하고 std
와 no_std
개발을 모두 가능하게 하는 idf-rust
이미지를 제공합니다.
linux/arm64
및 linux/amd64
플랫폼에 대한 수많은 태그를 찾을 수 있습니다.
각 Rust 릴리스에 대해, 우리는 다음과 같은 명명 규칙으로 태그를 생성합니다:
<chip>_<rust-toolchain-version>
- 예를 들어,
esp32_1.64.0.0
에는std
를 개발하기 위한 생태계와1.64.0.0
Xtensa
Rust 툴체인이 있는ESP32
용no_std
애플리케이션이 포함되어 있습니다.
- 예를 들어,
특별 케이스가 있다.:
<chip>
은 모든 Espressif 대상과의 호환성을 나타내는 모든 것이 될 수 있습니다.<rust-toolchain-version>
can belatest
which indicates the latest release of theXtensa
Rust toolchain<rust-toolchain-version>
은Xtensa
Rust 툴체인의최신
릴리스를 나타내는 최신일 수 있습니다.
운영 체제에 따라 Docker, Podman, 또는 Lima와 같은 컨테이너 런타임을 선택할 수 있습니다.
자신만의 어플리케이션 만들기
적절한 Rust 컴파일러와 툴체인이 설치되면, 이제 애플리케이션을 만들 준비가 되었습니다.
다음과 같은 방법으로 어플리케이션을 만들 수 있습니다.
-
(강력권장) 템플릿에서 생성: 구성된 프로젝트를 제공하고, 시간을 절약하며, 가능한 오류를 방지합니다.
-
cargo를 사용하여 처음부터 시작하세요: 프로젝트의 여러 부분을 구성해야 하기 때문에 더 많은 전문 지식이 필요합니다.
⚠️ 참고: Cargo로 프로젝트를 시작하는 것은 어떤 이점도 제공하지 않으며, Rust에서 프로젝트를 생성하는 일반적인 방법이기 때문에 여기에만 언급됩니다.
이 장에서는 cargo
로 처음부터 프로젝트를 만드는 방법에 대한 지침을 다루지 않으며, 템플릿 프로젝트에서 프로젝트를 생성하는 데에만 초점을 맞출 것이다.
이 장에서 사용되는 도구는 다음 장 Tooling에서 더 자세히 다룰 것이며, 필요할 때 자유롭게 참조하십시오.
템플릿으로 프로젝트 만들기
현재 두 템플릿 레포지토리를 유지하고있습니다.
esp-template
-no_std
템플릿esp-idf-template
-std
템플릿
두 템플릿 모두 기존 템플릿을 기반으로한 새 프로젝트를 만들 수 있는 도구 cargo-generate
기반으로 합니다.
두 템플릿 모두 기존 템플릿을 기반으로 새 프로젝트를 만들 수 있는 도구인 cargo-generate
를 기반으로 합니다. 우리의 경우, esp-idf-template
또는 esp-template
를 사용하여 필요한 모든 구성과 종속성을 가진 애플리케이션을 생성할 수 있습니다.
-
cargo generate
를 설치합니다:cargo install cargo-generate
-
템플릿 중 하나를 기반으로 프로젝트를 생성하세요.:
-
esp-template
:cargo generate esp-rs/esp-template
템플릿 프로젝트에 대한 자세한 내용은 Understanding
esp-template
을 참조하십시오. -
esp-idf-template
:cargo generate esp-rs/esp-idf-template cargo
템플릿 프로젝트에 대한 자세한 내용은 Understanding
esp-idf-template
을 참조하십시오.
cargo generate
서브커맨드가 호출되면, 타겟 앱에 관한 몇 가지 질문에 답하라는 메시지가 표시됩니다. 이 과정이 완료되면, 당신은 모든 올바른 구성으로 빌드 가능한 프로젝트를 갖게 될 것입니다. -
-
생성된 프로젝트를 빌드/실행하세요:
cargo build
를 사용하여 적절한 툴체인과 대상을 사용하여 프로젝트를 컴파일하세요.cargo run
을 사용하여 프로젝트를 컴파일하고, 플래시하고, 타겟 장치로 시리얼 모니터를 여세요.
템플릿에서 개발 컨테이너 사용하기
두 템플릿 저장소 모두 Dev Containers 지원에 대한 프롬프트가 있습니다. 템플릿 README의 Dev Containers 섹션에서 자세한 내용을 참조하십시오.
개발 컨테이너는 Setting up a Development Environment장의 Using Container 섹션에서 설명된 idf-rust
컨테이너 이미지를 사용합니다. 이 이미지는 설치 없이 Espressif 칩용 Rust 애플리케이션을 개발할 준비가 된 환경을 제공합니다. Dev Containers는 또한 Wokwi simulator 시뮬레이터와 통합하여 프로젝트를 시뮬레이션하고 web-flash
를 사용하여 컨테이너에서 깜박일 수 있습니다.
esp-template
의 이해
이제 no_std 프로젝트를 생성하는 방법을 알았으니, 생성된 프로젝트에 포함된 것을 검사하고, 모든 부분을 이해하고, 실행해 봅시다.
생성된 프로젝트 검사하기
다음 질답으로 esp-template에서 프로젝트를 만들 때:
- 어떤 MCU가 타겟인가? ·
esp32c3
- 고급 템플릿 옵션을 구성하시겠습니까? ·
false
이 설명을 위해, 우리는 기본값을 사용할 것입니다. 추가 수정을 원한다면, 기본값을 사용하지 않을 때 추가 프롬프트들을 참조하십시오.
다음과 같은 파일 구조를 생성합니다.:
├── .cargo
│ └── config.toml
├── src
│ └── main.rs
├── .gitignore
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
└── rust-toolchain.toml
더 나아가기 전에, 이 파일들이 무엇을 위한 것인지 봅시다.
-
-
Cargo 구성설정
-
이것은 프로젝트를 올바르게 구축하기 위한 몇 가지 옵션을 정의합니다.
-
runner = "espflash flash --monitor"
-cargo run
으로 코드를 플래시하고 모니터를 할 수 있게합니다.
-
-
src/main.rs
- 새로 생성된 프로젝트의 주요 소스 파일
- For details, see the Understanding
main.rs
section below - 자세한 내용은 아래의
main.rs
이해 섹션 을 참조하십시오.
-
- 어떤 폴더와 파일을 무시해야 하는지
git
에게 알려줍니다.
- 어떤 폴더와 파일을 무시해야 하는지
-
- 일반적인 카고 매니페스트는 프로젝트의 일부 메타 데이터와 종속성을 선언합니다.
-
LICENSE-APACHE
,LICENSE_MIT
-
그것들은 러스트 생태계에서 사용되는 가장 일반적인 라이선스이다.
다른 라이선스를 사용하려면, 이 파일을 삭제하고
Cargo.toml
에서 라이선스를 변경할 수 있습니다.
-
-
- 사용할 Rust 툴체인을 정의합니다.
- 툴체인은 당신의 목표에 따라
nightly
또는esp
가 될 것입니다.
- 툴체인은 당신의 목표에 따라
- 사용할 Rust 툴체인을 정의합니다.
Understanding main.rs
1 #![no_std]
2 #![no_main]
#![no_std]
- 이것은 러스트 컴파일러에게 이 코드가
libstd
를 사용하지 않는다는 것을 알려줍니다.
- 이것은 러스트 컴파일러에게 이 코드가
#![no_main]
no_main
속성은 이 프로그램이 인수를 받는 명령줄 응용 프로그램에 맞는 표준 메인 인터페이스를 사용하지 않을 것이라고 말한다. 표준 메인 대신, 우리는 사용자 지정 진입점을 정의하기 위해riscv-rt
크레이트의 항목 속성을 사용할 것입니다. 이 프로그램에서, 우리는 진입점을main
으로 명명했지만, 다른 이름이 사용될 수 있었다. 엔트리포인트 함수는 발산함수여야 한다. 즉,fn foo() -> !;
이 유형은 함수가 절대 반환되지 않는다는 것을 나타냅니다. 이는 프로그램이 절대 종료되지 않는다는 것을 의미합니다.
4 use esp_backtrace as _;
5 use esp_println::println;
6 use hal::{clock::ClockControl, peripherals::Peripherals, prelude::*, timer::TimerGroup, Rtc};
use esp_backtrace as _;
- 우리는 베어메탈 환경에 있기 때문에, 코드에서 패닉이 발생하면 실행되는 패닉 핸들러가 필요합니다.
- 사용할 수 있는 몇 가지 다른 크레이트(예:
panic-halt
)가 있지만esp-backtrace
는 백트레이스의 주소를 프린트하는 구현을 제공합니다.espflash
/espmonitor
와 함께 이러한 주소는 소스 코드 위치로 디코딩될 수 있습니다.
use esp_println::println;
println!
implementation을 제공합니다
use hal:{...}
- 몇가지 사용할 것들을
esp-hal
에서 가져옵니다
- 몇가지 사용할 것들을
8 #[entry]
9 fn main() -> ! {
10 let peripherals = Peripherals::take();
11 let mut system = peripherals.SYSTEM.split();
12 let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
13
14 // Disable the RTC and TIMG watchdog timers
15 let mut rtc = Rtc::new(peripherals.RTC_CNTL);
16 let timer_group0 = TimerGroup::new(
17 peripherals.TIMG0,
18 &clocks,
19 &mut system.peripheral_clock_control,
20 );
21 let mut wdt0 = timer_group0.wdt;
22 let timer_group1 = TimerGroup::new(
23 peripherals.TIMG1,
24 &clocks,
25 &mut system.peripheral_clock_control,
26 );
27 rtc.swd.disable();
28 rtc.rwdt.disable();
29 wdt0.disable();
30 wdt1.disable();
31
32 println!("Hello world!");
33
34 loop {}
35 }
main
함수 속 내용들:
let peripherals = Peripherals::take().unwrap();
- HAL 드라이버는 보통 PAC(peripheral access crate)을 통해 접근하는 주변 장치의 소유권을 갖는다.
- 여기서 우리는 PAC(peripheral access crate)의 모든 주변 장치를 가져가서 나중에 HAL 드라이버에게 전달합니다.
let mut system = peripherals.SYSTEM.split();
- 때때로 peripheral 장치(여기서 시스템 peripheral 장치)는 거친 입자이며 HAL 드라이버에 정확히 맞지 않습니다. 그래서 여기서 우리는 시스템 주변 장치를 드라이버에 전달되는 더 작은 조각으로 나눕니다.
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
- 여기서 우리는 시스템 clock를 구성합니다 - 이 경우, 기본값을 권장합니다
- clock을 freeze하여 추후에 바꾸지 못하도록 합니다.
- 몇몇 드라이버들은 rate와 duration 계산 방법에 대한 clock의 레퍼런스를 필요로 합니다
- 다음 코드 블록은 부팅 후 워치독을 비활성화하기 위해 일부 주변 장치(즉, RTC와 두 타이머 그룹)를 인스턴스화합니다.
- 이 코드가 없으면 잠시 후 SoC가 다시 부팅됩니다.
- 재부팅을 방지하는 또 다른 방법은 워치독에 전원을 공급하는 것입니다
println!("Hello world!");
- "Hello world!" 출력합니다
loop {}
- 함수는 절대 반환되지 않아야하기 때문에 루프에서 "아무것도하지 않습니다"
코드 실행
코드를 빌드하고 실행하는 것은 어렵지 않습니다.
cargo run
이렇게 하면 configuration에 따라 코드가 빌드되고 espflash
를 실행하여 코드를 보드에 플래시합니다.
우리의 runner
configuration 은 espflash
에 --monitor
인수도 있기때문에, 우리는 코드출력을 볼수있습니다.
espflash
를 설치했는지 확인하세요,그렇지 않으면 이 단계가 fail 하게됩니다. espflash
설치방법은 다음과 같습니다.:
cargo install espflash
이와 유사한 내용을 확인해야 합니다:
[2023-04-17T14:17:08Z INFO ] Serial port: '/dev/ttyACM0'
[2023-04-17T14:17:08Z INFO ] Connecting...
[2023-04-17T14:17:09Z INFO ] Using flash stub
[2023-04-17T14:17:09Z WARN ] Setting baud rate higher than 115,200 can cause issues
Chip type: esp32c3 (revision v0.3)
Crystal frequency: 40MHz
Flash size: 4MB
Features: WiFi, BLE
MAC address: 60:55:f9:c0:39:7c
App/part. size: 203,920/4,128,768 bytes, 4.94%
[00:00:00] [========================================] 13/13 0x0
[00:00:00] [========================================] 1/1 0x8000
[00:00:01] [========================================] 64/64 0x10000
[2023-04-17T14:17:11Z INFO ] Flashing has completed!
Commands:
CTRL+R Reset chip
CTRL+C Exit
...
Hello world!
여기에 표시되는 것은 1단계 및 2단계 부트로더의 메시지와 "Hello world" 메시지입니다!
이것은 실제 코드가 동작하는 것입니다
재부팅 단축키는 CTRL+R
, exit 단축키는 CTRL+C
입니다.
프로젝트를 빌드하는 동안 문제가 발생하면 문제 해결 장을 참조하십시오.
esp-idf-template
의 이해
이제 우리는 std
프로젝트를 생성하는 방법을 알았으니, 생성된 프로젝트에 무엇이 포함되어 있는지 검사하고 그것의 모든 부분을 이해하려고 노력합시다.
생성된 프로젝트 점검
다음과 같은 답변으로 esp-idf-template
에서 프로젝트를 만들 때:
- 어떤 MCU를 타겟으로 하시나요? ·
esp32c3
- 고급 템플릿 옵션들을 설정하겠습니까? ·
false
이 설명을 위해, 우리는 디폴트값을 사용할 것입니다. 추가 수정을 원한다면, 디폴트 값을 사용하지 않을 때 additional prompts를 참조하십시오.
다음과 같은 파일 구조를 생성해야 합니다:
├── .cargo
│ └── config.toml
├── src
│ └── main.rs
├── .gitignore
├── build.rs
├── Cargo.toml
├── rust-toolchain.toml
└── sdkconfig.defaults
더 나아가기 전에, 이 파일들이 무엇을 위한 것인지 봅시다.
.cargo/config.toml
- Cargo 구성설정
- 타겟 포함
runner = "espflash flash --monitor"
-cargo run
으로 코드를 플래시하고 모니터를 할 수 있게합니다.- 사용할 링커를 포함합니다. 위 케이스는
ldproxy
를 포함합니다. - 활성화된 불안정한
build-std
Cargo 기능이 포함되어 있습니다. - 프로젝트가 사용할 ESP-IDF 버전을
esp-idf-sys
에 알려주는ESP-IDF-VERSION
환경 변수를 포함합니다.
src/main.rs
- 새로 생성된 프로젝트의 주요 소스 파일
- 자세한 내용은 아래의
main.rs
의 이해 섹션을 참조하십시오.
.gitignore
- 어떤 폴더와 파일을 무시해야 하는지
git
에게 알려줍니다.
- 어떤 폴더와 파일을 무시해야 하는지
build.rs
ldproxy
에 대한 링커 인수를 전파합니다.
Cargo.toml
- 프로젝트의 일부 메타 데이터와 종속성을 선언하는 일반적인 Cargo 매니페스트
rust-toolchain.toml
- 사용할 Rust 툴체인을 정의합니다.
- 툴체인은 당신의 목표에 따라
nightly
또는esp
될 것입니다.
- 툴체인은 당신의 목표에 따라
- 사용할 Rust 툴체인을 정의합니다.
sdkconfig.defaults
- ESP-IDF 기본값에서 재정의된 값을 포함합니다.
main.rs
의 이해
1 use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported
2
3 fn main() {
4 // It is necessary to call this function once. Otherwise some patches to the runtime
5 // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
6 esp_idf_sys::link_patches();
7 println!("Hello, world!");
8 }
첫 번째 줄은 루트 크레이트가 주 함수를 정의하는 바이너리 상자일 때 ESP-IDF 진입점이 정의된 것을 가져오기입니다.
그런 다음, 우리는 몇 줄이 있는 일반적인 주요 기능을 가지고 있습니다:
-
Rust에서 구현된 ESP-IDF에 대한 몇 가지 패치가 최종 실행 파일과 연결되도록 하는
esp_idf_sys::link_patches
함수에 대한 호출우리는 콘솔에 유명한 "Hello, world!"를 인쇄합니다.
코드 실행하기
코드를 빌드하고 실행하는 것은 어렵지 않습니다.
cargo run
이렇게 하면 configuration에 따라 코드가 빌드되고 espflash
를 실행하여 코드를 보드에 플래시합니다.
우리의 runner
configuration 은 espflash
에 --monitor
인수도 있기때문에, 우리는 코드출력을 볼수있습니다.
espflash
를 설치했는지 확인하세요,그렇지 않으면 이 단계가 fail 하게됩니다. espflash
설치방법은 다음과 같습니다.: cargo install espflash
이와 유사한 내용을 확인해야 합니다:
[2023-04-18T08:05:09Z INFO ] Connecting...
[2023-04-18T08:05:10Z INFO ] Using flash stub
[2023-04-18T08:05:10Z WARN ] Setting baud rate higher than 115,200 can cause issues
Chip type: esp32c3 (revision v0.3)
Crystal frequency: 40MHz
Flash size: 4MB
Features: WiFi, BLE
MAC address: 60:55:f9:c0:39:7c
App/part. size: 478,416/4,128,768 bytes, 11.59%
[00:00:00] [========================================] 13/13 0x0
[00:00:00] [========================================] 1/1 0x8000
[00:00:04] [========================================] 227/227 0x10000
[2023-04-18T08:05:15Z INFO ] Flashing has completed!
Commands:
CTRL+R Reset chip
CTRL+C Exit
...
I (344) cpu_start: Starting scheduler.
Hello, world!
여기에 표시되는 것은 1단계 및 2단계 부트로더의 메시지와 "Hello world" 메시지입니다!
이것은 실제 코드가 동작하는 것입니다
재부팅 단축키는 CTRL+R
, exit 단축키는 CTRL+C
입니다.
프로젝트를 빌드하는 동안 문제가 발생하면 문제 해결 장을 참조하십시오.
no_std
어플리케이션 만들기
no_std
애플리케이션을 개발하는 방법을 배우고 싶다면, 다음 교육 자료를 참조하십시오:
교육은 ESP32-C3-DevKit-RUST-1을 기반으로 합니다. 다른 Espressif 개발 보드를 사용할 수 있지만 코드 변경 및 구성 변경이 필요할 수 있습니다.
- 입문 수준의 예시:
⚠️ 참고: 모든 SoC
esp-hal
의 예제 폴더 아래에 특정 주변 장치의 사용을 다루는 몇 가지 예가 있습니다. 예:esp32c3-hal/examples
std
어플리케이션 만들기
std
애플리케이션을 개발하는 방법을 배우고 싶다면, Ferrous Systems와 함께 개발된 다음 교육 자료를 참조하십시오:
교육은 ESP32-C3-DevKit-RUST-1을 기반으로 합니다. 다른 Espressif 개발 보드를 사용할 수 있지만, 코드 변경과 구성 변경이 필요할 수 있습니다.
- 입문 수준의 예제:
- 고급 수준의 예제:
- 로우레벨 GPIO
- 일반적인 상황의 인터럽트
- I2C Driver
- I2C Sensor Reading
- GPIO/Button Interrupts
- RGB LED 조작
⚠️ 참고:
esp-idf-hal
의 예제 폴더 아래에 특정 주변 장치의 사용을 다루는 몇 가지 예가 있습니다. 즉,esp-idf-hal/examples
.
개발도구
이제 필요한 종속성을 설치했고, 템플릿 프로젝트를 생성하는 방법을 알고 있기 때문에, 몇 가지 도구를 더 자세히 다룰 것입니다. 이 도구들은 Espressif chips을 위한 Rust 애플리케이션을 훨씬 쉽게 개발할 것이다.
이 장에서, 우리는 espflash
/cargo-espflash
를 제시하고, Visual Studio Code를 IDE로 제안하고, 현재 사용 가능한 시뮬레이션 및 디버깅 방법을 파헤칠 것입니다.
Visual Studio Code
더 일반적인 개발 환경 중 하나는 RA라고도 알려진 Rust Analyzer와 함께 Microsoft의 Visual Studio Code 텍스트 편집기입니다.
Visual Studio Code는 풍부한 확장 생태계를 갖춘 오픈 소스 및 크로스 플랫폼 그래픽 텍스트 편집기입니다. Rust Analyzer extension은 Rust를 위한 언어 서버 프로토콜의 구현을 제공하며 자동 완성, 이동 정의 등과 같은 기능을 추가로 포함합니다.
Visual Studio Code는 가장 인기 있는 패키지 관리자를 통해 설치할 수 있으며, 설치 프로그램은 공식 웹사이트에서 사용할 수 있습니다. Rust Analyzer extension은 내장된 확장 관리자를 통해 Visual Studio Code에 설치할 수 있습니다.
Rust Analyzer와 함께 도움이 될 수 있는 다른 extension들이 있습니다:
- TOML 기반 구성 파일 편집을 위한 Even Better TOML
- Rust dependencies 관리를 도와주는 crates
팁과 요령
no_std
에서의 Rust Analyzer 사용하기
std
를 지원하지 않는 대상을 위해 개발하는 경우, Rust Analyzer는 이상하게 동작할 수 있으며, 종종 다양한 오류를 보고합니다. 이것은 프로젝트에 .vscode/settings.json
파일을 만들고 다음을 채워서 해결할 수 있습니다:
{
"rust-analyzer.checkOnSave.allTargets": false
}
Cargo Hints When Using Custom Toolchains
커스텀 툴체인을 사용할때 Cargo hints
Xtensa
대상과 마찬가지로 사용자 지정 툴체인을 사용하는 경우, 사용자 경험을 개선하기 위해 rust-toolchain.toml
파일을 통해 cargo
에 몇 가지 힌트를 제공할 수 있습니다.
[toolchain]
channel = "esp"
components = ["rustfmt", "rustc-dev"]
targets = ["xtensa-esp32-none-elf"]
다른 IDE들
우리는 Rust를 잘 지원하고 개발자들 사이에서 인기가 있기 때문에 VS Code를 다루기로 결정했습니다. CLion과 vim과 같은 유사한 Rust를 지원하는 다른 IDE도 있지만, 이는 이 책의 범위를 벗어납니다.
espflash
espflash
는 Espressif SoCs 와 modules을 위한 esptool.py를 기반으로 하는 시리얼 플래시 usb 유틸리티입니다.
espflash
저장소에는 두 개의 crate들, cargo-espflash
와 espflash
가 포함되어 있습니다. 이 crate 대한 자세한 내용은 아래의 각 섹션을 참조하십시오.
⚠️ Note: 아래에 표시된
espflash
및cargo-espflash
명령은 버전2.0
이상이 사용되었다고 가정합니다.
cargo-espflash
교차 컴파일과 플래싱을 처리하는 cargo
에 대한 하위 명령을 제공합니다.
cargo-espflash
를 설치하려면, 필요한 종속성이 설치되어 있는지 확인한 다음, 다음 명령을 실행하십시오:
cargo install cargo-espflash
이 명령은 Cargo 프로젝트, 즉 Cargo.toml
파일이 포함된 디렉토리 내에서 실행되어야 합니다. 예를 들어, 'blinky'라는 예제를 만들려면, 결과 바이너리를 장치에 플래시한 다음, 시리얼 모니터를 시작하십시오:
cargo espflash flash --example=blinky --monitor
자세한 내용은 cargo-espflash
README를 참조하십시오.
espflash
ELF 파일을 장치에 플래시하는 독립형 명령줄 애플리케이션을 제공합니다.
espflash
를 설치하려면, 필요한 종속성이 설치되어 있는지 확인한 다음, 다음 명령을 실행하십시오:
cargo install espflash
이미 다른 방법으로 ELF 바이너리를 구축했다고 가정하면, 특히 espflash
를 사용하여 장치에 다운로드하고 시리얼 포트를 모니터링할 수 있습니다. 예를 들어, idf.py
를 사용하여 ESP-IDF에서 getting-started/blinky
예제를 구축했다면, 다음과 같은 것을 실행할 수 있습니다:
espflash flash build/blinky --monitor
자세한 내용은 espflash
README를 참조하십시오.
espflash
는 프로젝트의 .cargo/config.toml
파일에 다음을 추가하여 Cargo runner로 사용할 수 있습니다.
[target.'cfg(any(target_arch = "riscv32", target_arch = "xtensa"))']
runner = "espflash flash --monitor"
이 구성을 사용하면 cargo run
을 사용하여 애플리케이션을 플래시하고 모니터링할 수 있습니다.
디버깅
이 장에서 다룰 다른 도구를 사용하여 러스트 응용 프로그램을 디버깅하는 것도 가능합니다.
모든 디버깅 방법에서 어떤 칩이 지원되는지 보려면 아래 표를 참조하십시오:
probe-rs | OpenOCD | |
---|---|---|
ESP32 | ⏳ | ✅ |
ESP32-C2 | ✅ | ✅ |
ESP32-C3 | ✅ | ✅ |
ESP32-C6 | ✅ | ✅ |
ESP32-H2 | ✅ | ✅ |
ESP32-S2 | ✅ | ✅ |
ESP32-S3 | ✅ | ✅ |
USB-JTAG-SERIAL
Peripheral
우리의 최근 제품 중 일부는 외부 하드웨어 디버거 없이 디버깅할 수 있는 USB-JTAG-SERIAL
주변 장치를 포함합니다. 인터페이스 구성에 대한 자세한 정보는 이 주변 장치를 지원하는 칩의 공식 문서에서 찾을 수 있습니다:
-
- 내장 JTAG 인터페이스의 가용성은 ESP32-C3 개정판에 따라 다릅니다:
- 0.3보다 오래된 개정판에는 JTAG 인터페이스가 내장되어 있지 않습니다.
- 개정판 0.3(및 그 이상)에는 JTAG 인터페이스가 내장되어 있으며, 디버깅하기 위해 외부 장치를 연결할 필요가 없습니다.
ESP32-C3 개정판을 찾으려면, 다음을 실행하세요:
cargo espflash board-info # or espflash board-info
- 내장 JTAG 인터페이스의 가용성은 ESP32-C3 개정판에 따라 다릅니다:
probe-rs
probe-rs
프로젝트는 다양한 디버그 프로브를 사용하여 임베디드 MCU와 상호 작용하는 도구 세트입니다. 그것은 OpenOCD, pyOCD, Segger tools 등과 유사하다. 다음을 포함하되 이에 국한되지 않는 도구 모음과 함께 ARM
& RISC-V
아키텍처에 대한 지원이 있습니다.
-
디버거
- GDB 지원.
- 대화형 디버깅을 위한 CLI.
- VS Code 익스텐션.
-
- IDF의
app_trace
구성 요소와 유사하다.
- IDF의
-
[Flash-algorithm][https://github.com/probe-rs/flash-algorithm.git]
probe-rs
웹사이트의 설치 및 셋업 지침을 따르세요.
USB-JTAG-SERIAL
peripheral 장치가 포함된 Espressif 제품은 외부 하드웨어 없이 probe-rs
를 사용할 수 있습니다.
probe-rs
으로 플래싱하기
probe-rs
는 ESP-IDF image format을 지원하기 때문에 대상에 어플리케이션을 플래시하는 데 사용할 수 있습니다.
- ESP32-C3 플래싱하는 명령어 예제:
probe-rs run --chip esp32c3
flash 명령은 프로젝트의 .cargo/config.toml
파일에 다음을 추가하여 사용자 지정 Cargo runner로 설정할 수 있습니다.
[target.'cfg(any(target_arch = "riscv32", target_arch = "xtensa"))']
runner = "probe-rs run --chip esp32c3"
이 구성을 사용하면 cargo run
을 사용하여 애플리케이션을 플래시하고 모니터링할 수 있습니다.
VS Code 익스텐션
VS 코드에는 probe-rs
확장이 있습니다. 설치, 구성 및 사용 방법에 대한 자세한 내용은 probe-rs
VS Code 문서를 참조하십시오.
launch.json
예제
{
"version": "0.2.0",
"configurations": [
{
"type": "probe-rs-debug",
"request": "launch",
"name": "Launch",
"cwd": "${workspaceFolder}",
"chip": "esp32c3", //!MODIFY
"flashingConfig": {
"flashingEnabled": true,
"resetAfterFlashing": true,
"haltAfterReset": true,
"formatOptions": {
"format": "idf" //!MODIFY (or remove). Valid values are: 'elf'(default), 'idf'
}
},
"coreConfigs": [
{
"coreIndex": 0,
"programBinary": "target/riscv32imc-unknown-none-elf/debug/${workspaceFolderBasename}", //!MODIFY
"rttEnabled": true,
"rttChannelFormats": [
{
"channelNumber": 0,
"dataFormat": "String",
"showTimestamp": true,
}
]
}
]
},
{
"type": "probe-rs-debug",
"request": "attach",
"name": "Attach",
"cwd": "${workspaceFolder}",
"chip": "esp32c3", //!MODIFY
"coreConfigs": [
{
"coreIndex": 0,
"programBinary": "target/riscv32imc-unknown-none-elf/debug/${workspaceFolderBasename}", //!MODIFY
"rttEnabled": true,
"rttChannelFormats": [
{
"channelNumber": 0,
"dataFormat": "String",
"showTimestamp": true,
}
]
}
]
}
]
}
⚠️ 참고: 예제
launch.json
은rtt
를 사용하며,esp-println
및esp-backtrace
와 같은 일부 상자에서 이러한 기능을 활성화해야 할 수 있습니다.esp-println
및esp-backtrace
를 사용하는 ESP32-C3no_std
프로젝트 예제:esp-backtrace = { version = "0.9.0", features = ["esp32c3", "panic-handler", "exception-handler", "print-rtt"] } esp-println = { version = "0.7.0", features = ["esp32c3", "rtt"], default-features = flase }
Launch
구성은 장치를 플래시하고 디버깅 프로세스를 시작하는 반면 Attach
는 이미 실행 중인 장치의 응용 프로그램에서 디버깅을 시작합니다. 자세한 내용은 launch와 attach의 차이점 에 대한 VS Code 문서를 참조하십시오.
cargo-flash
와 cargo-embed
probe-rs
는 이 두 가지 도구와 함께 제공됩니다:
cargo-flash
: 빌드된 바이너리를 타겟에 다운로드하고 실행하는 플래시 도구.cargo-embed
: RTT 터미널이나 GDB 서버를 열 수 있는cargo-flash
의 슈퍼셋. configuration file은 동작을 정의하는 데 사용할 수 있다.
GDB Integration
probe-rs
에는 일반적인 도구로 일반적인 워크플로우에 통합할 수 있는 GDB 스텁이 포함되어 있습니다. probe-rs gdb
명령은 기본적으로 포트 1337
에서 GDB 서버를 실행합니다.
지원되는 모든 Espressif 제품이 있는 GDB는 espressif/binutils-gdb
에서 얻을 수 있습니다.
OpenOCD
probe-rs
와 마찬가지로, OpenOCD는 Xtensa
아키텍처를 지원하지 않습니다. 그러나, Espressif는 Espressif의 칩을 지원하는 espressif/openocd-esp32
리포지토리에서 OpenOCD의 fork 리포지토리를 유지합니다.
플랫폼에 openocd-esp32
를 설치하는 방법에 대한 지침은 Espressif 문서에서 찾을 수 있습니다.
지원되는 모든 Espressif 제품이 있는 GDB는 espressif/binutils-gdb
에서 얻을 수 있습니다.
일단 설치되면, 올바른 인수로 openocd
를 실행하는 것만큼 간단합니다. USB-JTAG-SERIAL
peripheral 장치가 내장된 칩의 경우, 일반적으로 ESP32-C3에서 즉시 작동하는 구성 파일이 있습니다.
openocd -f board/esp32c3-builtin.cfg
다른 구성의 경우, 칩과 인터페이스를 지정해야 할 수 있습니다. 예를 들어, J-Link가 있는 ESP32:
openocd -f interface/jlink.cfg -f target/esp32.cfg
VS Code Extension
OpenOCD는 Espressif 제품을 디버깅하기 위해 cortex-debug
확장을 통해 VS 코드에서 사용할 수 있습니다.
Configuration
- 필요한 경우, 외부 JTAG 어댑터를 연결하세요.
- ESP-IDF 프로그래밍 가이드의 다른 JTAG 인터페이스 구성 섹션을 참조하십시오. 예: Section for ESP32
⚠️ Note: Windows에서는,
USB Serial Converter A 0403 6010 00
드라이버가 WinUSB이어야 합니다.
- VSCode 설정하기
- Cortex-Debug VS Code 확장 익스텐션 설치하기.
- 디버그하려는 프로젝트 트리에
.vscode/launch.json
파일을 만드세요. executable
,svdFile
,serverpath
및toolchainPrefix
필드를 업데이트하십시오.
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
// more info at: https://github.com/Marus/cortex-debug/blob/master/package.json
"name": "Attach",
"type": "cortex-debug",
"request": "attach", // launch will fail when attempting to download the app into the target
"cwd": "${workspaceRoot}",
"executable": "target/xtensa-esp32-none-elf/debug/.....", //!MODIFY
"servertype": "openocd",
"interface": "jtag",
"toolchainPrefix": "xtensa-esp32-elf", //!MODIFY
"openOCDPreConfigLaunchCommands": ["set ESP_RTOS none"],
"serverpath": "C:/Espressif/tools/openocd-esp32/v0.11.0-esp32-20220411/openocd-esp32/bin/openocd.exe", //!MODIFY
"gdbPath": "C:/Espressif/tools/riscv32-esp-elf-gdb/riscv32-esp-elf-gdb/bin/riscv32-esp-elf-gdb.exe", //!MODIFY
"configFiles": ["board/esp32-wrover-kit-3.3v.cfg"], //!MODIFY
"overrideAttachCommands": [
"set remote hardware-watchpoint-limit 2",
"mon halt",
"flushregs"
],
"overrideRestartCommands": ["mon reset halt", "flushregs", "c"]
}
]
}
여러 코어들을 디버깅하기
때때로 GDB 또는 VSCode에서 각 코어를 개별적으로 디버깅해야 할 수도 있습니다. 이 경우, set ESP_RTOS none
을 set ESP_RTOS hwthread
으로 바꾸십시오. 이것은 각 코어를 GDB의 하드웨어 스레드로 보이게 할 것이다. 이것은 현재 Espressif 공식 문서에 문서화되어 있지 않지만 OpenOCD 문서에 문서화되어 있습니다: https://openocd.org/doc/html/GDB-and-OpenOCD.html
시뮬레이팅
프로젝트를 시뮬레이션하는 것은 편리할 수 있다. 그것은 사용자가 CI를 사용하여 프로젝트를 테스트하고, 하드웨어를 사용할 수 없는 프로젝트와 다른 많은 시나리오를 시도할 수 있게 해준다.
현재, Espressif 칩에서 Rust 프로젝트를 시뮬레이션하는 몇 가지 방법이 있다. 모든 방법에는 몇 가지 한계가 있지만, 빠르게 진화하고 매일 나아지고 있다.
이 장에서, 우리는 현재 사용 가능한 시뮬레이션 도구에 대해 논의할 것이다.
모든 시뮬레이션 방법에서 어떤 칩이 지원되는지 보려면 아래 표를 참조하십시오:
Wokwi | QEMU | |
---|---|---|
ESP32 | ✅ | ✅ |
ESP32-C2 | ❌ | ❌ |
ESP32-C3 | ✅ | ❌ |
ESP32-C6 | ✅ | ❌ |
ESP32-H2 | ✅ | ❌ |
ESP32-S2 | ✅ | ❌ |
ESP32-S3 | ✅ | ❌ |
Wokwi
Wokwi는 Espressif Chips에서 Rust 프로젝트(std
및 no_std
모두) 시뮬레이션을 지원하는 온라인 시뮬레이터입니다. 예시 목록과 새로운 프로젝트를 시작하는 방법은 wokwi.com/rust를 참조하십시오.
Wokwi는 다른 많은 기능 중에서 Wi-Fi 시뮬레이션, 가상 로직 분석기 및 GDB debugging을 제공합니다. 자세한 내용은 Wokwi 문서를 참조하십시오. ESP 칩의 경우, 현재 지원되는 시뮬레이션 기능 표가 있습니다.
Wokwi VS Code 확장프로그램 사용하기
Wokwi는 몇 개의 파일만 추가하여 코드 편집기에서 직접 프로젝트를 시뮬레이션할 수 있는 VS 코드 확장 프로그램을 제공합니다. 자세한 내용은 Wokwi 문서를 참조하십시오. VS 코드 디버거를 사용하여 코드를 디버깅할 수도 있습니다. 코드 디버깅을 참조하십시오.
templates을 사용하고 기본값을 사용하지 않을 때, 프롬프트가 있습니다 (Wokwi VS Code 확장으로 Wokwi 시뮬레이션을 지원하는 프로젝트 구성
) Wokwi VS Code 확장자를 사용하는 데 필요한 파일을 생성합니다.
Using wokwi-server
wokwi-server
는 프로젝트의 Wokwi 시뮬레이션을 시작하기 위한 CLI 도구입니다. 즉, 기계나 컨테이너에 프로젝트를 구축하고 결과 바이너리를 시뮬레이션할 수 있습니다.
wokwi-server
는 또한 칩 자체 이외의 더 많은 하드웨어 부품으로 다른 Wokwi 프로젝트에서 결과 바이너리를 시뮬레이션할 수 있습니다. 자세한 지침은 wokwi-server
README의 해당 섹션을 참조하십시오.
커스텀 칩들
Wokwi는 Wokwi에서 지원되지 않는 구성 요소의 동작을 프로그래밍할 수 있는 사용자 지정 칩을 생성할 수 있습니다. 자세한 내용은 공식 Wokwi 문서를 참조하십시오.
커스텀 칩은 Rust로도 쓸 수 있습니다! 자세한 내용은 Wokwi Custom Chip API를 참조하십시오. 예를 들어, Rust의 커스텀 inverter chip.
QEMU
Espressif는 Espressif 칩에서 작동하도록 필요한 패치와 함께 espressif/QEMU에서 QEMU 포크를 유지합니다. QEMU를 구축하고 프로젝트를 에뮬레이트하는 방법에 대한 지침은 QEMU wiki를 참조하십시오.
QEMU를 구축하면, qemu-system-xtensa
파일이 있어야 합니다.
프로젝트를 QEMU에서 실행하기
⚠️ Note: 현재 ESP32만 지원되므로,
xtensa-esp32-espidf
대상을 위해 컴파일하고 있는지 확인하세요.
QEMU에서 프로젝트를 실행하려면 부트로더와 파티션 테이블이 병합된 펌웨어/이미지가 필요합니다. 우리는 그것을 생성하기 위해 cargo-espflash
를 사용할 수 있습니다:
cargo espflash save-image --chip esp32 --merge <OUTFILE> --release
espflash
를 사용하는 것을 선호한다면, 먼저 프로젝트를 구축한 다음 이미지를 생성하여 동일한 결과를 얻을 수 있습니다.
cargo build --release
espflash save-image --merge ESP32 target/xtensa-esp32-espidf/release/<NAME> <OUTFILE>
이제, QEMU에서 이미지를 실행하세요:
/path/to/qemu-system-xtensa -nographic -machine esp32 -drive file=<OUTFILE>,if=mtd,format=raw
문제 해결
이 장에서는 우리가 시간이 지남에 따라 직면한 특정 질문과 일반적인 문제, 그리고 그들의 해결책과 함께 나열합니다. 이 페이지는 선택된 ESP 생태계와 독립적인 일반적인 문제를 수집합니다. 여기에 나열된 문제를 찾을 수 없다면, 적절한 저장소에서 문제를 열거나 Matrix room에서 문의하십시오.
잘못된 Rust Toolchain 사용
$ cargo build
error: failed to run `rustc` to learn about target-specific information
Caused by:
process didn't exit successfully: `rustc - --crate-name ___ --print=file-names --target xtensa-esp32-espidf --crate-type bin --crate-type rlib --crate-type dylib --crate-type cdylib --crate-type staticlib --crate-type proc-macro --print=sysroot --print=cfg` (exit status: 1)
--- stderr
error: Error loading target specification: Could not find specification for target "xtensa-esp32-espidf". Run `rustc --print target-list` for a list of built-in targets
이전 오류나 유사한 오류가 발생한다면, 아마도 적절한 Rust 툴체인을 사용하지 않을 것입니다. Xtensa
대상의 경우, Espressif Rust 포크 툴체인을 사용해야 한다는 것을 기억하세요. 몇 가지 방법이 있습니다:
-
커맨드 라인에서 툴체인 단축키 재정의:
cargo +esp
. -
RUSTUP_TOOLCHAIN
환경 변수를esp
로 설정하세요. -
디렉토리 재정의 설정:
rustup 재정의 세트 esp
-
프로젝트에
rust-toolchain.toml
파일을 추가하세요:[toolchain] channel = "esp"
-
esp
를 디폴트 툴체인으로 세팅한다.
툴체인 재정의에 대한 자세한 내용은 The rustup book의 재정의 장을 참조하십시오.
Windows
긴 Path 네임
Windows를 사용할 때, 긴 경로 이름을 사용하는 경우 새 프로젝트를 구축하는 데 문제가 발생할 수 있습니다. 게다가 - 그리고 std
애플리케이션을 빌드하려고 하는 경우 - 프로젝트 경로가 ~ 10자보다 길면 빌드가 어려운 오류와 함께 실패합니다.
문제를 해결하려면 프로젝트 이름을 줄이고 드라이브 루트로 옮겨야 합니다. C:\myproj
. 또한 Windows subst
유틸리티(예: subst r: <pathToYourProject>
)를 사용하는 동안 프로젝트 위치를 그대로 유지하면서 빌드 중에 짧은 경로를 사용하는 쉬운 솔루션처럼 보일 수 있지만, 짧고 대체된 경로가 Windows API에 의해 실제 (긴) 위치로 확장되기 때문에 작동하지 않습니다.
또 다른 대안은 Linux용 Windows 하위 시스템(WSL)을 설치하고, 네이티브 Linux 파일 파티션 내부로 프로젝트를 이동하고, WSL 내부에 빌드하고, WSL 외부에서 컴파일된 MCU ELF 파일만 플래시하는 것입니다.
Missing ABI
Compiling cc v1.0.69
error: linker `link.exe` not found
|
= note: The system cannot find the file specified. (os error 2)
note: the msvc targets depend on the msvc linker but `link.exe` was not found
note: please ensure that VS 2013, VS 2015, VS 2017 or VS 2019 was installed with the Visual C++ option
error: could not compile `compiler_builtins` due to previous error
warning: build failed, waiting for other jobs to finish...
error: build failed
이 오류의 이유는 MSVC C++가 누락되어 컴파일 시간 요구 사항을 충족하지 못하기 때문입니다. [Visual Studio 2013(또는 그 이상) 또는 Visual C++ Build Tools 2019][ Visual Studio 2013 (or later) or the Visual C++ Build Tools 2019]를 설치하십시오. 비주얼 스튜디오의 경우, "C++ 도구"와 "윈도우 10 SDK" 옵션을 확인하세요. GNU ABI를 사용하는 경우, MinGW/MSYS2 툴체인을 설치하세요.
esp-idf-hal
기반 프로젝트들
LIBCLANG_PATH
환경변수가 정의되지않았을때
thread 'main' panicked at 'Unable to find libclang: "couldn't find any valid shared libraries matching: ['libclang.so', 'libclang-*.so', 'libclang.so.*', 'libclang-*.so.*'], set the `LIBCLANG_PATH` environment variable to a path where one of these files can be found (invalid: [])"', /home/esp/.cargo/registry/src/github.com-1ecc6299db9ec823/bindgen-0.60.1/src/lib.rs:2172:31
우리는 bindgen
이 ESP-IDF C 헤더에 Rust 바인딩을 생성하기 위해 libclang
이 필요합니다. Espup
에서 생성된 내보내기 파일을 소싱했는지 확인하십시오. 환경 변수 설정을 참조하십시오.
ldproxy
가 보이지않을때
error: linker `ldproxy` not found
|
= note: No such file or directory (os error 2)
std
애플리케이션을 구축하려는 경우 ldproxy를 설치해야 합니다. std
개발 요구 사항 보기
cargo install ldproxy
sdkconfig.defaults
파일이 업데이트되었지만 아무런 영향을 미치지 않는 것으로 나타남
적용하려면 sdkconfig.defaults
의 변경 사항을 위해 프로젝트를 정리하고 재구성해야 합니다.
cargo clean
cargo build
이 페이지에 언급된 Crate에 대한 문서가 오래되었거나 누락되었습니다
docs.rs에 의해 부과된 자원 제한으로 인해, 문서를 작성하는 동안 인터넷 접속이 차단됩니다. 이러한 이유로, 우리는 esp-idf-sys
또는 그것에 따라 어떤 crate에도 대한 문서를 만들 수 없습니다.
대신, 우리는 문서를 만들고 GitHub 페이지에서 직접 호스팅하고 있습니다:
작업 main
의 스택 오버플로가 감지되었습니다
2단계 부트로더가 이 오류를 보고한다면, 주요 작업에 대한 스택 크기를 늘려야 할 것입니다. 이것은 sdkconfig.defaults
파일에 다음을 추가하여 수행할 수 있습니다:
CONFIG_ESP_MAIN_TASK_STACK_SIZE=7000
이 예에서, 우리는 주요 작업의 스택에 7kB를 할당하고 있다.
워치독 타이머를 비활성화하는 방법?
sdkconfig.defaults
파일에 추가하세요:
CONFIG_INT_WDT=n
CONFIG_ESP_TASK_WDT=n
이러한 구성 파일을 수정할 때 재구축하기 전에 프로젝트를 정리해야 한다는 것을 기억하세요.
espflash
rtc_clk_init: Possibly invalid CONFIG_XTAL_FREQ setting
이 문제는 26MHz 크리스탈 오실레이터가 있는 ESP32 모듈을 사용하는 사용자에 의해 보고됩니다. 이 문제의 근본 원인은 espflash에 의해 깜박이는 기본 부트로더가 40MHz 크리스탈을 예상한다는 것이다.
esp-idf-sys
기반 프로젝트 빌드하는 경우
26MHz 크리스탈을 사용하도록 sdkconfig
가 제대로 설정되어 있는지 확인하세요. 다음과 같은 구성 옵션을 포함해야 합니다:
CONFIG_XTAL_FREQ_26=y
또한 espflash
보다 cargo-espflash
를 사용하는 것을 선호해야 합니다. cargo-espflash
는 프로젝트와 통합되며 기본 부팅 로더 대신 프로젝트 옆에 내장된 부트로더를 플래시합니다.
espflash
를 사용하려면, --bootloader
를 사용하여 적절한 부트로더 이미지를 지정해야 합니다. target/<MCU의 대상 폴더>/<빌드에 따라 디버그 또는 릴리스>/build/esp-idf-sys-*/build/bootloader/bootloader.bin
에서 부트로더를 찾을 수 있습니다.
esp-hal
기반 프로젝트를 구축하는 경우
HAL(ESP32, ESP32-C2)이 올바른 결정 주파수로 구성되어 있는지 확인하세요. 이렇게 하려면, 기본 기능을 비활성화하고 xtal-26mhz
를 활성화해야 합니다(다른 기본 기능 외에).
flasing 일때, --bootloader
를 사용하여 적절한 부트로더 이미지를 지정해야 합니다. 현재 esp-idf
기반 프로젝트를 사용하여 이 부트로더를 구축해야 합니다(Rust 또는 C 기반은 동등하게 작동해야 하며, esp-idf-template로 설정된 프로젝트를 권장합니다).