Skip to content

Commit 757db54

Browse files
committed
Add RISC-V32 arch. port layer
This update adapts the ThreadX low-level kernel routines for RV32, including: - startup and initialization logic - context save/restore implementations - interrupt control and scheduler entry - thread stack build and system return paths - timer interrupt handling - made it complient as per new risc-v64/gnu & threadx style - added reademe for risc-v32/gnu port These changes provide full low-level support needed to run ThreadX on RISC-V32 targets. Signed-off-by: Akif Ejaz <akif.ejaz@10xengineers.ai>
1 parent c4ad279 commit 757db54

13 files changed

+2623
-0
lines changed

cmake/riscv32-unknown-elf.cmake

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Toolchain settings
2+
set(CMAKE_C_COMPILER riscv32-unknown-elf-gcc)
3+
set(CMAKE_CXX_COMPILER riscv32-unknown-elf-g++)
4+
set(AS riscv32-unknown-elf-as)
5+
set(AR riscv32-unknown-elf-ar)
6+
set(OBJCOPY riscv32-unknown-elf-objcopy)
7+
set(OBJDUMP riscv32-unknown-elf-objdump)
8+
set(SIZE riscv32-unknown-elf-size)
9+
10+
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
11+
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
12+
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
13+
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
14+
15+
# this makes the test compiles use static library option so that we don't need to pre-set linker flags and scripts
16+
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
17+
18+
set(CMAKE_C_FLAGS "${CFLAGS}" CACHE INTERNAL "c compiler flags")
19+
set(CMAKE_CXX_FLAGS "${CXXFLAGS}" CACHE INTERNAL "cxx compiler flags")
20+
set(CMAKE_ASM_FLAGS "${ASFLAGS} -D__ASSEMBLER__ -D__riscv_float_abi_single" CACHE INTERNAL "asm compiler flags")
21+
set(CMAKE_EXE_LINKER_FLAGS "${LDFLAGS}" CACHE INTERNAL "exe link flags")
22+
23+
SET(CMAKE_C_FLAGS_DEBUG "-Og -g -ggdb3" CACHE INTERNAL "c debug compiler flags")
24+
SET(CMAKE_CXX_FLAGS_DEBUG "-Og -g -ggdb3" CACHE INTERNAL "cxx debug compiler flags")
25+
SET(CMAKE_ASM_FLAGS_DEBUG "-g -ggdb3" CACHE INTERNAL "asm debug compiler flags")
26+
27+
SET(CMAKE_C_FLAGS_RELEASE "-O3" CACHE INTERNAL "c release compiler flags")
28+
SET(CMAKE_CXX_FLAGS_RELEASE "-O3" CACHE INTERNAL "cxx release compiler flags")
29+
SET(CMAKE_ASM_FLAGS_RELEASE "" CACHE INTERNAL "asm release compiler flags")

cmake/riscv32_gnu.cmake

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Name of the target
2+
set(CMAKE_SYSTEM_NAME Generic)
3+
set(CMAKE_SYSTEM_PROCESSOR risc-v32)
4+
5+
set(THREADX_ARCH "risc-v32")
6+
set(THREADX_TOOLCHAIN "gnu")
7+
set(ARCH_FLAGS "-g -march=rv32gc -mabi=ilp32d -mcmodel=medany")
8+
set(CFLAGS "${ARCH_FLAGS}")
9+
set(ASFLAGS "${ARCH_FLAGS}")
10+
set(LDFLAGS "${ARCH_FLAGS}")
11+
12+
include(${CMAKE_CURRENT_LIST_DIR}/riscv32-unknown-elf.cmake)

