Skip to content
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
71 changes: 71 additions & 0 deletions cmake/riscv-none-elf-rv32imc.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# /***************************************************************************
# * Copyright (C) 2026 Eclipse ThreadX contributors
# *
# * This program and the accompanying materials are made available under the
# * terms of the MIT License which is available at
# * https://opensource.org/licenses/MIT.
# *
# * SPDX-License-Identifier: MIT
# ***************************************************************************/

# CMake toolchain file for bare-metal RV32IMC targets (e.g. CORE-V MCU / CV32E40P)
#
# Uses the xPack riscv-none-elf-gcc toolchain:
# https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack
#
# This is a cross-platform (Linux/macOS/Windows), multilib-capable toolchain
# analogous to arm-none-eabi-gcc. Its multilib includes rv32imc/ilp32
# (soft-float), so -lgcc resolves correctly without any distro package.
#
# Install via: bash ports/risc-v32/gnu/example_build/core_v_mcu/install_deps.sh
# (downloads the latest xPack release to /opt/xpack-riscv-none-elf-gcc/)
#
# Do NOT use riscv32-unknown-elf-gcc (riscv-collab riscv32-elf release) for
# this target: that toolchain is built --disable-multilib --with-abi=ilp32d,
# so its libgcc only provides ilp32d (hardware FP) helpers and cannot link
# rv32imc/ilp32 soft-float objects.
#
# Target ISA : rv32imc_zicsr (integer, multiply, compressed, Zicsr)
# ABI : ilp32 (32-bit int/long/ptr, soft-float)
# Code model : medlow (addresses in [0, 2 GiB))

set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR riscv)

set(THREADX_ARCH "risc-v32")
set(THREADX_TOOLCHAIN "gnu")

set(ARCH_FLAGS "-march=rv32imc_zicsr -mabi=ilp32 -mcmodel=medlow")
set(CFLAGS "${ARCH_FLAGS}")
set(ASFLAGS "${ARCH_FLAGS}")
set(LDFLAGS "${ARCH_FLAGS}")

# xPack riscv-none-elf multilib toolchain.
set(CMAKE_C_COMPILER riscv-none-elf-gcc)
set(CMAKE_CXX_COMPILER riscv-none-elf-g++)
set(AS riscv-none-elf-as)
set(AR riscv-none-elf-ar)
set(OBJCOPY riscv-none-elf-objcopy)
set(OBJDUMP riscv-none-elf-objdump)
set(SIZE riscv-none-elf-size)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

# Use static library for compiler feature probing (no linker script yet)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

set(CMAKE_C_FLAGS "${CFLAGS}" CACHE INTERNAL "c compiler flags")
set(CMAKE_CXX_FLAGS "${CFLAGS}" CACHE INTERNAL "cxx compiler flags")
set(CMAKE_ASM_FLAGS "${ASFLAGS} -D__ASSEMBLER__" CACHE INTERNAL "asm compiler flags")
set(CMAKE_EXE_LINKER_FLAGS "${LDFLAGS}" CACHE INTERNAL "exe link flags")

set(CMAKE_C_FLAGS_DEBUG "-Og -g -ggdb3" CACHE INTERNAL "c debug flags")
set(CMAKE_CXX_FLAGS_DEBUG "-Og -g -ggdb3" CACHE INTERNAL "cxx debug flags")
set(CMAKE_ASM_FLAGS_DEBUG "-g -ggdb3" CACHE INTERNAL "asm debug flags")

set(CMAKE_C_FLAGS_RELEASE "-Os" CACHE INTERNAL "c release flags")
set(CMAKE_CXX_FLAGS_RELEASE "-Os" CACHE INTERNAL "cxx release flags")
set(CMAKE_ASM_FLAGS_RELEASE "" CACHE INTERNAL "asm release flags")
52 changes: 38 additions & 14 deletions cmake/riscv32-unknown-elf-rv32imc.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,34 @@
# * SPDX-License-Identifier: MIT
# ***************************************************************************/

