Skip to content

NuttX RV32 (QEMU) - Example #64

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions .github/workflows/build-nuttx.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Build NuttX Examples

on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
schedule:
# Build on Mondays at 9am PST every week
- cron: '0 17 * * 1'

jobs:
build-nuttx:
runs-on: ubuntu-24.04

strategy:
fail-fast: false
matrix:
example: [nuttx-riscv-blink]
swift: [swift-DEVELOPMENT-SNAPSHOT-2024-12-22-a]

steps:
- name: Checkout repo
uses: actions/checkout@v4

- name: Install apt dependencies
run: |
sudo apt-get -qq update && sudo apt-get -qq -y install \
bison flex gettext texinfo libncurses5-dev libncursesw5-dev \
gperf automake libtool pkg-config build-essential gperf genromfs \
libgmp-dev libmpc-dev libmpfr-dev libisl-dev binutils-dev libelf-dev \
libexpat-dev gcc-multilib g++-multilib u-boot-tools util-linux \
kconfig-frontends ninja-build

- name: Install CMake 3.30.2
run: |
ARCH=`uname -m`
curl -sL https://github.com/Kitware/CMake/releases/download/v3.30.2/cmake-3.30.2-linux-$ARCH.tar.gz -O
tar xzf cmake-3.30.2-linux-$ARCH.tar.gz
export PATH="`pwd`/cmake-3.30.2-linux-$ARCH/bin:$PATH"
echo "PATH=$PATH" >> $GITHUB_ENV
cmake --version

- name: Install RISC-V toolchain
run: |
mkdir -p riscv-none-elf-gcc && \
curl -s -L "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-2/xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz" \
| tar -C riscv-none-elf-gcc --strip-components 1 -xz
export PATH="$PATH:`pwd`/riscv-none-elf-gcc/bin/"
echo "PATH=$PATH" >> $GITHUB_ENV
riscv-none-elf-gcc --version

- name: Install ${{ matrix.swift }}
run: |
wget -q https://download.swift.org/development/ubuntu2404/${{ matrix.swift }}/${{ matrix.swift }}-ubuntu24.04.tar.gz
tar xzf ${{ matrix.swift }}-ubuntu24.04.tar.gz
export PATH="`pwd`/${{ matrix.swift }}-ubuntu24.04/usr/bin/:$PATH"
echo "PATH=$PATH" >> $GITHUB_ENV
swiftc --version

- name: Config ${{ matrix.example }}
working-directory: ${{ matrix.example }}
run: cmake -B build -GNinja -DBOARD_CONFIG=rv-virt:leds_swift -DENABLE_NUTTX_TRACE=ON

- name: Build ${{ matrix.example }}
working-directory: ${{ matrix.example }}
run: cmake --build build
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,20 @@ Each example in this repository contains build and deployment instructions, howe