ports/risc-v32/gnu/CMakeLists.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
target_sources(${PROJECT_NAME}
3+
PRIVATE
4+
# {{BEGIN_TARGET_SOURCES}}
5+
${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S
6+
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.S
7+
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.S
8+
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S
9+
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S
10+
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S
11+
${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S
12+
${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S
13+
# {{END_TARGET_SOURCES}}
14+
)
15+
16+
target_include_directories(${PROJECT_NAME}
17+
PUBLIC
18+
${CMAKE_CURRENT_LIST_DIR}/inc
19+
)

ports/risc-v32/gnu/inc/tx_port.h

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
/***************************************************************************
2+
* Copyright (c) 2025 10xEngineers
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the MIT License which is available at
6+
* https://opensource.org/licenses/MIT.
7+
*
8+
* SPDX-License-Identifier: MIT
9+
**************************************************************************/
10+
11+
12+
/**************************************************************************/
13+
/**************************************************************************/
14+
/** */
15+
/** ThreadX Component */
16+
/** */
17+
/** Port Specific */
18+
/** */
19+
/**************************************************************************/
20+
/**************************************************************************/
21+
22+
23+
/**************************************************************************/
24+
/* */
25+
/* PORT SPECIFIC C INFORMATION RELEASE */
26+
/* */
27+
/* tx_port.h RISC-V32/GNU */
28+
/* 6.4.x */
29+
/* */
30+
/* AUTHOR */
31+
/* */
32+
/* Akif Ejaz, 10xEngineers */
33+
/* */
34+
/* DESCRIPTION */
35+
/* */
36+
/* This file contains data type definitions that make the ThreadX */
37+
/* real-time kernel function identically on a variety of different */
38+
/* processor architectures. For example, the size or number of bits */
39+
/* in an "int" data type vary between microprocessor architectures and */
40+
/* even C compilers for the same microprocessor. ThreadX does not */
41+
/* directly use native C data types. Instead, ThreadX creates its */
42+
/* own special types that can be mapped to actual data types by this */
43+
/* file to guarantee consistency in the interface and functionality. */
44+
/* */
45+
/* RELEASE HISTORY */
46+
/* */
47+
/* DATE NAME DESCRIPTION */
48+
/* */
49+
/* 23-12-2025 Akif Ejaz Initial Version 6.4.x */
50+
/* */
51+
/**************************************************************************/
52+
53+
#ifndef TX_PORT_H
54+
#define TX_PORT_H
55+
56+
#ifndef __ASSEMBLER__
57+
58+
/* Include for memset. */
59+
#include <string.h>
60+
61+
62+
/* Determine if the optional ThreadX user define file should be used. */
63+
64+
#ifdef TX_INCLUDE_USER_DEFINE_FILE
65+
66+
67+
/* Yes, include the user defines in tx_user.h. The defines in this file may
68+
alternately be defined on the command line. */
69+
70+
#include "tx_user.h"
71+
#endif /* TX_INCLUDE_USER_DEFINE_FILE */
72+
73+
#endif /* __ASSEMBLER__ */
74+
75+
76+
/* Define ThreadX basic types for this port. */
77+
78+
#define VOID void
79+
80+
#ifndef __ASSEMBLER__
81+
typedef char CHAR;
82+
typedef unsigned char UCHAR;
83+
typedef int INT;
84+
typedef unsigned int UINT;
85+
typedef long LONG;
86+
typedef unsigned long ULONG;
87+
typedef unsigned long long ULONG64;
88+
typedef short SHORT;
89+
typedef unsigned short USHORT;
90+
#define ULONG64_DEFINED
91+
#endif /* __ASSEMBLER__ */
92+
93+
94+
95+
96+
/* Define the priority levels for ThreadX. Legal values range
97+
from 32 to 1024 and MUST be evenly divisible by 32. */
98+
99+
#ifndef TX_MAX_PRIORITIES
100+
#define TX_MAX_PRIORITIES 32
101+
#endif
102+
103+
104+
/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during
105+
thread creation is less than this value, the thread create call will return an error. */
106+
107+
#ifndef TX_MINIMUM_STACK
108+
#define TX_MINIMUM_STACK 1024 /* Minimum stack size for this port */
109+
#endif
110+
111+
112+
/* Define the system timer thread's default stack size and priority. These are only applicable
113+
if TX_TIMER_PROCESS_IN_ISR is not defined. */
114+
115+
#ifndef TX_TIMER_THREAD_STACK_SIZE
116+
#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */
117+
#endif
118+
119+
#ifndef TX_TIMER_THREAD_PRIORITY
120+
#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */
121+
#endif
122+
123+
124+
/* Define various constants for the ThreadX RISC-V port. */
125+
126+
#define TX_INT_DISABLE 0x00000000 /* Disable interrupts value */
127+
#define TX_INT_ENABLE 0x00000008 /* Enable interrupt value */
128+
129+
130+
/* Define the clock source for trace event entry time stamp. The following two item are port specific.
131+
For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock
132+
source constants would be:
133+
134+
#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024)
135+
#define TX_TRACE_TIME_MASK 0x0000FFFFUL
136+
137+
*/
138+
139+
#ifndef TX_TRACE_TIME_SOURCE
140+
#define TX_TRACE_TIME_SOURCE ++_tx_trace_simulated_time
141+
#endif
142+
#ifndef TX_TRACE_TIME_MASK
143+
#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL
144+
#endif
145+
146+
147+
/* Define the port specific options for the _tx_build_options variable. This variable indicates
148+
how the ThreadX library was built. */
149+
150+
#define TX_PORT_SPECIFIC_BUILD_OPTIONS 0
151+
152+
153+
/* Define the in-line initialization constant so that modules with in-line
154+
initialization capabilities can prevent their initialization from being
155+
a function call. */
156+
157+
#define TX_INLINE_INITIALIZATION
158+
159+
160+
/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is
161+
disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack
162+
checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING
163+
define is negated, thereby forcing the stack fill which is necessary for the stack checking
164+
logic. */
165+
166+
#ifdef TX_ENABLE_STACK_CHECKING
167+
#undef TX_DISABLE_STACK_FILLING
168+
#endif
169+
170+
171+
/* Define the TX_THREAD control block extensions for this port. The main reason
172+
for the multiple macros is so that backward compatibility can be maintained with
173+
existing ThreadX kernel awareness modules. */
174+
175+
#define TX_THREAD_EXTENSION_0
176+
#define TX_THREAD_EXTENSION_1
177+
#define TX_THREAD_EXTENSION_2
178+
#define TX_THREAD_EXTENSION_3
179+
180+
181+
/* Define the port extensions of the remaining ThreadX objects. */
182+
183+
#define TX_BLOCK_POOL_EXTENSION
184+
#define TX_BYTE_POOL_EXTENSION
185+
#define TX_EVENT_FLAGS_GROUP_EXTENSION
186+
#define TX_MUTEX_EXTENSION
187+
#define TX_QUEUE_EXTENSION
188+
#define TX_SEMAPHORE_EXTENSION
189+
#define TX_TIMER_EXTENSION
190+
191+
192+
/* Define the user extension field of the thread control block. Nothing
193+
additional is needed for this port so it is defined as white space. */
194+
195+
#ifndef TX_THREAD_USER_EXTENSION
196+
#define TX_THREAD_USER_EXTENSION
197+
#endif
198+
199+
200+
/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete,
201+
tx_thread_shell_entry, and tx_thread_terminate. */
202+
203+
#define TX_THREAD_CREATE_EXTENSION(thread_ptr)
204+
#define TX_THREAD_DELETE_EXTENSION(thread_ptr)
205+
#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr)
206+
#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr)
207+
208+
209+
/* Define the ThreadX object creation extensions for the remaining objects. */
210+
211+
#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr)
212+
#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
213+
#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr)
214+
#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr)
215+
#define TX_QUEUE_CREATE_EXTENSION(queue_ptr)
216+
#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr)
217+
#define TX_TIMER_CREATE_EXTENSION(timer_ptr)
218+
219+
220+
/* Define the ThreadX object deletion extensions for the remaining objects. */
221+
222+
#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr)
223+
#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr)
224+
#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr)
225+
#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr)
226+
#define TX_QUEUE_DELETE_EXTENSION(queue_ptr)
227+
#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr)
228+
#define TX_TIMER_DELETE_EXTENSION(timer_ptr)
229+
230+
231+
/* Define ThreadX interrupt lockout and restore macros for protection on
232+
access of critical kernel information. The restore interrupt macro must
233+
restore the interrupt posture of the running thread prior to the value
234+
present prior to the disable macro. In most cases, the save area macro
235+
is used to define a local function save area for the disable and restore
236+
macros. */
237+
238+
/* Expose helper used to perform an atomic read/modify/write of mstatus.
239+
The helper composes and returns the posture per ThreadX contract. */
240+
#ifndef __ASSEMBLER__
241+
UINT _tx_thread_interrupt_control(UINT new_posture);
242+
#endif
243+
244+
#ifdef TX_DISABLE_INLINE
245+
246+
#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save;
247+
248+
#define TX_DISABLE __asm__ volatile("csrrci %0, mstatus, 8" : "=r" (interrupt_save) :: "memory");
249+
#define TX_RESTORE { \
250+
unsigned long _temp_mstatus; \
251+
__asm__ volatile( \
252+
"csrc mstatus, 8\n" \
253+
"andi %0, %1, 8\n" \
254+
"csrs mstatus, %0" \
255+
: "=&r" (_temp_mstatus) \
256+
: "r" (interrupt_save) \
257+
: "memory"); \
258+
}
259+
260+
#else
261+
262+
#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save;
263+
264+
#define TX_DISABLE interrupt_save = _tx_thread_interrupt_control(TX_INT_DISABLE);
265+
#define TX_RESTORE _tx_thread_interrupt_control(interrupt_save);
266+
267+
#endif /* TX_DISABLE_INLINE */
268+
269+
270+
/* Define the interrupt lockout macros for each ThreadX object. */
271+
272+
#define TX_BLOCK_POOL_DISABLE TX_DISABLE
273+
#define TX_BYTE_POOL_DISABLE TX_DISABLE
274+
#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE
275+
#define TX_MUTEX_DISABLE TX_DISABLE
276+
#define TX_QUEUE_DISABLE TX_DISABLE
277+
#define TX_SEMAPHORE_DISABLE TX_DISABLE
278+
279+
280+
/* Define the version ID of ThreadX. This may be utilized by the application. */
281+
282+
#ifndef __ASSEMBLER__
283+
#ifdef TX_THREAD_INIT
284+
CHAR _tx_version_id[] =
285+
"Copyright (c) 2024 Microsoft Corporation. * ThreadX RISC-V32/GNU Version 6.4.2 *";
286+
#else
287+
extern CHAR _tx_version_id[];
288+
#endif /* TX_THREAD_INIT */
289+
#endif /* __ASSEMBLER__ */
290+
291+
#endif /* TX_PORT_H */

0 commit comments

Comments
 (0)