Category (Click)
개발보드 덕질하기

WWDC24 Swift for Embedded 개발환경 설정 및 테스트 (feat. ESP32-C6)

 차완기 - @6/17/2024, 12:37:00 AM

아 ㅋㅋ 임베디드가 뭔 Swi..어라?

요즈음 Apple의 개발자 회의, WWDC24가 한창입니다.
임베디드 개발을 주로 하다 보니 Apple 소프트웨어와 관련된 WWDC는 관심을 딱히 가지지 않는 편인데요, 어느 날 침대에 엎어져 유튜브를 슥슥 내리다가 이상한 걸 발견하게 되었습니다.
??????
에이에이 아니겠지 누군가가 참신하게 포팅했겠지 하며 클릭했지만, 돌아온 것은 Apple 공식 마크였습니다.
Apple Developer - Embedded Swift로 경량화하기 [링크]
Swift.. 이거 Apple 앱 만들 때 쓰는 거 아니었나요..?
Rust도 슬슬 준비해야 하는데 Apple은 도대체 왜 ㅜㅜ.. 임베디드 개발자에게는 그저 신기능 축제인 줄 알았는데, 그게 숙제 파티가 될 줄은 꿈에도 몰랐죠..
Apple Developer - Embedded Swift로 경량화하기 [링크]
그래도 최근 관심이 많은 Matter 예시가 있으니, 맛도 볼 겸 따라 해보기로 했습니다.
겸사겸사 왜 애플에서 갑자기 이걸 만들었는지 알 수 있으면 좋겠네요.

Swift for Embedded?

처음 이걸 보았을 때는 Swift 언어를 사용하는 Zephyr를 떠올렸는데요,
UserManual.md
EmbeddedSwift
Apple의 공식 자료에서는 ESP-IDF, Pico C SDK 등 기존에 C언어로 작성된 MCU 제조사의 SDK를 Swift 언어에서 사용할 수 있도록 하는 빌드 시스템이라고 합니다.
아두이노 코어가 빠진 아두이노 IDE 정도로 이해하면 될 것 같습니다.
개발 환경을 세팅한 후 코드를 설명하며 더 자세한 부분을 다뤄보도록 하겠습니다.

개발 환경 세팅

우리들 가운데 스파이가 있는 것 같아
다양한 Apple 기기를 가지고 있지만, 정작 어플리케이션 개발은 하지 않다 보니 개발 환경 세팅에 어려움이 있었습니다. 앞으로 쓸 일도 없는데 12GB나 차지하는 Xcode를 끝까지 설치하지 않고 버티다가 많은 삽질을 하게 되었습니다. 결국 설치했습니다.
글을 작성하는 현재 시점에서 Swift 6.0은 preview 상태입니다. 정식 출시 후 개발 환경 설정 과정이 다를 수 있으니 주의해주세요.
LED와 스위치를 동시에 사용하는 예제 코드를 작성했습니다. 개발환경 세팅 과정에서 아래 리포지토리를 사용합니다.
Swift - Development Snapshots [링크]
Swift 공식 홈페이지의 GET Started에서 Swift 6.0 툴 체인을 다운로드 받습니다.
파일이 꽤 큰 편인데요, 다운로드가 완료되면 더블클릭해 설치합니다.
설치가 완료된 후 /Developer/Toolchains 디렉토리를 보면 새롭게 설치한 툴 체인과, 이를 가리키는 심볼릭 링크를 확인할 수 있습니다. 심볼릭 링크는 항상 가장 마지막에 설치된 툴 체인을 가리키는 것 같습니다.
다음으로 삽질의 주범인 Xcode를 설치합니다.
Xcode가 설치되어야 CMake 과정의 xcrun 커멘드가 새롭게 설치한 Swift 6.0을 사용하게 됩니다. 용량 아끼겠다고 설치하지 않으면 삽질 당첨입니다
Xcode를 실행한 후, 이 화면이 나올때 까지만 진행합니다. 이 화면이 나오면 더는 볼 일이 없으니 ㅎㅎㅎ 바로 꺼버립니다. cmd + q!
$ export TOOLCHAINS=swift
Bash
복사
터미널에서 위 명령을 입력한 이후 Swift의 버전이 새롭게 설치한 버전으로 바뀌는 것을 확인해 주시면 됩니다.
만약 Xcode를 설치하기 전에 swift 명령을 한 번이라도 입력하면 xcode-select가 잘못된 경로로 잡힐 수 있습니다. 이 경우 아래 명령을 입력합니다.
$ sudo rm -rf /Library/Developer/CommandLineTools $ xcode-select -p /Library/Developer/CommandLineTools # 잘못된 경로 확인 $ sudo xcode-select -r (패스워드 입력) $ xcode-select -p /Applications/Xcode.app/Contents/Developer # 변경된 경로 확인
Bash
복사
VSCode에서 최신 버전(v5.2) ESP-IDF 개발 환경을 만든 후,
$ git clone https://github.com/varofla/esp32_swift_led_and_switch_example
Bash
복사
예제 코드를 clone 합니다.
빌드를 진행한 후, 업로드까지 진행합니다.