| Name | Platform | SDK | Description | Photo |
| ---- | -------- | --- | ----------- | ----- |
| [esp32-led-blink-sdk](./esp32-led-blink-sdk) | ESP32-C6-Bug | ESP-IDF SDK | Blink an LED repeatedly with Swift & the ESP-IDF. | <img width="300" src="esp32-led-blink-sdk/assets/images/ledon.jpg"> |
| [esp32-led-strip-sdk](./esp32-led-strip-sdk) | ESP32-C6-DevKitC-1 | ESP-IDF SDK | Control NeoPixel LEDs with Swift & the ESP-IDF. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/15f8a3e0-953e-426d-ad2d-3902baf859be"> |
| [nrfx-blink-sdk](./nrfx-blink-sdk) | nRF52840-DK | Zephyr SDK | Blink an LED repeatedly with Swift & Zephyr. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/ae3ff153-dd33-4460-8a08-4eac442bf7b0"> |
| [nuttx-riscv-blink] | QEMU | NuttX | Blink a virualized led in QEMU using the Apache NuttX RTOS | |
| [pico-blink-sdk](./pico-blink-sdk) | Raspberry Pi Pico, Pico 2 | Pico SDK | Blink an LED repeatedly with Swift & the Pico SDK. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/f2c45c18-f9a4-48b4-a941-1298ecc942cb"> |
| [pico-blink](./pico-blink) | Raspberry Pi Pico | None | Blink an LED repeatedly. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/f2c45c18-f9a4-48b4-a941-1298ecc942cb"> |
| [pico-w-blink-sdk](./pico-w-blink-sdk) | Raspberry Pi Pico W | Pico SDK | Blink an LED to signal 'SOS' in Morse code repeatedly with Swift & the Pico SDK. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/26223064/a4949a2e-1887-4325-8f5f-a681963c93d7"> |
| [pico2-neopixel](./pico2-neopixel) | Raspberry Pi Pico 2 | None | Control Neopixel LEDs using the RP2350 PIO. | <img width="300" src="pico2-neopixel/assets/images/example.jpg"> |
| [stm32-blink](./stm32-blink) | STM32F746G-DISCO | None | Blink an LED repeatedly. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/739e98fd-a438-4a64-a7aa-9dddee25034b"> |
| [stm32-lcd-logo](./stm32-lcd-logo) | STM32F746G-DISCO | None | Animate the Swift Logo on the built-in LCD. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/9e117d81-e808-493e-a20c-7284ea630f37"> |
| [stm32-neopixel](./stm32-neopixel) | STM32F746G-DISCO | None | Control NeoPixel LEDs using SPI. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/9c5d8f74-f8aa-4632-831e-212a3e35e75a"> |
| [stm32-uart-echo](./stm32-uart-echo) | STM32F746G-DISCO | None | Echo user input using UART. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/97d3c465-9a07-4b86-9654-0c2aaaa43b3d">|
| [pico-blink](./pico-blink) | Raspberry Pi Pico | None | Blink an LED repeatedly. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/f2c45c18-f9a4-48b4-a941-1298ecc942cb"> |
| [pico-blink-sdk](./pico-blink-sdk) | Raspberry Pi Pico, Pico 2 | Pico SDK | Blink an LED repeatedly with Swift & the Pico SDK. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/f2c45c18-f9a4-48b4-a941-1298ecc942cb"> |
| [pico-w-blink-sdk](./pico-w-blink-sdk) | Raspberry Pi Pico W | Pico SDK | Blink an LED to signal 'SOS' in Morse code repeatedly with Swift & the Pico SDK. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/26223064/a4949a2e-1887-4325-8f5f-a681963c93d7"> |
| [pico2-neopixel](./pico2-neopixel) | Raspberry Pi Pico 2 | None | Control Neopixel LEDs using the RP2350 PIO. | <img width="300" src="pico2-neopixel/assets/images/example.jpg"> |
| [nrfx-blink-sdk](./nrfx-blink-sdk) | nRF52840-DK | Zephyr SDK | Blink an LED repeatedly with Swift & Zephyr. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/ae3ff153-dd33-4460-8a08-4eac442bf7b0"> |
| [esp32-led-strip-sdk](./esp32-led-strip-sdk) | ESP32-C6-DevKitC-1 | ESP-IDF SDK | Control NeoPixel LEDs with Swift & the ESP-IDF. | <img width="300" src="https://github.com/apple/swift-embedded-examples/assets/1186214/15f8a3e0-953e-426d-ad2d-3902baf859be"> |
| [esp32-led-blink-sdk](./esp32-led-blink-sdk) | ESP32-C6-Bug | ESP-IDF SDK | Blink an LED repeatedly with Swift & the ESP-IDF. | <img width="300" src="esp32-led-blink-sdk/assets/images/ledon.jpg"> |

