Skip to content
Open
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
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ if(THREADX_SMP)
target_compile_definitions(${PROJECT_NAME} PUBLIC "TX_MPCORE" )
endif()

# Optional: build for S-mode (Supervisor mode) instead of M-mode (Machine mode).
# Required when running after OpenSBI, e.g. booted from U-Boot.
option(TX_RISCV_SMODE "Use S-mode CSRs instead of M-mode for RISC-V targets" OFF)
if(TX_RISCV_SMODE)
message(STATUS "RISC-V S-mode enabled (TX_RISCV_SMODE)")
target_compile_definitions(${PROJECT_NAME} PUBLIC "TX_RISCV_SMODE")
endif()

# Enable a build target that produces a ZIP file of all sources
set(CPACK_SOURCE_GENERATOR "ZIP")
set(CPACK_SOURCE_IGNORE_FILES
Expand Down
4 changes: 4 additions & 0 deletions ports/risc-v64/gnu/example_build/bananapi-f3/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
kernel.bin
kernel.elf
kernel.uImage

45 changes: 45 additions & 0 deletions ports/risc-v64/gnu/example_build/bananapi-f3/board.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/***************************************************************************
* Copyright (c) 2026 10xEngineers
*
* 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
**************************************************************************/

#include "plic.h"
#include "hwtimer.h"
#include "uart.h"
#include <stdint.h>
#include <stddef.h>

void *memset(void *des, int c, size_t n)
{
if ((des == NULL) || n == 0)
return des;

char *t = (char *)des;
for (size_t i = 0; i < n; i++)
t[i] = c;
return t;
}

int board_init(void)
{
int ret;

ret = plic_init();
if (ret)
return ret;

ret = uart_init();
if (ret)
return ret;

ret = hwtimer_init();
if (ret)
return ret;

return 0;
}
59 changes: 59 additions & 0 deletions ports/risc-v64/gnu/example_build/bananapi-f3/build_libthreadx.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/bin/bash
# Build the bananapi-f3 (SpacemiT K1) ThreadX kernel.
#
# Boot flow: FSBL -> OpenSBI (M-mode) -> U-Boot (S-mode) -> ThreadX (S-mode).
#
# OpenSBI runs in M-mode and delegates S-mode to the next stage.
# U-Boot runs in S-mode; any code launched from U-Boot also runs in S-mode.
#
# Use the TX_RISCV_SMODE CMake option to build libthreadx.a for S-mode.
#
# This libthreadx.a (S-mode), then links the BSP objects
# to produce kernel.elf / kernel.bin.

set -e

# Where ThreadX is loaded by U-Boot (${loadaddr}). Must match the link.lds origin.
LOAD_ADDR=0x00200000

# printf "y\n" | rm -rf ../../../../../build/
rm -f kernel.elf kernel.bin kernel.uImage

pushd ../../../../../
cmake -Bbuild -GNinja \
-DCMAKE_TOOLCHAIN_FILE=cmake/riscv64_gnu.cmake \
-DTX_USER_FILE="" \
-DTX_RISCV_SMODE=ON \
.
cmake --build ./build/
popd

riscv64-unknown-elf-gcc \
-march=rv64gc -mabi=lp64d \
-mcmodel=medany -O0 -g3 -Wall \
-DTX_RISCV_SMODE \
-ffunction-sections -fdata-sections \
-I../../../../../common/inc \
-I../../inc \
entry.S \
tx_initialize_low_level.S \
board.c uart.c hwtimer.c plic.c trap.c demo_threadx.c \
-L../../../../../build -lthreadx \
-T link.lds -nostartfiles \
-o kernel.elf

# Strip ELF metadata down to the loadable bytes.
riscv64-unknown-elf-objcopy -O binary kernel.elf kernel.bin

echo "== Build artifacts =="
ls -la kernel.elf kernel.bin 2>/dev/null || true
echo
riscv64-unknown-elf-size kernel.elf || true
echo

# Run on Bananapi BPI-F3
# Stop the boot at U-Boot (press reset button and press "s" key continuously to stop autoboot).
# at "=>" prompt, load the kernel using the following commands:
#
# " ELF: tftpboot ${loadaddr} kernel.elf && bootelf ${loadaddr}"
# " BIN: tftpboot 0x200000 kernel.bin && go 0x200000"
98 changes: 98 additions & 0 deletions ports/risc-v64/gnu/example_build/bananapi-f3/csr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/***************************************************************************
* Copyright (c) 2026 10xEngineers
*
* 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
**************************************************************************/

/* RISC-V S-mode CSR helpers
*
* Privilege level: Supervisor (S-mode).
* Reference: RISC-V Privileged Specification
*
* Bit positions per the RISC-V Privileged Specification:
*
* sstatus: SIE(1) SPIE(5) SPP(8) FS(13:14) SUM(18) MXR(19)
* sie: SSIE(1) STIE(5) SEIE(9)
* scause: Interrupt bit = 63; Code 1=SSI, 5=STI, 9=SEI
*/

#ifndef RISCV_CSR_H
#define RISCV_CSR_H

#define SSTATUS_SIE (1L << 1) /* Supervisor Interrupt Enable */
#define SSTATUS_SPIE (1L << 5) /* Previous SIE (saved on trap) */
#define SSTATUS_SPP_MASK (1L << 8)
#define SSTATUS_SPP_S (1L << 8) /* SPP = Supervisor */
#define SSTATUS_SPP_U (0L << 8) /* SPP = User */
#define SSTATUS_FS (3L << 13) /* FP unit state (Off/Init/Clean/Dirty) */

#define SIE_SSIE (1L << 1) /* S-mode software interrupt */
#define SIE_STIE (1L << 5) /* S-mode timer interrupt */
#define SIE_SEIE (1L << 9) /* S-mode external interrupt */

#ifndef __ASSEMBLER__

#include <stdint.h>

/*
* Return the hart ID of the running core.
*
* mhartid is an M-mode CSR and cannot be read from S-mode. When booted
* from U-Boot only hart 0 is active (secondary harts remain parked in
* OpenSBI HSM), so we return 0. An SMP extension would need to pass
* the hart ID through a0 or shared memory at boot.
*/
static inline uint64_t riscv_get_core(void)
{
return 0;
}


static inline uint64_t riscv_read_sstatus(void)
{
uint64_t x;
asm volatile("csrr %0, sstatus" : "=r" (x));
return x;
}

static inline void riscv_write_sstatus(uint64_t x)
{
asm volatile("csrw sstatus, %0" : : "r" (x));
}


static inline void riscv_sintr_on(void)
{
riscv_write_sstatus(riscv_read_sstatus() | SSTATUS_SIE);
}

static inline void riscv_sintr_off(void)
{
riscv_write_sstatus(riscv_read_sstatus() & ~SSTATUS_SIE);
}

static inline int riscv_sintr_get(void)
{
return (riscv_read_sstatus() & SSTATUS_SIE) != 0;
}

static inline void riscv_sintr_restore(int enabled)
{
if (enabled)
riscv_sintr_on();
else
riscv_sintr_off();
}

/* Unified names used by BSP drivers (uart.c, etc.). */
#define riscv_intr_on riscv_sintr_on
#define riscv_intr_off riscv_sintr_off
#define riscv_intr_get riscv_sintr_get
#define riscv_intr_restore riscv_sintr_restore

#endif /* __ASSEMBLER__ */
#endif /* RISCV_CSR_H */
Loading