# CMake toolchain file for CORE-V MCU (CV32E40P, RV32IMC)
# CMake toolchain file for RV32GC targets (QEMU virt, etc.)
#
# Uses the dedicated riscv32-unknown-elf-gcc bare-metal toolchain from
# riscv-collab (riscv32-elf-ubuntu-24.04-gcc.tar.xz, installs to /opt/riscv).
# This is the correct toolchain for RV32 bare-metal targets — analogous to
# arm-none-eabi-gcc for Cortex-M. It ships a native rv32/ilp32 libgcc with
# all soft-float and integer helpers (__clzsi2, __muldf3, etc.) built for the
# correct ABI.
# riscv-collab (riscv32-elf-ubuntu-24.04-gcc.tar.xz, installs to /opt/riscv
# via scripts/install_riscv.sh).
#
# Do NOT use riscv64-unknown-elf-gcc for this target: the riscv-collab
# riscv64-elf toolchain is built without rv32 multilib and will produce
# missing-symbol linker errors with -nodefaultlibs.
# IMPORTANT: the riscv-collab riscv32-elf toolchain is built
# --disable-multilib --with-abi=ilp32d, so its libgcc only provides
# ilp32d (hardware double-FP) helpers. This cmake file therefore targets
# rv32gc/ilp32d, which matches the toolchain's built-in ABI and works
# correctly with QEMU virt (which emulates hardware FP).
#
# Install both toolchains with: bash scripts/install_riscv.sh
# Do NOT use this file for bare-metal targets that lack hardware FP (e.g.
# CV32E40P, rv32imc). For those, use cmake/riscv64-ubuntu-rv32imc.cmake
# which calls the Ubuntu gcc-riscv64-unknown-elf package — a multilib build
# that includes the rv32im/ilp32 (soft-float) libgcc variant.
#
# Target ISA : rv32imc_zicsr (integer, multiply, compressed, Zicsr)
# ABI : ilp32 (32-bit int/long/ptr, no hardware FP)
# Code model : medlow (addresses in [0, 2 GiB))
# Target ISA : rv32gc (integer, multiply, atomics, FP, compressed, Zicsr)
# ABI : ilp32d (32-bit int/long/ptr, hardware double-precision FP)
# Code model : medlow (addresses in [0, 2 GiB))

set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR riscv)

set(THREADX_ARCH "risc-v32")
set(THREADX_TOOLCHAIN "gnu")

set(ARCH_FLAGS "-march=rv32imc_zicsr -mabi=ilp32 -mcmodel=medlow")
set(ARCH_FLAGS "-march=rv32gc -mabi=ilp32d -mcmodel=medlow")
set(CFLAGS "${ARCH_FLAGS}")
set(ASFLAGS "${ARCH_FLAGS}")
set(LDFLAGS "${ARCH_FLAGS}")
Expand Down Expand Up @@ -67,3 +69,25 @@ set(CMAKE_ASM_FLAGS_DEBUG "-g -ggdb3" CACHE INTERNAL "asm debug flags")
set(CMAKE_C_FLAGS_RELEASE "-Os" CACHE INTERNAL "c release flags")
set(CMAKE_CXX_FLAGS_RELEASE "-Os" CACHE INTERNAL "cxx release flags")
set(CMAKE_ASM_FLAGS_RELEASE "" CACHE INTERNAL "asm release flags")


set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

# Use static library for compiler feature probing (no linker script yet)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

set(CMAKE_C_FLAGS "${CFLAGS}" CACHE INTERNAL "c compiler flags")
set(CMAKE_CXX_FLAGS "${CFLAGS}" CACHE INTERNAL "cxx compiler flags")
set(CMAKE_ASM_FLAGS "${ASFLAGS} -D__ASSEMBLER__" CACHE INTERNAL "asm compiler flags")
set(CMAKE_EXE_LINKER_FLAGS "${LDFLAGS}" CACHE INTERNAL "exe link flags")

set(CMAKE_C_FLAGS_DEBUG "-Og -g -ggdb3" CACHE INTERNAL "c debug flags")
set(CMAKE_CXX_FLAGS_DEBUG "-Og -g -ggdb3" CACHE INTERNAL "cxx debug flags")
set(CMAKE_ASM_FLAGS_DEBUG "-g -ggdb3" CACHE INTERNAL "asm debug flags")

set(CMAKE_C_FLAGS_RELEASE "-Os" CACHE INTERNAL "c release flags")
set(CMAKE_CXX_FLAGS_RELEASE "-Os" CACHE INTERNAL "cxx release flags")
set(CMAKE_ASM_FLAGS_RELEASE "" CACHE INTERNAL "asm release flags")
4 changes: 2 additions & 2 deletions cmake/riscv64-gcc-rv32imc.cmake
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# This file is a compatibility alias. Use riscv32-unknown-elf-rv32imc.cmake.
include(${CMAKE_CURRENT_LIST_DIR}/riscv32-unknown-elf-rv32imc.cmake)
# This file is a compatibility alias. Use riscv-none-elf-rv32imc.cmake.
include(${CMAKE_CURRENT_LIST_DIR}/riscv-none-elf-rv32imc.cmake)
30 changes: 15 additions & 15 deletions ports/risc-v32/gnu/example_build/core_v_mcu/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,18 @@ Or install individually:

| Tool | Minimum version | Notes |
|------|----------------|-------|
| `riscv32-unknown-elf-gcc` | 15.x | riscv-collab `riscv32-elf` release — run `bash scripts/install_riscv.sh` |
| `riscv-none-elf-gcc` | 15.x | xPack riscv-none-elf-gcc — run `bash install_deps.sh` |
| CMake | 3.15 | `apt install cmake` |
| Ninja | 1.10 | `apt install ninja-build` |
| OpenOCD | 0.12 | `apt install openocd` |
| GDB | any multiarch | `apt install gdb-multiarch` — Ubuntu does not ship `riscv32-unknown-elf-gdb` |
| GDB | any multiarch | `apt install gdb-multiarch` |

> **Note:** Use the dedicated `riscv32-unknown-elf-gcc` bare-metal toolchain
> (riscv-collab `riscv32-elf` release, installs to `/opt/riscv`). This is
> the RV32 equivalent of `arm-none-eabi-gcc` and ships a native rv32/ilp32
> libgcc with all required soft-float and integer helpers. Do **not** use
> `riscv64-unknown-elf-gcc` — the riscv-collab riscv64-elf toolchain has no
> rv32 multilib and will produce missing-symbol linker errors.
> **Note:** Use the [xPack riscv-none-elf-gcc](https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack)
> toolchain — a cross-platform (Linux/macOS/Windows) multilib bare-metal
> toolchain analogous to `arm-none-eabi-gcc`. Its multilib includes
> rv32imc/ilp32 (soft-float) libgcc required for the CV32E40P. Do **not**
> use `riscv32-unknown-elf-gcc` (riscv-collab) — that release is built
> `--disable-multilib --with-abi=ilp32d` and cannot link soft-float objects.

---

Expand Down Expand Up @@ -224,19 +224,19 @@ build/demo_threadx.map — linker map
```bash
THREADX_ROOT=$(realpath ../../../../..)
cmake -B build -G Ninja \
-DCMAKE_TOOLCHAIN_FILE="${THREADX_ROOT}/cmake/riscv32-unknown-elf-rv32imc.cmake" \
-DCMAKE_TOOLCHAIN_FILE="${THREADX_ROOT}/cmake/riscv-none-elf-rv32imc.cmake" \
.
cmake --build build
```

### Toolchain file

`${THREADX_ROOT}/cmake/riscv32-unknown-elf-rv32imc.cmake` sets:
`${THREADX_ROOT}/cmake/riscv-none-elf-rv32imc.cmake` sets:

```
CMAKE_C_COMPILER riscv32-unknown-elf-gcc
CMAKE_ASM_COMPILER riscv32-unknown-elf-gcc
CMAKE_OBJCOPY riscv32-unknown-elf-objcopy
CMAKE_C_COMPILER riscv-none-elf-gcc
CMAKE_ASM_COMPILER riscv-none-elf-gcc
CMAKE_OBJCOPY riscv-none-elf-objcopy
CMAKE_C_FLAGS -march=rv32imc_zicsr -mabi=ilp32 -mcmodel=medlow
```

Expand Down Expand Up @@ -288,7 +288,7 @@ port 3333 (GDB) and 4444 (telnet).
In a second terminal:

```bash
riscv32-unknown-elf-gdb --command=gdb_init
riscv-none-elf-gdb --command=gdb_init
```

