diff --git a/cmake/riscv-none-elf-rv32imc.cmake b/cmake/riscv-none-elf-rv32imc.cmake new file mode 100644 index 000000000..647d8099f --- /dev/null +++ b/cmake/riscv-none-elf-rv32imc.cmake @@ -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") diff --git a/cmake/riscv32-unknown-elf-rv32imc.cmake b/cmake/riscv32-unknown-elf-rv32imc.cmake index 7e9356898..0109799f2 100644 --- a/cmake/riscv32-unknown-elf-rv32imc.cmake +++ b/cmake/riscv32-unknown-elf-rv32imc.cmake @@ -8,24 +8,26 @@ # * 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) @@ -33,7 +35,7 @@ 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}") @@ -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") diff --git a/cmake/riscv64-gcc-rv32imc.cmake b/cmake/riscv64-gcc-rv32imc.cmake index d3d50115d..b0916a2fd 100644 --- a/cmake/riscv64-gcc-rv32imc.cmake +++ b/cmake/riscv64-gcc-rv32imc.cmake @@ -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) diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/README.md b/ports/risc-v32/gnu/example_build/core_v_mcu/README.md index d2b8a8442..41f45dab6 100644 --- a/ports/risc-v32/gnu/example_build/core_v_mcu/README.md +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/README.md @@ -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. --- @@ -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 ``` @@ -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 @@ -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). --- diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/build.sh b/ports/risc-v32/gnu/example_build/core_v_mcu/build.sh index c2ccfc559..2e1bb844b 100755 --- a/ports/risc-v32/gnu/example_build/core_v_mcu/build.sh +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/build.sh @@ -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" diff --git a/ports/risc-v32/gnu/example_build/core_v_mcu/install_deps.sh b/ports/risc-v32/gnu/example_build/core_v_mcu/install_deps.sh index b4cd46a8a..d01926653 100755 --- a/ports/risc-v32/gnu/example_build/core_v_mcu/install_deps.sh +++ b/ports/risc-v32/gnu/example_build/core_v_mcu/install_deps.sh @@ -6,11 +6,7 @@ # * 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. @@ -18,6 +14,10 @@ # 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 @@ -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 @@ -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." +