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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
.tmp/
_deps/
build/
build_qemu/
Debug/
CMakeFiles/
CMakeScripts/
Expand Down
9 changes: 8 additions & 1 deletion cmake/riscv32_gnu.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ set(CMAKE_SYSTEM_PROCESSOR risc-v32)

set(THREADX_ARCH "risc-v32")
set(THREADX_TOOLCHAIN "gnu")
set(ARCH_FLAGS "-g -march=rv32gc -mabi=ilp32d -mcmodel=medany")
# -mrelax enables linker relaxation, in particular GP-relative
# addressing for symbols within +/- 2 KiB of __global_pointer$ (small
# data window). This requires the runtime to load the global pointer
# explicitly under .option norelax (see entry.s in the QEMU virt demo)
# and the linker script to PROVIDE __global_pointer$ centred in the
# small-data window (see link.lds). Without those two pieces in place
# -mrelax produces broken GP-relative loads on bare-metal targets.
set(ARCH_FLAGS "-g -march=rv32gc -mabi=ilp32d -mcmodel=medany -mrelax")
set(CFLAGS "${ARCH_FLAGS}")
set(ASFLAGS "${ARCH_FLAGS}")
set(LDFLAGS "${ARCH_FLAGS}")
Expand Down
8 changes: 8 additions & 0 deletions ports/risc-v32/gnu/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,11 @@ target_include_directories(${PROJECT_NAME}
PUBLIC
${CMAKE_CURRENT_LIST_DIR}/inc
)

# Optional: pull in the QEMU virt demo if its CMakeLists is present.
# kernel.elf is EXCLUDE_FROM_ALL inside, so the default build is
# unaffected; consumers opt in via `--target kernel.elf` or
# `--target check-functional-riscv32`.
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/example_build/qemu_virt/CMakeLists.txt)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/example_build/qemu_virt)
endif()
61 changes: 61 additions & 0 deletions ports/risc-v32/gnu/example_build/qemu_virt/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# ThreadX RISC-V32 GNU port: QEMU virt demo build.
#
# This subdirectory is opted-in by ports/risc-v32/gnu/CMakeLists.txt when
# the consumer is building the threadx library for the risc-v32/gnu port.
#
# kernel.elf is marked EXCLUDE_FROM_ALL so that:
# - The default `cmake --build .` (which builds the threadx library
# and any tests the consumer wires up) is unaffected by the demo.
# - Users who explicitly want the demo can `cmake --build .
# --target kernel.elf` or `cmake --build . --target
# check-functional-riscv32` to also drive the QEMU/GDB test runner.
#
# This avoids touching the root CMakeLists.txt while still keeping the
# build-system entry point for the demo discoverable next to the demo
# sources themselves.

set(QEMU_DEMO_DIR ${CMAKE_CURRENT_LIST_DIR})

add_executable(kernel.elf EXCLUDE_FROM_ALL
${QEMU_DEMO_DIR}/demo_threadx.c
${QEMU_DEMO_DIR}/entry.s
${QEMU_DEMO_DIR}/uart.c
${QEMU_DEMO_DIR}/plic.c
${QEMU_DEMO_DIR}/hwtimer.c
${QEMU_DEMO_DIR}/trap.c
${QEMU_DEMO_DIR}/board.c
${QEMU_DEMO_DIR}/tx_initialize_low_level.S
)

target_link_libraries(kernel.elf PRIVATE threadx)

target_include_directories(kernel.elf PRIVATE
${CMAKE_SOURCE_DIR}/common/inc
${CMAKE_SOURCE_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc
${QEMU_DEMO_DIR}
)

target_link_options(kernel.elf PRIVATE
-T${QEMU_DEMO_DIR}/link.lds
-nostartfiles
-Wl,-Map=kernel.map
)

# QEMU/GDB functional test runner. Optional: skipped silently if the
# host has no Python 3 interpreter on PATH.
find_package(Python3 COMPONENTS Interpreter)
if(Python3_FOUND)
add_custom_target(check-functional-riscv32
COMMAND ${Python3_EXECUTABLE}
${QEMU_DEMO_DIR}/test/azrtos_test_tx_gnu_riscv32_qemu.py
--elf $<TARGET_FILE:kernel.elf>
--qemu qemu-system-riscv32
--gdb gdb
DEPENDS kernel.elf
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Running RISC-V32 QEMU/GDB functional test runner..."
)
else()
message(STATUS
"Python3 not found; check-functional-riscv32 target unavailable.")
endif()
9 changes: 7 additions & 2 deletions ports/risc-v32/gnu/example_build/qemu_virt/demo_threadx.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
#define DEMO_BLOCK_POOL_SIZE 100
#define DEMO_QUEUE_SIZE 100

/* Shared FPU register exercised by thread_6/7 to validate FP context save/restore. */
float fpu_test_val = 0.0f;

char *_to_str(ULONG val)
{
static char buf[11]; /* 10 digits max + '\0' */
Expand Down Expand Up @@ -201,7 +204,7 @@ UINT status;
thread_0_counter++;

/* Sleep for 10 ticks. */
tx_thread_sleep(10);
tx_thread_sleep(1);

/* Set event flag 0 to wakeup thread 5. */
status = tx_event_flags_set(&event_flags_0, 0x1, TX_OR);
Expand Down Expand Up @@ -337,7 +340,6 @@ ULONG actual_flags;
}
}


