Skip to content

Commit 5be7f3b

Browse files
feat: uCOS3 port for Sifive E2x RISC-V (#5)
-This commit contains changes for enabling interrupt(including timer interrupt) in uC-OS RISC V port. -Saving and restoring of registers during context switch (task to task, interrupt to task, task to interrupt) -Removed systick handler as we are directly calling OSTimeTick() from timer ISR. -Added comments in os_cpu_a.S file for better understanding of assembly line instruction. Signed-off-by: Gaurav <[email protected]>
1 parent 8512591 commit 5be7f3b

File tree

2 files changed

+116
-80
lines changed

2 files changed

+116
-80
lines changed

Ports/RISC-V/RV32/GCC/os_cpu_a.S

Lines changed: 116 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -35,25 +35,25 @@
3535
.extern OSPrioHighRdy
3636
.extern OSTCBCurPtr
3737
.extern OSTCBHighRdyPtr
38-
.extern OSIntExit
3938
.extern OSTaskSwHook
4039

4140

4241
.global OSStartHighRdy # Functions declared in this file
4342
.global OSCtxSw
4443
.global OSIntCtxSw
4544
.global Software_IRQHandler
45+
.global ucos_intr_exception_handler
4646

4747

4848
#********************************************************************************************************
4949
# EQUATES
5050
#********************************************************************************************************
5151

52-
.equ RISCV_MSTATUS_MIE, 0x08
52+
.equ RISCV_MSTATUS_MIE, 0x08
5353

54-
.equ RISCV_MIE_MSIE, 0x08 # M Soft Interrupt bit
54+
.equ ARCH_CPU_MCAUSE_INTR_MASK, 0x80000000
5555

56-
.equ RISCV_PRCI_BASE_ADDR, 0x44000000
56+
.equ ARCH_CPU_MCAUSE_CAUSE_MASK, 0x000003FF
5757

5858

5959
#********************************************************************************************************
@@ -78,27 +78,38 @@
7878

7979
OSStartHighRdy:
8080
# Disable interrupts
81+
# load immediately "RISCV_MSTATUS_MIE" into t0 register
8182
li t0, RISCV_MSTATUS_MIE
83+
# mstatus = mstatus & ~t0
8284
csrrc zero, mstatus, t0
8385

8486
# Execute OS task switch hook.
87+
# jump to OSTaskSwHook function(address) and store the next instruction
88+
# into link register
89+
# this function will get called each time when the context switch happens
8590
jal OSTaskSwHook
8691

8792
# OSRunning = TRUE;
8893
li t0, 0x01
94+
# load address of OSRunning into t1 register
8995
la t1, OSRunning
96+
# store byte value of t0 into memory address pointed by t1 with 0 offset
9097
sb t0, 0(t1)
9198

9299
# SWITCH TO HIGHEST PRIORITY TASK
93100
la t0, OSTCBHighRdyPtr
101+
# load word from address stored in [t0 + 0(offset)] to t1
94102
lw t1, 0(t0)
103+
# load word from address stored in [t1+ 0(offset)] into sp
95104
lw sp, 0(t1)
96105

97106
# Retrieve the location where to jump
98107
lw t0, 31 * 4(sp)
108+
# value stored in t0 is stored into mepc
99109
csrw mepc, t0
100110

101111
# Restore x1 to x31 registers
112+
# load word from memory addres [(0 * 4) + sp] into ra register
102113
lw ra, 0 * 4(sp)
103114
lw t0, 4 * 4(sp)
104115
lw t1, 5 * 4(sp)
@@ -129,6 +140,7 @@ OSStartHighRdy:
129140
lw t6, 30 * 4(sp)
130141

131142
# Compensate for the stack pointer
143+
# sp = sp + 32 * 4
132144
addi sp, sp, 32 * 4
133145

134146
# Use register t6 to jump to HIGHEST priority
@@ -147,66 +159,116 @@ OSStartHighRdy:
147159
# PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw()
148160
#
149161
# Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch. This function
150-
# triggers a synchronous software interrupt by writing into the MSIP register
162+
# triggers a ecall.
151163
#
152164
# 2) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as
153-
# the result of an interrupt. This function triggers a synchronous software interrupt by
154-
# writing into the MSIP register
165+
# the result of an interrupt. This function just return back as the context switch after interrupt
166+
# is executed just before exiting the interrupt handler.
155167
#********************************************************************************************************
168+
OSIntCtxSw:
169+
ret
156170

157171
OSCtxSw:
158-
OSIntCtxSw:
159-
# MIE_MSIE -- enable software interrupt bit
160-
li t0, RISCV_MIE_MSIE
161-
csrrs zero, mie, t0
162-
163-
# This will trigger a synchronous software interrupt; PRCI->MSIP[0] = 0x01;
164-
li t0, RISCV_PRCI_BASE_ADDR
165-
li t1, 0x1
166-
sw t1, 0x0(t0)
172+
ecall
167173
ret
168174

175+
# Exception handler should be 256 bytes aligned
176+
.align 8
177+
ucos_intr_exception_handler:
178+
# save regs to current sp
179+
addi sp, sp, -4*32
180+
# store contents of register ra into memory [(0 * 4) + sp]
181+
sw ra, 0 * 4(sp)
182+
sw t0, 4 * 4(sp)
183+
sw t1, 5 * 4(sp)
184+
sw t2, 6 * 4(sp)
185+
sw s0, 7 * 4(sp)
186+
sw s1, 8 * 4(sp)
187+
sw a0, 9 * 4(sp)
188+
sw a1, 10 * 4(sp)
189+
sw a2, 11 * 4(sp)
190+
sw a3, 12 * 4(sp)
191+
sw a4, 13 * 4(sp)
192+
sw a5, 14 * 4(sp)
193+
sw a6, 15 * 4(sp)
194+
sw a7, 16 * 4(sp)
195+
sw s2, 17 * 4(sp)
196+
sw s3, 18 * 4(sp)
197+
sw s4, 19 * 4(sp)
198+
sw s5, 20 * 4(sp)
199+
sw s6, 21 * 4(sp)
200+
sw s7, 22 * 4(sp)
201+
sw s8, 23 * 4(sp)
202+
sw s9, 24 * 4(sp)
203+
sw s10, 25 * 4(sp)
204+
sw s11, 26 * 4(sp)
205+
sw t3, 27 * 4(sp)
206+
sw t4, 28 * 4(sp)
207+
sw t5, 29 * 4(sp)
208+
sw t6, 30 * 4(sp)
209+
210+
# If it is a ecall, do not add 4 in mepc
211+
# otherwise add 4 in mepc
212+
li t1, ARCH_CPU_MCAUSE_CAUSE_MASK
213+
csrr t0, mcause
214+
# t3 = t1 & t0
215+
and t3, t1, t0
216+
li t1, 11
217+
csrr t0, mepc
218+
# If t1 != t3 jump to DONTADD:
219+
bne t1, t3, DONTADD
220+
addi t0, t0, 4
221+
222+
DONTADD: # for interrupt do not add 4 in mepc
223+
sw t0, 31*4(sp)
224+
# load address of OSTCBCurPtr into t0 register
225+
la t0, OSTCBCurPtr
226+
# load word from register [t0 + 0] address into t1
227+
lw t1, 0(t0)
228+
# store value stored in sp to [t1 + 0] address
229+
sw sp, 0(t1)
230+
231+
li t1, ARCH_CPU_MCAUSE_INTR_MASK
232+
csrr t0, mcause
233+
and t2, t1, t0
234+
bne t1, t2, run_exception_handler
235+
# it is a interrupt
236+
j run_interrupt_exception_handler
237+
238+
run_exception_handler:
239+
li t1, ARCH_CPU_MCAUSE_CAUSE_MASK
240+
csrr t0, mcause
241+
and t3, t1, t0
242+
li t1, 11
243+
bne t1, t3, run_interrupt_exception_handler
244+
# it is a ecall
245+
j run_ecall_handler
246+
247+
run_interrupt_exception_handler:
248+
jal osa_intr_master_isr
249+
250+
run_ecall_handler:
251+
j Software_IRQHandler
252+
253+
254+
169255

170256
#********************************************************************************************************
171257
# void Software_IRQHandler (void)
172258
#
173-
# Note(s) : 1) This function is defined with weak linking in 'riscv_hal_stubs.c' so that it can be
174-
# overridden by the kernel port with same prototype.
175-
#
176-
# 2) Pseudo-code is:
177-
# a) Disable global interrupts.
178-
# b) Clear soft interrupt for hart0.
179-
# c) Save the process SP in its TCB, OSTCBCurPtr->StkPtr = SP;
180-
# d) Call OSTaskSwHook();
181-
# e) Get current high priority, OSPrioCur = OSPrioHighRdy;
182-
# f) Get current ready thread TCB, OSTCBCurPtr = OSTCBHighRdyPtr;
183-
# g) Get new process SP from TCB, SP = OSTCBHighRdyPtr->StkPtr;
184-
# h) Retrieve the address at which exception happened
185-
# i) Restore x1-x31 from new process stack; x0 is always zero.
186-
# j) Perform exception return which will restore remaining context.
259+
# 1) Pseudo-code is:
260+
# a) Call OSTaskSwHook();
261+
# b) Get current high priority, OSPrioCur = OSPrioHighRdy;
262+
# c) Get current ready thread TCB, OSTCBCurPtr = OSTCBHighRdyPtr;
263+
# d) Get new process SP from TCB, SP = OSTCBHighRdyPtr->StkPtr;
264+
# e) Retrieve the address at which exception happened.
265+
# f) Restore x1-x31 from new process stack; x0 is always zero.
266+
# g) set MPIE = 1 to enable interrupt before returning.
267+
# h) Perform exception return which will restore remaining context.
187268
#
188-
# 3) On entry into Software_IRQHandler:
189-
# a) The initial register context save is being done by 'entry.S'
190-
# b) Stack pointer was passed by 'entry.s' in register a2.
191-
# c) OSTCBCurPtr points to the OS_TCB of the task to suspend
192-
# OSTCBHighRdyPtr points to the OS_TCB of the task to resume
193269
#********************************************************************************************************
194270

195271
Software_IRQHandler:
196-
# Disable interrupts globally and prevent interruption during context switch
197-
li t0, RISCV_MSTATUS_MIE
198-
csrrc zero, mstatus, t0
199-
200-
# Clear soft interrupt for hart0, PRCI->MSIP[0] = 0x00;
201-
li t0, RISCV_PRCI_BASE_ADDR
202-
sw zero, 0x0(t0)
203-
204-
# Stack pointer was passed by 'entry.s' in register a2.
205-
# OSTCBCurPtr->StkPtr = SP;
206-
la t0, OSTCBCurPtr
207-
lw t1, 0(t0)
208-
sw a2, 0(t1)
209-
210272
# Execute OS task switch hook.
211273
jal OSTaskSwHook
212274

@@ -259,12 +321,16 @@ Software_IRQHandler:
259321
lw t5, 29 * 4(sp)
260322
lw t6, 30 * 4(sp)
261323

324+
# Compensate for the stack pointer
262325
addi sp, sp, 4 * 32
263326

264327
# Exception return will restore remaining context
328+
# set MPIE = 1
329+
# interrupts will be enabled from here onwards
330+
li t0, 0x80
331+
csrrs zero, mstatus, t0
265332
mret
266333

267-
268334
#********************************************************************************************************
269335
# MODULE END
270336
#*********************************************************************************************************

Ports/RISC-V/RV32/GCC/os_cpu_c.c

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -443,36 +443,6 @@ void OSTimeTickHook (void)
443443
#endif
444444
}
445445

446-
447-
/*
448-
*********************************************************************************************************
449-
* SYS TICK HANDLER
450-
*
451-
* Description: Handle the system tick (SysTick) interrupt, which is used to generate the uC/OS-III tick
452-
* interrupt.
453-
*
454-
* Arguments : None.
455-
*
456-
* Note(s) : This function is defined with weak linking in 'riscv_hal_stubs.c' so that it can be
457-
* overridden by the kernel port with same prototype
458-
*********************************************************************************************************
459-
*/
460-
461-
void SysTick_Handler (void)
462-
{
463-
CPU_SR_ALLOC(); /* Allocate storage for CPU status register */
464-
465-
466-
CPU_CRITICAL_ENTER();
467-
OSIntEnter(); /* Tell uC/OS-III that we are starting an ISR */
468-
CPU_CRITICAL_EXIT();
469-
470-
OSTimeTick(); /* Call uC/OS-III's OSTimeTick() */
471-
472-
OSIntExit(); /* Tell uC/OS-III that we are leaving the ISR */
473-
}
474-
475-
476446
/*
477447
*********************************************************************************************************
478448
* EXTERNAL C LANGUAGE LINKAGE END

0 commit comments

Comments
 (0)