코드 설명&Swift for Embedded 구체적으로 살펴보기

앞서 짧게 언급한 것과 같이 Swift for Embedded 자체는 Swift 언어로 임베디드 개발을 할 수 있도록 도와주는 툴 체인입니다. 작성한 코드를 빌드하면 SDK를 빌드하는 동시에 Swift 툴 체인을 통해 Swift 코드가 함께 빌드되고, 두 코드가 짬뽕 된 결과물이 하나의 바이너리로 나오는 것이죠.
main/CMakeLists.txt
.vscode 디렉토리 아래의 settings.jsonTOOLCHAINS 환경변수가 swift로 설정된 것을 확인할 수 있습니다. 다른 SDK를 사용하더라도 이건 모두 동일하게 해주어야 하니 참고해 주세요.
따라서 CMakeLists.txt에 MCU 제조사의 SDK와 Swift 툴 체인을 함께 사용하도록 반영해야 합니다. CMakeLists.txt 파일을 자세히 살펴보면 Swift 툴 체인으로 빌드된 결과물을 MCU측 툴 체인에 링크하는 것을 알 수 있습니다.
main/CMakeLists.txt
여기서 CMakeLists.txt 파일을 자세히 살펴보면 Swift 툴 체인을 실행할 때 MCU 측 SDK를 담고 있는(include 한) 헤더 파일을 -import-bridging-header 옵션으로 전달하는 것을 알 수 있습니다. C언어로 작성된 코드를 Swift로 bridging 하는 것인데요, 이를 전달받은 Swift 컴파일러는 Swift 코드에 사용된 C언어 함수를 Swift에 맞는 타입으로 변환하며 컴파일합니다.
한편, Swift for Embedded 자체는 MCU의 Peripheral를 직접적으로 제어하는 기능을 지원하지 않습니다. Zephyr와는 다르다는 것이죠. 이러한 이유로 위와 같이 HAL과 비슷한 코드를 작성해야 합니다. (물론 APP 코드에 bridging 된 C API를 그대로 사용해도 되지만.. 그건 양심에 찔리죠 ㅋㅋ )
main/Main.swift 중 일부
여기서는 ESP32-C6이기 때문에 ESP-IDF의 GPIO 드라이버를 사용했습니다.
main/Main.swift 중 일부
위에서 작성한 HAL인 LEDController를 이용해 기능을 만들어 주었습니다.
위 코드는 버튼을 클릭했을 때 LED를 토글하며 시리얼 터미널에 LED 상태 로그를 띄웁니다.

테스트

마무리

여기까지 최근 WWDC24에서 공개된 Swift for Embedded를 찍먹(?)해 보았습니다.
처음에는 “Apple에서 Swift 교육용으로 또 다른 아두이노를 만드는구나”라 생각했는데요, Docs를 자세히 읽고 직접 테스트해 보니 처음 생각하던 것과는 많이 달라지게 되었습니다.
여기까지 맛본 바로는 Apple에서 심혈을 기울여 만든, 안전하다고 평가되는 Swift 언어를 임베디드의 APP 레이어에 적용함으로써 임베디드의 C 비중을 낮추는 것이 목표가 아닌가 싶습니다. 또 다른 Rust인 셈이죠. STM32처럼 저수준의 레지스터 제어를 직접 지원하는 경우 APP 레이어 뿐만 아니라 HAL 레이어까지 커버할 수 있게 되니 이런 개발 환경에는 꽤 의미있을 것 같습니다.
물론 위가 만족되기 위해서는 믿을 수 있는 HAL이 작성되어야겠죠.
ESP32의 Rust HAL처럼 MCU 제조사에서 Swift HAL을 작성해 준다면 가장 좋을텐데.. 이게 얼마나 잘 지원되느냐에 따라 희망편 아두이노가 되거나 절망편..아두이노가 될 것 같습니다. ESP-HAL의 스타 수를 보면.. 🫠
아무튼 맛을 보기 시작했으니, 끝을 봐야겠죠. 기본 예제인 Matter 쪽을 살펴보는 포스팅으로 돌아오겠습니다.