`gdb_init` connects to OpenOCD, loads the ELF, sets a breakpoint at `main`, and
Expand Down Expand Up @@ -488,7 +488,7 @@ bash deploy.sh --debug
```

The script starts OpenOCD in the background, waits for it to become ready,
then drives `riscv32-unknown-elf-gdb` to load the ELF. OpenOCD is always
then drives `riscv-none-elf-gdb` to load the ELF. OpenOCD is always
stopped on exit (including Ctrl-C).

---
Expand Down
8 changes: 7 additions & 1 deletion ports/risc-v32/gnu/example_build/core_v_mcu/build.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
#!/bin/bash
set -e

XPACK_GCC_DIR=/opt/xpack-riscv-none-elf-gcc-15.2.0-1
if [ -d "${XPACK_GCC_DIR}/bin" ]; then
export PATH="${XPACK_GCC_DIR}/bin:${PATH}"
fi

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
THREADX_ROOT="${SCRIPT_DIR}/../../../../.."
cmake -B "${SCRIPT_DIR}/build" \
-G Ninja \
-DCMAKE_TOOLCHAIN_FILE="${THREADX_ROOT}/cmake/riscv32-unknown-elf-rv32imc.cmake" \
-DCMAKE_TOOLCHAIN_FILE="${THREADX_ROOT}/cmake/riscv-none-elf-rv32imc.cmake" \
"${SCRIPT_DIR}"
cmake --build "${SCRIPT_DIR}/build"
45 changes: 35 additions & 10 deletions ports/risc-v32/gnu/example_build/core_v_mcu/install_deps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@
# * terms of the MIT License which is available at
# * https://opensource.org/licenses/MIT.
# *
# * AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
# * The AI-generated portions may be considered public domain (CC0-1.0)
# * and not subject to the project's licence.
# *
# * SPDX-License-Identifier: MIT AND CC0-1.0
# * SPDX-License-Identifier: MIT
# ***************************************************************************/

# install_deps.sh -- Install Linux build/debug dependencies for the CORE-V MCU ThreadX port.
#
# Supported: Ubuntu 20.04 / 22.04 / 24.04 and Debian derivatives.
# Run as a regular user; sudo is invoked internally where needed.
#
# Installs:
# - xPack riscv-none-elf-gcc (multilib bare-metal toolchain, rv32imc/ilp32 capable)
# - cmake, ninja-build, gdb-multiarch, openocd, usbutils
#
# Usage:
# bash install_deps.sh

Expand All @@ -28,11 +28,21 @@ info() { echo "[INFO] $*"; }

command -v apt-get >/dev/null 2>&1 || die "This script requires apt-get (Ubuntu/Debian)."

PACKAGES=(
# ---------------------------------------------------------------------------
# xPack riscv-none-elf-gcc
# Cross-platform multilib toolchain (Linux/macOS/Windows).
# Includes rv32imc/ilp32 (soft-float) libgcc — required for CV32E40P.
# See: https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack
# ---------------------------------------------------------------------------
XPACK_VERSION="15.2.0-1"
XPACK_TARBALL="xpack-riscv-none-elf-gcc-${XPACK_VERSION}-linux-x64.tar.gz"
XPACK_URL="https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v${XPACK_VERSION}/${XPACK_TARBALL}"
XPACK_INSTALL_DIR="/opt/xpack-riscv-none-elf-gcc-${XPACK_VERSION}"
XPACK_BIN="${XPACK_INSTALL_DIR}/bin"

APT_PACKAGES=(
cmake
ninja-build
gcc-riscv64-unknown-elf
binutils-riscv64-unknown-elf
gdb-multiarch
openocd
usbutils
Expand All @@ -42,12 +52,27 @@ PACKAGES=(
info "Updating package lists ..."
sudo apt-get update -qq

info "Installing: ${PACKAGES[*]}"
sudo apt-get install -y "${PACKAGES[@]}"
info "Installing apt packages: ${APT_PACKAGES[*]}"
sudo apt-get install -y "${APT_PACKAGES[@]}"

if [ -x "${XPACK_BIN}/riscv-none-elf-gcc" ]; then
info "xPack riscv-none-elf-gcc ${XPACK_VERSION} already installed at ${XPACK_INSTALL_DIR}"
else
info "Downloading xPack riscv-none-elf-gcc ${XPACK_VERSION} ..."
wget --no-verbose "${XPACK_URL}" -O "/tmp/${XPACK_TARBALL}"
sudo mkdir -p "${XPACK_INSTALL_DIR}"
sudo tar xzf "/tmp/${XPACK_TARBALL}" -C /opt
rm "/tmp/${XPACK_TARBALL}"
info "Installed to ${XPACK_INSTALL_DIR}"
fi

info ""
info "Add the toolchain to your PATH:"
info " export PATH=${XPACK_BIN}:\$PATH"
info ""
info "All dependencies installed."
info ""
info "Next steps:"
info " 1. Run scripts/setup_opella.sh to configure udev rules for the Ashling Opella LD."
info " 2. (WSL only) Follow the usbipd-win instructions printed by setup_opella.sh."