Skip to content

Commit 5d2c393

Browse files
committed
Add RISC-V32 QEMU-virt example
This commit introduces the complete example build environment for the RISC-V32/GNU port targeting the QEMU virt machine. It includes basic BSP components, startup code, drivers, linker script, and a minimal ThreadX demo application. Signed-off-by: Akif Ejaz <akif.ejaz@10xengineers.ai>
1 parent c4ad279 commit 5d2c393

File tree

14 files changed

+1437
-0
lines changed

14 files changed

+1437
-0
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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+
#include "plic.h"
12+
#include "hwtimer.h"
13+
#include "uart.h"
14+
#include <stdint.h>
15+
#include <stddef.h>
16+
17+
void *memset(const void *des, int c,size_t n)
18+
{
19+
if((des == NULL) || n <=0)
20+
return (void*)des;
21+
char* t = (char*)des;
22+
int i;
23+
for(i=0;i<n;i++)
24+
t[i]=c;
25+
return t;
26+
}
27+
28+
29+
int board_init(void)
30+
{
31+
int ret;
32+
ret = plic_init();
33+
if(ret)
34+
return ret;
35+
ret = uart_init();
36+
if(ret)
37+
return ret;
38+
ret = hwtimer_init();
39+
if(ret)
40+
return ret;
41+
return 0;
42+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/bash
2+
pushd ../../../../../
3+
cmake -Bbuild -GNinja -DCMAKE_TOOLCHAIN_FILE=cmake/riscv32_gnu.cmake .
4+
cmake --build ./build/
5+
popd
Lines changed: 343 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,343 @@
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+
#ifndef RISCV_CSR_H
13+
#define RISCV_CSR_H
14+
15+
16+
// Machine Status Register, mstatus
17+
#define MSTATUS_MPP_MASK (3L << 11) // previous mode.
18+
#define MSTATUS_MPP_M (3L << 11)
19+
#define MSTATUS_MPP_S (1L << 11)
20+
#define MSTATUS_MPP_U (0L << 11)
21+
#define MSTATUS_MIE (1L << 3) // machine-mode interrupt enable.
22+
#define MSTATUS_MPIE (1L << 7)
23+
#define MSTATUS_FS (1L << 13)
24+
25+
// Machine-mode Interrupt Enable
26+
#define MIE_MTIE (1L << 7)
27+
#define MIE_MSIE (1L << 3)
28+
#define MIE_MEIE (1L << 11)
29+
#define MIE_STIE (1L << 5) // supervisor timer
30+
#define MIE_SSIE (1L << 1)
31+
#define MIE_SEIE (1L << 9)
32+
33+
// Supervisor Status Register, sstatus
34+
#define SSTATUS_SPP (1L << 8) // Previous mode, 1=Supervisor, 0=User
35+
#define SSTATUS_SPIE (1L << 5) // Supervisor Previous Interrupt Enable
36+
#define SSTATUS_UPIE (1L << 4) // User Previous Interrupt Enable
37+
#define SSTATUS_SIE (1L << 1) // Supervisor Interrupt Enable
38+
#define SSTATUS_UIE (1L << 0) // User Interrupt Enable
39+
#define SSTATUS_SPIE (1L << 5)
40+
#define SSTATUS_UPIE (1L << 4)
41+
42+
// Supervisor Interrupt Enable
43+
#define SIE_SEIE (1L << 9) // external
44+
#define SIE_STIE (1L << 5) // timer
45+
#define SIE_SSIE (1L << 1) // software
46+
47+
#ifndef __ASSEMBLER__
48+
49+
#include <stdint.h>
50+
51+
static inline uint32_t riscv_get_core()
52+
{
53+
uint32_t x;
54+
asm volatile("csrr %0, mhartid" : "=r" (x) );
55+
return x;
56+
}
57+
58+
static inline uint32_t riscv_get_mstatus()
59+
{
60+
uint32_t x;
61+
asm volatile("csrr %0, mstatus" : "=r" (x) );
62+
return x;
63+
}
64+
65+
static inline void riscv_writ_mstatus(uint32_t x)
66+
{
67+
asm volatile("csrw mstatus, %0" : : "r" (x));
68+
}
69+
70+
static inline void riscv_writ_mepc(uint32_t x)
71+
{
72+
asm volatile("csrw mepc, %0" : : "r" (x));
73+
}
74+
75+
static inline uint32_t riscv_get_sstatus()
76+
{
77+
uint32_t x;
78+
asm volatile("csrr %0, sstatus" : "=r" (x) );
79+
return x;
80+
}
81+
82+
static inline void riscv_writ_sstatus(uint32_t x)
83+
{
84+
asm volatile("csrw sstatus, %0" : : "r" (x));
85+
}
86+
87+
static inline uint32_t riscv_get_sip()
88+
{
89+
uint32_t x;
90+
asm volatile("csrr %0, sip" : "=r" (x) );
91+
return x;
92+
}
93+
94+
static inline void riscv_writ_sip(uint32_t x)
95+
{
96+
asm volatile("csrw sip, %0" : : "r" (x));
97+
}
98+
99+
static inline uint32_t riscv_get_sie()
100+
{
101+
uint32_t x;
102+
asm volatile("csrr %0, sie" : "=r" (x) );
103+
return x;
104+
}
105+
106+
static inline void riscv_writ_sie(uint32_t x)
107+
{
108+
asm volatile("csrw sie, %0" : : "r" (x));
109+
}
110+
111+
static inline uint32_t riscv_get_mie()
112+
{
113+
uint32_t x;
114+
asm volatile("csrr %0, mie" : "=r" (x) );
115+
return x;
116+
}
117+
118+
static inline void riscv_writ_mie(uint32_t x)
119+
{
120+
asm volatile("csrw mie, %0" : : "r" (x));
121+
}
122+
123+
static inline void riscv_writ_sepc(uint32_t x)
124+
{
125+
asm volatile("csrw sepc, %0" : : "r" (x));
126+
}
127+
128+
static inline uint32_t riscv_get_sepc()
129+
{
130+
uint32_t x;
131+
asm volatile("csrr %0, sepc" : "=r" (x) );
132+
return x;
133+
}
134+
135+
static inline uint32_t riscv_get_medeleg()
136+
{
137+
uint32_t x;
138+
asm volatile("csrr %0, medeleg" : "=r" (x) );
139+
return x;
140+
}
141+
142+
static inline void riscv_writ_medeleg(uint32_t x)
143+
{
144+
asm volatile("csrw medeleg, %0" : : "r" (x));
145+
}
146+
147+
static inline uint32_t riscv_get_mideleg()
148+
{
149+
uint32_t x;
150+
asm volatile("csrr %0, mideleg" : "=r" (x) );
151+
return x;
152+
}
153+
154+
static inline void riscv_writ_mideleg(uint32_t x)
155+
{
156+
asm volatile("csrw mideleg, %0" : : "r" (x));
157+
}
158+
159+
static inline void riscv_writ_stvec(uint32_t x)
160+
{
161+
asm volatile("csrw stvec, %0" : : "r" (x));
162+
}
163+
164+
static inline uint32_t riscv_get_stvec()
165+
{
166+
uint32_t x;
167+
asm volatile("csrr %0, stvec" : "=r" (x) );
168+
return x;
169+
}
170+
171+
static inline uint32_t riscv_get_stimecmp()
172+
{
173+
uint32_t x;
174+
asm volatile("csrr %0, 0x14d" : "=r" (x) );
175+
return x;
176+
}
177+
178+
static inline void riscv_writ_stimecmp(uint32_t x)
179+
{
180+
asm volatile("csrw 0x14d, %0" : : "r" (x));
181+
}
182+
183+
static inline uint32_t riscv_get_menvcfg()
184+
{
185+
uint32_t x;
186+
asm volatile("csrr %0, 0x30a" : "=r" (x) );
187+
return x;
188+
}
189+
190+
static inline void riscv_writ_menvcfg(uint32_t x)
191+
{
192+
asm volatile("csrw 0x30a, %0" : : "r" (x));
193+
}
194+
195+
static inline void riscv_writ_pmpcfg0(uint32_t x)
196+
{
197+
asm volatile("csrw pmpcfg0, %0" : : "r" (x));
198+
}
199+
200+
static inline void riscv_writ_pmpaddr0(uint32_t x)
201+
{
202+
asm volatile("csrw pmpaddr0, %0" : : "r" (x));
203+
}
204+
205+
static inline void riscv_writ_satp(uint32_t x)
206+
{
207+
asm volatile("csrw satp, %0" : : "r" (x));
208+
}
209+
210+
static inline uint32_t riscv_get_satp()
211+
{
212+
uint32_t x;
213+
asm volatile("csrr %0, satp" : "=r" (x) );
214+
return x;
215+
}
216+
217+
static inline uint32_t riscv_get_scause()
218+
{
219+
uint32_t x;
220+
asm volatile("csrr %0, scause" : "=r" (x) );
221+
return x;
222+
}
223+
224+
static inline uint32_t riscv_get_stval()
225+
{
226+
uint32_t x;
227+
asm volatile("csrr %0, stval" : "=r" (x) );
228+
return x;
229+
}
230+
231+
static inline void riscv_writ_mcounteren(uint32_t x)
232+
{
233+
asm volatile("csrw mcounteren, %0" : : "r" (x));
234+
}
235+
236+
static inline uint32_t riscv_get_mcounteren()
237+
{
238+
uint32_t x;
239+
asm volatile("csrr %0, mcounteren" : "=r" (x) );
240+
return x;
241+
}
242+
243+
static inline uint32_t riscv_get_time()
244+
{
245+
uint32_t x;
246+
asm volatile("csrr %0, time" : "=r" (x) );
247+
return x;
248+
}
249+
250+
static inline void riscv_sintr_on()
251+
{
252+
uint32_t sstatus = riscv_get_sstatus();
253+
sstatus |= SSTATUS_SIE;
254+
riscv_writ_sstatus(sstatus);
255+
}
256+
257+
static inline void riscv_sintr_off()
258+
{
259+
uint32_t sstatus = riscv_get_sstatus();
260+
sstatus &= (~SSTATUS_SIE);
261+
riscv_writ_sstatus(sstatus);
262+
}
263+
264+
static inline int riscv_sintr_get()
265+
{
266+
uint32_t x = riscv_get_sstatus();
267+
return (x & SSTATUS_SIE) != 0;
268+
}
269+
270+
static inline void riscv_sintr_restore(int x)
271+
{
272+
if(x)
273+
riscv_sintr_on();
274+
else
275+
riscv_sintr_off();
276+
}
277+
278+
static inline void riscv_mintr_on()
279+
{
280+
uint32_t mstatus = riscv_get_mstatus();
281+
mstatus |= MSTATUS_MIE;
282+
riscv_writ_mstatus(mstatus);
283+
}
284+
285+
static inline void riscv_mintr_off()
286+
{
287+
uint32_t mstatus = riscv_get_mstatus();
288+
mstatus &= (~MSTATUS_MIE);
289+
riscv_writ_mstatus(mstatus);
290+
}
291+
292+
static inline int riscv_mintr_get()
293+
{
294+
uint32_t x = riscv_get_mstatus();
295+
return (x & MSTATUS_MIE) != 0;
296+
}
297+
298+
static inline void riscv_mintr_restore(int x)
299+
{
300+
if(x)
301+
riscv_mintr_on();
302+
else
303+
riscv_mintr_off();
304+
}
305+
306+
static inline uint32_t riscv_get_sp()
307+
{
308+
uint32_t x;
309+
asm volatile("mv %0, sp" : "=r" (x) );
310+
return x;
311+
}
312+
313+
// read and write tp, the thread pointer, which xv6 uses to hold
314+
// this core's hartid (core number), the index into cpus[].
315+
static inline uint32_t riscv_get_tp()
316+
{
317+
uint32_t x;
318+
asm volatile("mv %0, tp" : "=r" (x) );
319+
return x;
320+
}
321+
322+
static inline void riscv_writ_tp(uint32_t x)
323+
{
324+
asm volatile("mv tp, %0" : : "r" (x));
325+
}
326+
327+
static inline uint32_t riscv_get_ra()
328+
{
329+
uint32_t x;
330+
asm volatile("mv %0, ra" : "=r" (x) );
331+
return x;
332+
}
333+
334+
// flush the TLB.
335+
static inline void sfence_vma()
336+
{
337+
// the zero, zero means flush all TLB entries.
338+
asm volatile("sfence.vma zero, zero");
339+
}
340+
341+
#endif // __ASSEMBLER__
342+
343+
#endif

0 commit comments

Comments
 (0)