void thread_6_and_7_entry(ULONG thread_input)
{

Expand All @@ -363,6 +365,9 @@ UINT status;
if (status != TX_SUCCESS)
break;

/* FPU Test*/
fpu_test_val += 1.1f;

/* Get the mutex again with suspension. This shows
that an owning thread may retrieve the mutex it
owns multiple times. */
Expand Down
51 changes: 44 additions & 7 deletions ports/risc-v32/gnu/example_build/qemu_virt/entry.s
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/

.section .text
/*
* ThreadX RISC-V32 GNU port: QEMU virt machine reset/entry stub.
*
* Linked at the load address of the QEMU `virt` machine (see link.lds).
* Placed in the .init section so the linker keeps it at the very start
* of the image regardless of file ordering during link, matching the
* PC value QEMU uses on reset.
*
* Responsibilities:
* 1. Park secondary harts on `wfi` (single-hart bring-up only; SMP TBD).
* 2. Zero the integer register file on the boot hart, including x3
* (the global pointer) which we load explicitly with the linker
* symbol `__global_pointer$` below, with relaxation disabled so
* the `la gp, ...` itself is not subject to GP-relative rewriting.
* 3. Set up the system stack and clear .bss before calling main().
*/

.section .init
.align 4
.global _start
.extern main
Expand All @@ -9,9 +36,14 @@
_start:
csrr t0, mhartid
bne t0, zero, 1f

/* Zero general purpose registers (x3/gp handled by the la below). */
li x1, 0
li x2, 0
li x3, 0
.option push
.option norelax
la gp, __global_pointer$ /* x3 = gp; norelax keeps this load absolute */
.option pop
Comment on lines +43 to +46
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x3 register is missing. also I'm not sure why we need to change .text to .init.

li x4, 0
li x5, 0
li x6, 0
Expand Down Expand Up @@ -40,19 +72,24 @@ _start:
li x29, 0
li x30, 0
li x31, 0
la t0, _sysstack_start
li t1, 0x1000

/* Set up the system stack: top-of-stack = _sysstack_start + 0x1000. */
la t0, _sysstack_start
li t1, 0x1000
add sp, t0, t1

/* Clear .bss [_bss_start, _bss_end). */
la t0, _bss_start
la t1, _bss_end
_bss_clean_start:
bgeu t0, t1, _bss_clean_end
sb zero, 0(t0)
sb zero, 0(t0)
addi t0, t0, 1
j _bss_clean_start
j _bss_clean_start
_bss_clean_end:
call main

1:
/* todo smp */
/* Secondary harts: park here. SMP bring-up is not yet supported. */
wfi
j 1b
38 changes: 31 additions & 7 deletions ports/risc-v32/gnu/example_build/qemu_virt/link.lds
Original file line number Diff line number Diff line change
@@ -1,14 +1,35 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Microsoft Software License Terms for Microsoft
* Azure RTOS. Full text of the license can be found in the LICENSE
* file at https://aka.ms/AzureRTOS_EULA.
*
* ThreadX RISC-V32 GNU port: linker script for the QEMU `virt` machine.
*
* - Image base 0x80000000 matches the PC QEMU sets when launched with
* `-machine virt -kernel kernel.elf` (DRAM start on this machine).
* - .init is placed first so entry.s / _start is the very first
* instruction the CPU executes after reset.
* - __global_pointer$ is provided at the start of .data + 0x800 so
* that GP-relative loads/stores reach symbols in [GP-0x800, GP+0x7FF],
* the standard small-data window that `-mrelax` uses (see entry.s
* for the matching `la gp, __global_pointer$` initialization).
* - A 4 KiB system stack is reserved after .bss, with _sysstack_start
* consumed by entry.s as the boot stack base.
*/

OUTPUT_ARCH( "riscv" )
ENTRY( _start )

SECTIONS
{
/*
* ensure that entry.S / _entry is at 0x80000000,
* where qemu's -kernel jumps.
*/
/* QEMU virt: -kernel jumps to 0x80000000 (DRAM start). */
. = 0x80000000;

.init : {
KEEP (*(.init))
}

.text : {
*(.text .text.*)
. = ALIGN(0x1000);
Expand All @@ -24,14 +45,17 @@ SECTIONS

.data : {
. = ALIGN(16);
/* Centre __global_pointer$ in the small-data window so the +/-2 KiB
reach of GP-relative addressing covers the .sdata/.sbss area. */
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*) /* do not need to distinguish this from .data */
. = ALIGN(16);
*(.data .data.*)
}

.bss : {
. = ALIGN(16);
_bss_start = .;
_bss_start = .; /* consumed by entry.s for .bss zero-init */
*(.sbss .sbss.*) /* do not need to distinguish this from .bss */
. = ALIGN(16);
*(.bss .bss.*)
Expand All @@ -40,8 +64,8 @@ SECTIONS

.stack : {
. = ALIGN(4096);
_sysstack_start = .;
. += 0x1000;
_sysstack_start = .; /* boot stack base used by entry.s */
. += 0x1000; /* 4 KiB system stack */
_sysstack_end = .;
}

Expand Down
Loading