Note that the SDK integration examples (Pico SDK, Zephyr SDK, etc.) are not recommendations or endorsement, the same is true for build system choice (Make, CMake, SwiftPM, shell scripts). Embedded Swift aims to be versatile and to allow for integration into more existing SDKs and build systems, and the example projects are merely showing the possibilities.
Note that the SDK integration examples (Pico SDK, Zephyr SDK, etc.) are not recommendations or endorsement, the same is true for build system choice (Make, CMake, SwiftPM, shell scripts). Embedded Swift aims to be versatile and allowing integration into existing SDKs and build systems, and the example projects show some of the possibilities.

## Community Examples

Expand Down
134 changes: 134 additions & 0 deletions nuttx-riscv-blink/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
cmake_minimum_required(VERSION 3.14...3.30)

project(blink
VERSION 1.0
DESCRIPTION "Blink on NuttX"
LANGUAGES Swift
)

if("${CMAKE_Swift_COMPILER_VERSION}" VERSION_LESS 6.1)
message(FATAL_ERROR "Swift 6.1 or later is required")
endif()

if(POLICY CMP0169)
# allow to call FetchContent_Populate directly
cmake_policy(SET CMP0169 OLD)
endif()

option(LIST_ALL_BOARDS "List all available boards" OFF)
option(ENABLE_NUTTX_TRACE "Enable NuttX trace" OFF)

if(ENABLE_NUTTX_TRACE)
set(TRACEFLAG "--trace")
else()
set(TRACEFLAG "")
endif()

set(FETCHCONTENT_QUIET FALSE)
include(FetchContent)
FetchContent_Declare(
apps
GIT_REPOSITORY https://github.com/apache/nuttx-apps.git
GIT_TAG nuttx-12.7.0
SOURCE_DIR ${CMAKE_BINARY_DIR}/apps
FIND_PACKAGE_ARGS
)
FetchContent_GetProperties(apps)
if(NOT apps_POPULATED)
FetchContent_Populate(apps)
endif()

FetchContent_Declare(
nuttx
GIT_REPOSITORY https://github.com/apache/nuttx.git
GIT_TAG nuttx-12.7.0
SOURCE_DIR ${CMAKE_BINARY_DIR}/nuttx
FIND_PACKAGE_ARGS
)
FetchContent_GetProperties(nuttx)
if(NOT nuttx_POPULATED)
FetchContent_Populate(nuttx)
endif()

if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
set(SCRIPT_SUFFIX .bat)
else()
set(SCRIPT_SUFFIX .sh)
endif()

if(LIST_ALL_BOARDS)
execute_process(
COMMAND ${CMAKE_COMMAND} -E chdir ${nuttx_SOURCE_DIR}
${CMAKE_COMMAND} -E env PATH=${nuttx_SOURCE_DIR}/tools:$ENV{PATH}
${nuttx_SOURCE_DIR}/tools/configure${SCRIPT_SUFFIX} -L
RESULT_VARIABLE result
)
if(result)
message(FATAL_ERROR "Failed to run tools/configure")
endif()
else()
if(NOT DEFINED BOARD_CONFIG)
message(FATAL_ERROR "Please define configuration with BOARD_CONFIG")
else()
message(STATUS "BOARD_CONFIG: ${BOARD_CONFIG}")
endif()

# Send swift-blinky example to nuttx-apps path
file(COPY ${CMAKE_SOURCE_DIR}/leds_swift DESTINATION ${apps_SOURCE_DIR}/examples)
file(COPY ${CMAKE_SOURCE_DIR}/defconfig DESTINATION ${nuttx_SOURCE_DIR}/boards/risc-v/qemu-rv/rv-virt/configs/leds_swift)

add_custom_target(distclean
COMMAND ${CMAKE_COMMAND} -E chdir ${nuttx_SOURCE_DIR}
${CMAKE_COMMAND} -E env PATH=${nuttx_SOURCE_DIR}/tools:$ENV{PATH}
make distclean
COMMENT "Clean NuttX"
)

execute_process(
COMMAND ${CMAKE_COMMAND} -E chdir ${nuttx_SOURCE_DIR}
${CMAKE_COMMAND} -E env PATH=${nuttx_SOURCE_DIR}/tools:$ENV{PATH}
${nuttx_SOURCE_DIR}/tools/configure${SCRIPT_SUFFIX} -l ${BOARD_CONFIG}
RESULT_VARIABLE result
)
if(result)
message(FATAL_ERROR "Failed to run tools/configure")
endif()

add_custom_target(copy_swift_example
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/leds_swift ${apps_SOURCE_DIR}/examples/leds_swift
COMMENT "Copying leds_swift example to nuttx-apps"
)

add_custom_target(build_nuttx ALL
COMMAND ${CMAKE_COMMAND} -E chdir ${nuttx_SOURCE_DIR}
${CMAKE_COMMAND} -E env PATH=${nuttx_SOURCE_DIR}/tools:$ENV{PATH}
make ${TRACEFLAG} -j ${JOB_POOLS}
DEPENDS copy_swift_example
COMMENT "Building NuttX"
)

add_custom_command(
TARGET build_nuttx
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${nuttx_SOURCE_DIR}/nuttx ${CMAKE_BINARY_DIR}/nuttx.elf
)

add_custom_target(export_nuttx
COMMAND ${CMAKE_COMMAND} -E chdir ${nuttx_SOURCE_DIR}
${CMAKE_COMMAND} -E env PATH=${nuttx_SOURCE_DIR}/tools:$ENV{PATH}
make export
COMMENT "Exporting NuttX"
)

add_custom_target(extract_nuttx_export
COMMAND ${CMAKE_COMMAND} -E tar xzf ${nuttx_SOURCE_DIR}/nuttx-export-12.7.0.tar.gz
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E remove ${nuttx_SOURCE_DIR}/nuttx-export-12.7.0.tar.gz
DEPENDS export_nuttx
COMMENT "Extracting NuttX export"
)

add_custom_target(nuttx-libs
DEPENDS build_nuttx export_nuttx extract_nuttx_export
)
endif()
71 changes: 71 additions & 0 deletions nuttx-riscv-blink/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Swift 6 on NuttX RTOS using CMake

## Description

Run blink rv32-blink_leds (QEMU) example on NuttX RTOS.

> [!NOTE]
> CMake is adapted to build NuttX and NuttX-apps (Makefiles) with Swift 6.

## Requirements

- [NuttX](https://github.com/apache/nuttx) & [NuttX-apps](https://github.com/apache/nuttx-apps)
- [kconfig-frontends](https://bitbucket.org/nuttx/tools)
- [CMake](https://cmake.org/download/)
- [QEMU](https://www.qemu.org/)
- [Swift 6](https://swift.org/download/) - Swift 6.1 or greater
- [RISC-V GNU Toolchain](https://github.com/riscv-collab/riscv-gnu-toolchain/releases)

## How to build

```bash
# list all supported boards
cmake -B build -DLIST_ALL_BOARDS=ON | less
# build configuration
cmake -B build -GNinja -DBOARD_CONFIG=rv-virt:leds_swift -DENABLE_NUTTX_TRACE=[ON|OFF]
# build
cmake --build build
# clean
cmake --build build -t distclean
# export NuttX as library
cmake --build build -t nuttx-libs
```

- **Output**
```bash
qemu-system-riscv32 \
-semihosting \
-M virt,aclint=on \
-cpu rv32 -smp 8 \
-bios none \
-kernel build/nuttx.elf -nographic
NuttShell (NSH) NuttX-12.7.0
nsh> leds_swift
leds_main: led_daemon started

led_daemon (pid# 4): Running
led_daemon: Opening /dev/userleds
led_daemon: Supported LEDs 0x7
led_daemon: LED set 0x1
board_userled: LED 1 set to 1
board_userled: LED 2 set to 0
board_userled: LED 3 set to 0
nsh> led_daemon: LED set 0x0
board_userled: LED 1 set to 0
board_userled: LED 2 set to 0
board_userled: LED 3 set to 0
led_daemon: LED set 0x1
board_userled: LED 1 set to 1
board_userled: LED 2 set to 0
board_userled: LED 3 set to 0
led_daemon: LED set 0x0
# [...] see output in QEMU
```

Quit from QEMU: `Ctrl-a x`

## References

- [Nuttx - Compiling with CMake](https://nuttx.apache.org/docs/latest/quickstart/compiling_cmake.html)
- [NuttX - C++ Example using CMake](https://nuttx.apache.org/docs/latest/guides/cpp_cmake.html)
- [NuttX - leds_rust](https://lupyuen.github.io/articles/rust6)
76 changes: 76 additions & 0 deletions nuttx-riscv-blink/defconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_DISABLE_OS_API is not set
# CONFIG_NSH_DISABLE_LOSMART is not set
CONFIG_16550_ADDRWIDTH=0
CONFIG_16550_UART0=y
CONFIG_16550_UART0_BASE=0x10000000
CONFIG_16550_UART0_CLOCK=3686400
CONFIG_16550_UART0_IRQ=37
CONFIG_16550_UART0_SERIAL_CONSOLE=y
CONFIG_16550_UART=y
CONFIG_ARCH="risc-v"
CONFIG_ARCH_BOARD="rv-virt"
CONFIG_ARCH_BOARD_QEMU_RV_VIRT=y
CONFIG_ARCH_CHIP="qemu-rv"
# CONFIG_ARCH_CHIP_QEMU_RV64=y
CONFIG_ARCH_CHIP_QEMU_RV=y
CONFIG_ARCH_CHIP_QEMU_RV_ISA_A=y
CONFIG_ARCH_CHIP_QEMU_RV_ISA_C=y
CONFIG_ARCH_CHIP_QEMU_RV_ISA_M=y
CONFIG_ARCH_INTERRUPTSTACK=2048
CONFIG_ARCH_RISCV=y
CONFIG_ARCH_STACKDUMP=y
CONFIG_BCH=y
CONFIG_BOARDCTL_POWEROFF=y
CONFIG_BOARD_LATE_INITIALIZE=y
CONFIG_BOARD_LOOPSPERMSEC=6366
CONFIG_BUILTIN=y
CONFIG_DEBUG_FEATURES=y
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEVICE_TREE=y
CONFIG_DEV_ZERO=y
CONFIG_ELF=y
# CONFIG_EXAMPLES_HELLO=y
CONFIG_EXAMPLES_LEDS=y
CONFIG_EXAMPLES_LEDS_SWIFT=y
CONFIG_FS_HOSTFS=y
CONFIG_FS_PROCFS=y
CONFIG_IDLETHREAD_STACKSIZE=2048
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_INIT_STACKSIZE=3072
CONFIG_LIBC_ENVPATH=y
CONFIG_LIBC_EXECFUNCS=y
CONFIG_LIBC_PERROR_STDOUT=y
CONFIG_LIBC_STRERROR=y
CONFIG_LIBM=y
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_READLINE=y
CONFIG_PATH_INITIAL="/system/bin"
CONFIG_RAM_SIZE=33554432
CONFIG_RAM_START=0x80000000
CONFIG_READLINE_CMD_HISTORY=y
CONFIG_RISCV_SEMIHOSTING_HOSTFS=y
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_WAITPID=y
CONFIG_SERIAL_UART_ARCH_MMIO=y
CONFIG_STACK_COLORATION=y
CONFIG_START_MONTH=12
CONFIG_START_YEAR=2021
CONFIG_SYMTAB_ORDEREDBYNAME=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_NSH_STACKSIZE=3072
CONFIG_TESTING_GETPRIME=y
CONFIG_TESTING_OSTEST=y
CONFIG_USEC_PER_TICK=1000
CONFIG_USERLED=y
CONFIG_USERLED_LOWER=y
Loading
Loading