Merge pull request #37 from kendryte/feature/new_sched

Refactor scheduler and interrupt handler
fix/double
sunnycase 2019-02-13 20:20:34 +08:00 committed by GitHub
commit 8f14b9dae3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 746 additions and 1026 deletions

View File

@ -14,12 +14,11 @@ add_compile_flags(LD
# C Flags Settings
add_compile_flags(BOTH
-mcmodel=medany
-march=rv64imafdc
-march=rv64imafc
-fno-common
-ffunction-sections
-fdata-sections
-fstrict-volatile-bitfields
-fno-zero-initialized-in-bss
-O2
-ggdb
)

View File

@ -53,12 +53,14 @@ SECTIONS
KEEP( *(.text.start) )
KEEP( *(.text.systick) )
} > ram : DATA
.init :
{
KEEP (*(SORT_NONE(.init)))
} > ram : DATA
. = ALIGN(8);
. = .;
.text :
{
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
@ -163,6 +165,7 @@ SECTIONS
} > ram : DATA
_edata = .; PROVIDE (edata = .);
. = ALIGN(8);
. = .;
__bss_start = .;
.sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } > ram : DYN_DATA

View File

@ -37,15 +37,15 @@ extern "C"
: "memory"); \
}
#define atomic_set(ptr, val) (*(volatile typeof(*(ptr))*)(ptr) = val)
#define atomic_read(ptr) (*(volatile typeof(*(ptr))*)(ptr))
#define atomic_set(ptr, val) (*(volatile typeof(*(ptr)) *)(ptr) = val)
#define atomic_read(ptr) (*(volatile typeof(*(ptr)) *)(ptr))
#define atomic_add(ptr, inc) __sync_fetch_and_add(ptr, inc)
#define atomic_or(ptr, inc) __sync_fetch_and_or(ptr, inc)
#define atomic_swap(ptr, swp) __sync_lock_test_and_set(ptr, swp)
#define atomic_cas(ptr, cmp, swp) __sync_val_compare_and_swap(ptr, cmp, swp)
static inline int spinlock_trylock(spinlock_t* lock)
static inline int spinlock_trylock(spinlock_t *lock)
{
int res = atomic_swap(&lock->lock, -1);
/*Use memory barrier to keep coherency */
@ -53,7 +53,7 @@ extern "C"
return res;
}
static inline void spinlock_lock(spinlock_t* lock)
static inline void spinlock_lock(spinlock_t *lock)
{
do
{
@ -62,7 +62,7 @@ extern "C"
} while (spinlock_trylock(lock));
}
static inline void spinlock_unlock(spinlock_t* lock)
static inline void spinlock_unlock(spinlock_t *lock)
{
/*Use memory barrier to keep coherency */
mb();
@ -83,7 +83,7 @@ extern "C"
.core = -1 \
}
static inline int corelock_trylock(corelock_t* lock)
static inline int corelock_trylock(corelock_t *lock)
{
int res = 0;
unsigned long core;
@ -115,7 +115,7 @@ extern "C"
return res;
}
static inline void corelock_lock(corelock_t* lock)
static inline void corelock_lock(corelock_t *lock)
{
unsigned long core;
@ -148,7 +148,7 @@ extern "C"
spinlock_unlock(&lock->lock);
}
static inline void corelock_unlock(corelock_t* lock)
static inline void corelock_unlock(corelock_t *lock)
{
unsigned long core;
@ -168,17 +168,7 @@ extern "C"
}
else
{
/* Different core release lock */
spinlock_unlock(&lock->lock);
register unsigned long a7 asm("a7") = 93;
register unsigned long a0 asm("a0") = 0;
register unsigned long a1 asm("a1") = 0;
register unsigned long a2 asm("a2") = 0;
asm volatile("scall"
: "+r"(a0)
: "r"(a1), "r"(a2), "r"(a7));
asm volatile("sbreak");
}
spinlock_unlock(&lock->lock);
}

View File

@ -160,6 +160,26 @@
#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V)
#define SYS_apc_return 2013
#define REG_EPC 0
#define REG_RA 1
#define REG_SP 2
#define REG_T0 5
#define REG_T1 6
#define REG_A0 10
#define REG_A1 11
#define REG_A2 12
#define REG_A3 13
#define REG_A4 14
#define REG_A5 15
#define REG_A6 16
#define REG_A7 17
#define REG_APC_PROC 64
#define REG_APC_RET 65
#define NUM_XCEPT_REGS (66)
#ifdef __riscv
#ifdef __riscv64

View File

@ -1,4 +1,4 @@
# Copyright 2018 Canaan Inc.
# Copyright 2018 Canaan Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -15,12 +15,18 @@
# define REGBYTES 8
# define STKSHIFT 16
# define IRQ_STACK_SIZE 20480
.global g_wake_address
.global g_irq_count
.global xPortStartScheduler
.global sys_apc_thunk
.section .text.start, "ax", @progbits
.globl _start
_start:
j 1f
.half 0x0000
nop
.word 0xdeadbeef
1:
csrw mideleg, 0
@ -29,6 +35,9 @@ _start:
csrw mip, 0
la t0, trap_entry
csrw mtvec, t0
li t0, 1
sd t0, _irq_enabled, t1
li x1, 0
li x2, 0
@ -66,266 +75,97 @@ _start:
csrs mstatus, t0
fssr x0
fmv.d.x f0, x0
fmv.d.x f1, x0
fmv.d.x f2, x0
fmv.d.x f3, x0
fmv.d.x f4, x0
fmv.d.x f5, x0
fmv.d.x f6, x0
fmv.d.x f7, x0
fmv.d.x f8, x0
fmv.d.x f9, x0
fmv.d.x f10,x0
fmv.d.x f11,x0
fmv.d.x f12,x0
fmv.d.x f13,x0
fmv.d.x f14,x0
fmv.d.x f15,x0
fmv.d.x f16,x0
fmv.d.x f17,x0
fmv.d.x f18,x0
fmv.d.x f19,x0
fmv.d.x f20,x0
fmv.d.x f21,x0
fmv.d.x f22,x0
fmv.d.x f23,x0
fmv.d.x f24,x0
fmv.d.x f25,x0
fmv.d.x f26,x0
fmv.d.x f27,x0
fmv.d.x f28,x0
fmv.d.x f29,x0
fmv.d.x f30,x0
fmv.d.x f31,x0
fmv.w.x f0, x0
fmv.w.x f1, x0
fmv.w.x f2, x0
fmv.w.x f3, x0
fmv.w.x f4, x0
fmv.w.x f5, x0
fmv.w.x f6, x0
fmv.w.x f7, x0
fmv.w.x f8, x0
fmv.w.x f9, x0
fmv.w.x f10,x0
fmv.w.x f11,x0
fmv.w.x f12,x0
fmv.w.x f13,x0
fmv.w.x f14,x0
fmv.w.x f15,x0
fmv.w.x f16,x0
fmv.w.x f17,x0
fmv.w.x f18,x0
fmv.w.x f19,x0
fmv.w.x f20,x0
fmv.w.x f21,x0
fmv.w.x f22,x0
fmv.w.x f23,x0
fmv.w.x f24,x0
fmv.w.x f25,x0
fmv.w.x f26,x0
fmv.w.x f27,x0
fmv.w.x f28,x0
fmv.w.x f29,x0
fmv.w.x f30,x0
fmv.w.x f31,x0
.option push
.option norelax
la gp, __global_pointer$
.option pop
la tp, _end + 63
and tp, tp, -64
csrr a0, mhartid
sll a2, a0, STKSHIFT
add tp, tp, a2
add sp, a0, 1
sll sp, sp, STKSHIFT
add sp, sp, tp
csrr t0, mhartid
beqz t0, 2f
la sp, _idle_stack1_top
la t0, g_wake_address
1:
lr.d t1, 0(t0)
beqz t1, 1b
jr t1
2:
la sp, _idle_stack0_top
# clear the bss segment
la t0, __bss_start
la t1, __bss_end
1:
sd zero, 0(t0)
addi t0, t0, 8
bltu t0, t1, 1b
j _init_bsp
la t0, _init_bsp
jr t0
# t0 = mhartid
# t1 = mhartid * 8
# t2 = _irq_count + t1
# t3 = _irq_count[t1]
.macro get_irq_count
csrr t0, mhartid
slli t1, t0, 3
la t2, g_irq_count
add t2, t2, t1
ld t3, 0(t2)
.endm
.globl trap_entry
.type trap_entry, @function
.align 2
trap_entry:
addi sp, sp, -REGBYTES
sd t0, 0x0(sp)
csrr t0, mcause
bgez t0, .handle_other
# Test soft interrupt
slli t0, t0, 1
addi t0, t0, -(IRQ_M_SOFT << 1)
bnez t0, .handle_irq
# Interupt is soft interrupt
# Get event
addi sp, sp, -REGBYTES
sd t1, 0x0(sp)
la t0, g_core_pending_switch
csrr t1, mhartid
slli t1, t1, 3
add t0, t0, t1
ld t1, 0x0(sp)
addi sp, sp, REGBYTES
# Test ContextSwitch event
ld t0, 0x0(t0)
beqz t0, .handle_irq
ld t0, 0x0(sp)
addi sp, sp, REGBYTES
# Do not use jal here
j xPortSysTickInt
csrw mscratch, t0
ld t0, _irq_enabled
bnez t0, 1f
# Disable interrupt
li t0, MSTATUS_MPIE
csrc mstatus, t0
csrr t0, mscratch
mret
.handle_irq:
ld t0, 0x0(sp)
addi sp, sp, REGBYTES
addi sp, sp, -36 * REGBYTES
sd ra, 0 * REGBYTES(sp)
sd t0, 1 * REGBYTES(sp)
sd t1, 2 * REGBYTES(sp)
sd t2, 3 * REGBYTES(sp)
sd a0, 4 * REGBYTES(sp)
sd a1, 5 * REGBYTES(sp)
sd a2, 6 * REGBYTES(sp)
sd a3, 7 * REGBYTES(sp)
sd a4, 8 * REGBYTES(sp)
sd a5, 9 * REGBYTES(sp)
sd a6, 10 * REGBYTES(sp)
sd a7, 11 * REGBYTES(sp)
sd t3, 12 * REGBYTES(sp)
sd t4, 13 * REGBYTES(sp)
sd t5, 14 * REGBYTES(sp)
sd t6, 15 * REGBYTES(sp)
fsd ft0, ( 0 + 16) * REGBYTES(sp)
fsd ft1, ( 1 + 16) * REGBYTES(sp)
fsd ft2, ( 2 + 16) * REGBYTES(sp)
fsd ft3, ( 3 + 16) * REGBYTES(sp)
fsd ft4, ( 4 + 16) * REGBYTES(sp)
fsd ft5, ( 5 + 16) * REGBYTES(sp)
fsd ft6, ( 6 + 16) * REGBYTES(sp)
fsd ft7, ( 7 + 16) * REGBYTES(sp)
fsd fa0, ( 8 + 16) * REGBYTES(sp)
fsd fa1, ( 9 + 16) * REGBYTES(sp)
fsd fa2, (10 + 16) * REGBYTES(sp)
fsd fa3, (11 + 16) * REGBYTES(sp)
fsd fa4, (12 + 16) * REGBYTES(sp)
fsd fa5, (13 + 16) * REGBYTES(sp)
fsd fa6, (14 + 16) * REGBYTES(sp)
fsd fa7, (15 + 16) * REGBYTES(sp)
fsd ft8, (16 + 16) * REGBYTES(sp)
fsd ft9, (17 + 16) * REGBYTES(sp)
fsd ft10, (18 + 16) * REGBYTES(sp)
fsd ft11, (19 + 16) * REGBYTES(sp)
csrr a0, mcause
csrr a1, mepc
jal handle_irq
li t0, MSTATUS_MPP | MSTATUS_MPIE
csrs mstatus, t0
ld ra, 0 * REGBYTES(sp)
ld t0, 1 * REGBYTES(sp)
ld t1, 2 * REGBYTES(sp)
ld t2, 3 * REGBYTES(sp)
ld a0, 4 * REGBYTES(sp)
ld a1, 5 * REGBYTES(sp)
ld a2, 6 * REGBYTES(sp)
ld a3, 7 * REGBYTES(sp)
ld a4, 8 * REGBYTES(sp)
ld a5, 9 * REGBYTES(sp)
ld a6, 10 * REGBYTES(sp)
ld a7, 11 * REGBYTES(sp)
ld t3, 12 * REGBYTES(sp)
ld t4, 13 * REGBYTES(sp)
ld t5, 14 * REGBYTES(sp)
ld t6, 15 * REGBYTES(sp)
fld ft0, ( 0 + 16) * REGBYTES(sp)
fld ft1, ( 1 + 16) * REGBYTES(sp)
fld ft2, ( 2 + 16) * REGBYTES(sp)
fld ft3, ( 3 + 16) * REGBYTES(sp)
fld ft4, ( 4 + 16) * REGBYTES(sp)
fld ft5, ( 5 + 16) * REGBYTES(sp)
fld ft6, ( 6 + 16) * REGBYTES(sp)
fld ft7, ( 7 + 16) * REGBYTES(sp)
fld fa0, ( 8 + 16) * REGBYTES(sp)
fld fa1, ( 9 + 16) * REGBYTES(sp)
fld fa2, (10 + 16) * REGBYTES(sp)
fld fa3, (11 + 16) * REGBYTES(sp)
fld fa4, (12 + 16) * REGBYTES(sp)
fld fa5, (13 + 16) * REGBYTES(sp)
fld fa6, (14 + 16) * REGBYTES(sp)
fld fa7, (15 + 16) * REGBYTES(sp)
fld ft8, (16 + 16) * REGBYTES(sp)
fld ft9, (17 + 16) * REGBYTES(sp)
fld ft10, (18 + 16) * REGBYTES(sp)
fld ft11, (19 + 16) * REGBYTES(sp)
addi sp, sp, 36 * REGBYTES
mret
.handle_other:
csrr t0, mcause
addi t0, t0, -CAUSE_USER_ECALL
bltz t0, .handle_except
.handle_syscall:
ld t0, 0x0(sp)
addi sp, sp, REGBYTES
addi sp, sp, -29 * REGBYTES
sd ra, 0 * REGBYTES(sp)
sd t0, 1 * REGBYTES(sp)
sd t1, 2 * REGBYTES(sp)
sd t2, 3 * REGBYTES(sp)
sd a6, 4 * REGBYTES(sp)
sd t3, 5 * REGBYTES(sp)
sd t4, 6 * REGBYTES(sp)
sd t5, 7 * REGBYTES(sp)
sd t6, 8 * REGBYTES(sp)
fsd ft0, ( 0 + 9) * REGBYTES(sp)
fsd ft1, ( 1 + 9) * REGBYTES(sp)
fsd ft2, ( 2 + 9) * REGBYTES(sp)
fsd ft3, ( 3 + 9) * REGBYTES(sp)
fsd ft4, ( 4 + 9) * REGBYTES(sp)
fsd ft5, ( 5 + 9) * REGBYTES(sp)
fsd ft6, ( 6 + 9) * REGBYTES(sp)
fsd ft7, ( 7 + 9) * REGBYTES(sp)
fsd fa0, ( 8 + 9) * REGBYTES(sp)
fsd fa1, ( 9 + 9) * REGBYTES(sp)
fsd fa2, (10 + 9) * REGBYTES(sp)
fsd fa3, (11 + 9) * REGBYTES(sp)
fsd fa4, (12 + 9) * REGBYTES(sp)
fsd fa5, (13 + 9) * REGBYTES(sp)
fsd fa6, (14 + 9) * REGBYTES(sp)
fsd fa7, (15 + 9) * REGBYTES(sp)
fsd ft8, (16 + 9) * REGBYTES(sp)
fsd ft9, (17 + 9) * REGBYTES(sp)
fsd ft10, (18 + 9) * REGBYTES(sp)
fsd ft11, (19 + 9) * REGBYTES(sp)
csrr a6, mepc
jal handle_syscall
csrw mepc, a1
# /* Run in machine mode */
li t0, MSTATUS_MPP | MSTATUS_MPIE
csrs mstatus, t0
ld ra, 0 * REGBYTES(sp)
ld t0, 1 * REGBYTES(sp)
ld t1, 2 * REGBYTES(sp)
ld t2, 3 * REGBYTES(sp)
ld a6, 4 * REGBYTES(sp)
ld t3, 5 * REGBYTES(sp)
ld t4, 6 * REGBYTES(sp)
ld t5, 7 * REGBYTES(sp)
ld t6, 8 * REGBYTES(sp)
fld ft0, ( 0 + 9) * REGBYTES(sp)
fld ft1, ( 1 + 9) * REGBYTES(sp)
fld ft2, ( 2 + 9) * REGBYTES(sp)
fld ft3, ( 3 + 9) * REGBYTES(sp)
fld ft4, ( 4 + 9) * REGBYTES(sp)
fld ft5, ( 5 + 9) * REGBYTES(sp)
fld ft6, ( 6 + 9) * REGBYTES(sp)
fld ft7, ( 7 + 9) * REGBYTES(sp)
fld fa0, ( 8 + 9) * REGBYTES(sp)
fld fa1, ( 9 + 9) * REGBYTES(sp)
fld fa2, (10 + 9) * REGBYTES(sp)
fld fa3, (11 + 9) * REGBYTES(sp)
fld fa4, (12 + 9) * REGBYTES(sp)
fld fa5, (13 + 9) * REGBYTES(sp)
fld fa6, (14 + 9) * REGBYTES(sp)
fld fa7, (15 + 9) * REGBYTES(sp)
fld ft8, (16 + 9) * REGBYTES(sp)
fld ft9, (17 + 9) * REGBYTES(sp)
fld ft10, (18 + 9) * REGBYTES(sp)
fld ft11, (19 + 9) * REGBYTES(sp)
addi sp, sp, 29 * REGBYTES
mret
.handle_except:
ld t0, 0x0(sp)
addi sp, sp, REGBYTES
addi sp, sp, -64 * REGBYTES
1:
csrr t0, mscratch
# Save context
addi sp, sp, -NUM_XCEPT_REGS * REGBYTES
sd x0, 0 * REGBYTES(sp)
sd x1, 1 * REGBYTES(sp)
sd x2, 2 * REGBYTES(sp)
sd x3, 3 * REGBYTES(sp)
sd x4, 4 * REGBYTES(sp)
sd x5, 5 * REGBYTES(sp)
sd x6, 6 * REGBYTES(sp)
@ -355,56 +195,184 @@ trap_entry:
sd x30, 30 * REGBYTES(sp)
sd x31, 31 * REGBYTES(sp)
fsd f0, ( 0 + 32) * REGBYTES(sp)
fsd f1, ( 1 + 32) * REGBYTES(sp)
fsd f2, ( 2 + 32) * REGBYTES(sp)
fsd f3, ( 3 + 32) * REGBYTES(sp)
fsd f4, ( 4 + 32) * REGBYTES(sp)
fsd f5, ( 5 + 32) * REGBYTES(sp)
fsd f6, ( 6 + 32) * REGBYTES(sp)
fsd f7, ( 7 + 32) * REGBYTES(sp)
fsd f8, ( 8 + 32) * REGBYTES(sp)
fsd f9, ( 9 + 32) * REGBYTES(sp)
fsd f10, (10 + 32) * REGBYTES(sp)
fsd f11, (11 + 32) * REGBYTES(sp)
fsd f12, (12 + 32) * REGBYTES(sp)
fsd f13, (13 + 32) * REGBYTES(sp)
fsd f14, (14 + 32) * REGBYTES(sp)
fsd f15, (15 + 32) * REGBYTES(sp)
fsd f16, (16 + 32) * REGBYTES(sp)
fsd f17, (17 + 32) * REGBYTES(sp)
fsd f18, (18 + 32) * REGBYTES(sp)
fsd f19, (19 + 32) * REGBYTES(sp)
fsd f20, (20 + 32) * REGBYTES(sp)
fsd f21, (21 + 32) * REGBYTES(sp)
fsd f22, (22 + 32) * REGBYTES(sp)
fsd f23, (23 + 32) * REGBYTES(sp)
fsd f24, (24 + 32) * REGBYTES(sp)
fsd f25, (25 + 32) * REGBYTES(sp)
fsd f26, (26 + 32) * REGBYTES(sp)
fsd f27, (27 + 32) * REGBYTES(sp)
fsd f28, (28 + 32) * REGBYTES(sp)
fsd f29, (29 + 32) * REGBYTES(sp)
fsd f30, (30 + 32) * REGBYTES(sp)
fsd f31, (31 + 32) * REGBYTES(sp)
fsw f0, ( 0 + 32) * REGBYTES(sp)
fsw f1, ( 1 + 32) * REGBYTES(sp)
fsw f2, ( 2 + 32) * REGBYTES(sp)
fsw f3, ( 3 + 32) * REGBYTES(sp)
fsw f4, ( 4 + 32) * REGBYTES(sp)
fsw f5, ( 5 + 32) * REGBYTES(sp)
fsw f6, ( 6 + 32) * REGBYTES(sp)
fsw f7, ( 7 + 32) * REGBYTES(sp)
fsw f8, ( 8 + 32) * REGBYTES(sp)
fsw f9, ( 9 + 32) * REGBYTES(sp)
fsw f10, (10 + 32) * REGBYTES(sp)
fsw f11, (11 + 32) * REGBYTES(sp)
fsw f12, (12 + 32) * REGBYTES(sp)
fsw f13, (13 + 32) * REGBYTES(sp)
fsw f14, (14 + 32) * REGBYTES(sp)
fsw f15, (15 + 32) * REGBYTES(sp)
fsw f16, (16 + 32) * REGBYTES(sp)
fsw f17, (17 + 32) * REGBYTES(sp)
fsw f18, (18 + 32) * REGBYTES(sp)
fsw f19, (19 + 32) * REGBYTES(sp)
fsw f20, (20 + 32) * REGBYTES(sp)
fsw f21, (21 + 32) * REGBYTES(sp)
fsw f22, (22 + 32) * REGBYTES(sp)
fsw f23, (23 + 32) * REGBYTES(sp)
fsw f24, (24 + 32) * REGBYTES(sp)
fsw f25, (25 + 32) * REGBYTES(sp)
fsw f26, (26 + 32) * REGBYTES(sp)
fsw f27, (27 + 32) * REGBYTES(sp)
fsw f28, (28 + 32) * REGBYTES(sp)
fsw f29, (29 + 32) * REGBYTES(sp)
fsw f30, (30 + 32) * REGBYTES(sp)
fsw f31, (31 + 32) * REGBYTES(sp)
csrr a0, mcause
csrr a1, mepc
mv a2, sp
add a3, sp, 32 * REGBYTES
jal handle_except
csrw mepc, a0
# Store mepc
csrr t0, mepc
sd t0, 0 * REGBYTES(sp)
# a0 = regs
mv a0, sp
# a1 = mcause
csrr a1, mcause
get_irq_count
# _irq_count++
addi t4, t3, 1
sd t4, 0(t2)
# Test if already in trap handler
bnez t3, 3f
# If not in trap handler, store sp
la t2, pxCurrentTCB
add t2, t2, t1
ld t2, 0(t2)
beqz t2, 1f
sd sp, 0(t2)
1:
# Then set sp to irq stack top
beqz t0, 2f
la sp, _irq_stack1_top
j 3f
2:
la sp, _irq_stack0_top
3:
la t0, handle_irq
jalr t0
# Disable interrupt
li t0, MSTATUS_MIE
csrc mstatus, t0
get_irq_count
# _irq_count--
addi t4, t3, -1
sd t4, 0(t2)
# If restore to task, use pxCurrentTCB instead of a0
bnez t4, 1f
.restore:
la t2, pxCurrentTCB
add t2, t2, t1
ld t2, 0(t2)
beqz t2, 1f
ld a0, 0(t2)
# Restore context
li t0, MSTATUS_MPP | MSTATUS_MPIE
csrs mstatus, t0
1:
# a0 = regs
# Restore mepc
ld t0, 0 * REGBYTES(a0)
csrw mepc, t0
# Store a0 to mscratch
ld t0, 10 * REGBYTES(a0)
csrw mscratch, t0
ld x1, 1 * REGBYTES(a0)
ld x2, 2 * REGBYTES(a0)
ld x4, 4 * REGBYTES(a0)
ld x5, 5 * REGBYTES(a0)
ld x6, 6 * REGBYTES(a0)
ld x7, 7 * REGBYTES(a0)
ld x8, 8 * REGBYTES(a0)
ld x9, 9 * REGBYTES(a0)
ld x11, 11 * REGBYTES(a0)
ld x12, 12 * REGBYTES(a0)
ld x13, 13 * REGBYTES(a0)
ld x14, 14 * REGBYTES(a0)
ld x15, 15 * REGBYTES(a0)
ld x16, 16 * REGBYTES(a0)
ld x17, 17 * REGBYTES(a0)
ld x18, 18 * REGBYTES(a0)
ld x19, 19 * REGBYTES(a0)
ld x20, 20 * REGBYTES(a0)
ld x21, 21 * REGBYTES(a0)
ld x22, 22 * REGBYTES(a0)
ld x23, 23 * REGBYTES(a0)
ld x24, 24 * REGBYTES(a0)
ld x25, 25 * REGBYTES(a0)
ld x26, 26 * REGBYTES(a0)
ld x27, 27 * REGBYTES(a0)
ld x28, 28 * REGBYTES(a0)
ld x29, 29 * REGBYTES(a0)
ld x30, 30 * REGBYTES(a0)
ld x31, 31 * REGBYTES(a0)
flw f0, ( 0 + 32) * REGBYTES(a0)
flw f1, ( 1 + 32) * REGBYTES(a0)
flw f2, ( 2 + 32) * REGBYTES(a0)
flw f3, ( 3 + 32) * REGBYTES(a0)
flw f4, ( 4 + 32) * REGBYTES(a0)
flw f5, ( 5 + 32) * REGBYTES(a0)
flw f6, ( 6 + 32) * REGBYTES(a0)
flw f7, ( 7 + 32) * REGBYTES(a0)
flw f8, ( 8 + 32) * REGBYTES(a0)
flw f9, ( 9 + 32) * REGBYTES(a0)
flw f10, (10 + 32) * REGBYTES(a0)
flw f11, (11 + 32) * REGBYTES(a0)
flw f12, (12 + 32) * REGBYTES(a0)
flw f13, (13 + 32) * REGBYTES(a0)
flw f14, (14 + 32) * REGBYTES(a0)
flw f15, (15 + 32) * REGBYTES(a0)
flw f16, (16 + 32) * REGBYTES(a0)
flw f17, (17 + 32) * REGBYTES(a0)
flw f18, (18 + 32) * REGBYTES(a0)
flw f19, (19 + 32) * REGBYTES(a0)
flw f20, (20 + 32) * REGBYTES(a0)
flw f21, (21 + 32) * REGBYTES(a0)
flw f22, (22 + 32) * REGBYTES(a0)
flw f23, (23 + 32) * REGBYTES(a0)
flw f24, (24 + 32) * REGBYTES(a0)
flw f25, (25 + 32) * REGBYTES(a0)
flw f26, (26 + 32) * REGBYTES(a0)
flw f27, (27 + 32) * REGBYTES(a0)
flw f28, (28 + 32) * REGBYTES(a0)
flw f29, (29 + 32) * REGBYTES(a0)
flw f30, (30 + 32) * REGBYTES(a0)
flw f31, (31 + 32) * REGBYTES(a0)
# Restore a0
addi sp, sp, NUM_XCEPT_REGS * REGBYTES
csrr a0, mscratch
mret
sys_apc_thunk:
addi sp, sp, -NUM_XCEPT_REGS * REGBYTES
ld t0, REG_APC_PROC * REGBYTES(sp)
sd a7, REG_APC_PROC * REGBYTES(sp)
jalr t0
ld x1, 1 * REGBYTES(sp)
ld x2, 2 * REGBYTES(sp)
ld x3, 3 * REGBYTES(sp)
ld x4, 4 * REGBYTES(sp)
ld x5, 5 * REGBYTES(sp)
ld x6, 6 * REGBYTES(sp)
ld x7, 7 * REGBYTES(sp)
ld x8, 8 * REGBYTES(sp)
ld x9, 9 * REGBYTES(sp)
ld x10, 10 * REGBYTES(sp)
ld x11, 11 * REGBYTES(sp)
ld x12, 12 * REGBYTES(sp)
ld x13, 13 * REGBYTES(sp)
@ -427,41 +395,43 @@ trap_entry:
ld x30, 30 * REGBYTES(sp)
ld x31, 31 * REGBYTES(sp)
fld f0, ( 0 + 32) * REGBYTES(sp)
fld f1, ( 1 + 32) * REGBYTES(sp)
fld f2, ( 2 + 32) * REGBYTES(sp)
fld f3, ( 3 + 32) * REGBYTES(sp)
fld f4, ( 4 + 32) * REGBYTES(sp)
fld f5, ( 5 + 32) * REGBYTES(sp)
fld f6, ( 6 + 32) * REGBYTES(sp)
fld f7, ( 7 + 32) * REGBYTES(sp)
fld f8, ( 8 + 32) * REGBYTES(sp)
fld f9, ( 9 + 32) * REGBYTES(sp)
fld f10, (10 + 32) * REGBYTES(sp)
fld f11, (11 + 32) * REGBYTES(sp)
fld f12, (12 + 32) * REGBYTES(sp)
fld f13, (13 + 32) * REGBYTES(sp)
fld f14, (14 + 32) * REGBYTES(sp)
fld f15, (15 + 32) * REGBYTES(sp)
fld f16, (16 + 32) * REGBYTES(sp)
fld f17, (17 + 32) * REGBYTES(sp)
fld f18, (18 + 32) * REGBYTES(sp)
fld f19, (19 + 32) * REGBYTES(sp)
fld f20, (20 + 32) * REGBYTES(sp)
fld f21, (21 + 32) * REGBYTES(sp)
fld f22, (22 + 32) * REGBYTES(sp)
fld f23, (23 + 32) * REGBYTES(sp)
fld f24, (24 + 32) * REGBYTES(sp)
fld f25, (25 + 32) * REGBYTES(sp)
fld f26, (26 + 32) * REGBYTES(sp)
fld f27, (27 + 32) * REGBYTES(sp)
fld f28, (28 + 32) * REGBYTES(sp)
fld f29, (29 + 32) * REGBYTES(sp)
fld f30, (30 + 32) * REGBYTES(sp)
fld f31, (31 + 32) * REGBYTES(sp)
addi sp, sp, 64 * REGBYTES
mret
flw f0, ( 0 + 32) * REGBYTES(sp)
flw f1, ( 1 + 32) * REGBYTES(sp)
flw f2, ( 2 + 32) * REGBYTES(sp)
flw f3, ( 3 + 32) * REGBYTES(sp)
flw f4, ( 4 + 32) * REGBYTES(sp)
flw f5, ( 5 + 32) * REGBYTES(sp)
flw f6, ( 6 + 32) * REGBYTES(sp)
flw f7, ( 7 + 32) * REGBYTES(sp)
flw f8, ( 8 + 32) * REGBYTES(sp)
flw f9, ( 9 + 32) * REGBYTES(sp)
flw f10, (10 + 32) * REGBYTES(sp)
flw f11, (11 + 32) * REGBYTES(sp)
flw f12, (12 + 32) * REGBYTES(sp)
flw f13, (13 + 32) * REGBYTES(sp)
flw f14, (14 + 32) * REGBYTES(sp)
flw f15, (15 + 32) * REGBYTES(sp)
flw f16, (16 + 32) * REGBYTES(sp)
flw f17, (17 + 32) * REGBYTES(sp)
flw f18, (18 + 32) * REGBYTES(sp)
flw f19, (19 + 32) * REGBYTES(sp)
flw f20, (20 + 32) * REGBYTES(sp)
flw f21, (21 + 32) * REGBYTES(sp)
flw f22, (22 + 32) * REGBYTES(sp)
flw f23, (23 + 32) * REGBYTES(sp)
flw f24, (24 + 32) * REGBYTES(sp)
flw f25, (25 + 32) * REGBYTES(sp)
flw f26, (26 + 32) * REGBYTES(sp)
flw f27, (27 + 32) * REGBYTES(sp)
flw f28, (28 + 32) * REGBYTES(sp)
flw f29, (29 + 32) * REGBYTES(sp)
flw f30, (30 + 32) * REGBYTES(sp)
flw f31, (31 + 32) * REGBYTES(sp)
addi sp, sp, NUM_XCEPT_REGS * REGBYTES
li a7, SYS_apc_return
ecall
j .
.global _init
.type _init, @function
@ -471,4 +441,32 @@ _init:
_fini:
ret
.size _init, .-_init
.size _fini, .-_fini
.size _fini, .-_fini
xPortStartScheduler:
la t0, vPortSetupTimer
jalr t0
csrr t0, mhartid
slli t1, t0, 3
j .restore
.align 3
g_irq_count:
.8byte 0
.8byte 0
_irq_enabled:
.8byte 0
g_wake_address:
.8byte 0
.section .bss
.align 3
_irq_stack_base:
.space IRQ_STACK_SIZE
_irq_stack0_top:
.space IRQ_STACK_SIZE
_irq_stack1_top:
.space IRQ_STACK_SIZE
_idle_stack0_top:
.space IRQ_STACK_SIZE
_idle_stack1_top:

View File

@ -589,7 +589,7 @@ private:
}
if (xHigherPriorityTaskWoken)
portYIELD();
portYIELD_FROM_ISR();
}
static int is_memory(uintptr_t address)

View File

@ -520,7 +520,7 @@ private:
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(driver.session_.stage_completion_event, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken)
portYIELD();
portYIELD_FROM_ISR();
}
private:

View File

@ -83,7 +83,7 @@ static void plic_complete_irq(uint32_t source)
}
/* Entry Point for PLIC Interrupt Handler */
extern "C" void handle_irq_m_ext(uintptr_t cause, uintptr_t epc)
extern "C" void handle_irq_m_ext(uintptr_t *regs, uintptr_t cause)
{
/**
* After the highest-priority pending interrupt is claimed by a target
@ -95,22 +95,22 @@ extern "C" void handle_irq_m_ext(uintptr_t cause, uintptr_t epc)
* without first restoring the interrupted context and taking another
* interrupt trap.
*/
if (read_csr(mip) & MIP_MEIP)
//if (read_csr(mip) & MIP_MEIP)
{
/* Get current core id */
uint64_t core_id = read_csr(mhartid);
uint64_t ie_flag = read_csr(mie);
// uint64_t ie_flag = read_csr(mie);
uint32_t int_num = plic.targets.target[core_id].claim_complete;
uint32_t int_threshold = plic.targets.target[core_id].priority_threshold;
plic.targets.target[core_id].priority_threshold = plic.source_priorities.priority[int_num];
clear_csr(mie, MIP_MTIP | MIP_MSIP);
set_csr(mstatus, MSTATUS_MIE);
//clear_csr(mie, MIP_MTIP | MIP_MSIP);
//set_csr(mstatus, MSTATUS_MIE);
kernel_iface_pic_on_irq(int_num);
plic_complete_irq(int_num);
clear_csr(mstatus, MSTATUS_MIE);
set_csr(mstatus, MSTATUS_MPIE | MSTATUS_MPP);
write_csr(mie, ie_flag);
//clear_csr(mstatus, MSTATUS_MIE);
//set_csr(mstatus, MSTATUS_MPIE | MSTATUS_MPP);
//write_csr(mie, ie_flag);
plic.targets.target[core_id].priority_threshold = int_threshold;
}
}

View File

@ -18,15 +18,16 @@
#include <syslog.h>
#include <uarths.h>
#include "dump.h"
#include "interrupt.h"
#define DUMP_PRINTF printk
static corelock_t s_dump_lock = CORELOCK_INIT;
void dump_core(const char* reason, uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
void dump_core(const char *reason, uintptr_t *regs, uintptr_t cause)
{
static const char* const reg_usage[][2] = {
{"zero ", "Hard-wired zero"},
{"mpec ", "Machine exception program counter"},
{"ra ", "Return address"},
{"sp ", "Stack pointer"},
{"gp ", "Global pointer"},
@ -104,8 +105,10 @@ void dump_core(const char* reason, uintptr_t cause, uintptr_t epc, uintptr_t reg
if (!reason)
reason = unknown_reason;
uintptr_t *fregs = regs + 32;
DUMP_PRINTF("core %d, core dump: %s\n", (int)read_csr(mhartid), reason);
DUMP_PRINTF("Cause 0x%016lx, EPC 0x%016lx\n", cause, epc);
DUMP_PRINTF("Cause 0x%016lx\n", cause);
int i = 0;

View File

@ -12,28 +12,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "interrupt.h"
#include "pin_cfg_priv.h"
#include <FreeRTOSConfig.h>
#include <clint.h>
#include <fpioa.h>
#include <hal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysctl.h>
#include <uarths.h>
#include "pin_cfg_priv.h"
#include <stdio.h>
#define PLL1_OUTPUT_FREQ 160000000UL
#define PLL2_OUTPUT_FREQ 45158400UL
extern uint8_t __bss_start[];
extern uint8_t __bss_end[];
extern uint8_t _tls_data[];
extern int main(int argc, char* argv[]);
extern void __libc_init_array(void);
extern void __libc_fini_array(void);
extern int os_entry(int core_id, int number_of_cores, int (*user_main)(int, char**));
extern int main(int argc, char *argv[]);
extern int os_entry(int (*user_main)(int, char **));
static void setup_clocks()
{
@ -41,29 +38,15 @@ static void setup_clocks()
sysctl_pll_set_freq(SYSCTL_PLL2, PLL2_OUTPUT_FREQ);
}
static void init_bss(void)
void _init_bsp()
{
memset(__bss_start, 0, __bss_end - __bss_start);
}
/* Init FPIOA */
fpioa_init();
bsp_pin_setup();
/* Setup clocks */
setup_clocks();
/* Init UART */
uarths_init();
void _init_bsp(int core_id, int number_of_cores)
{
if (core_id == 0)
{
/* Initialize bss data to 0 */
init_bss();
/* Register finalization function */
atexit(__libc_fini_array);
/* Init libc array for C++ */
__libc_init_array();
/* Init FPIOA */
fpioa_init();
bsp_pin_setup();
/* Setup clocks */
setup_clocks();
/* Init UART */
uarths_init();
}
exit(os_entry(core_id, number_of_cores, main));
exit(os_entry(main));
}

View File

@ -12,81 +12,62 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dump.h"
#include "interrupt.h"
#include <encoding.h>
#include <stdlib.h>
#include "dump.h"
#ifndef UNUSED
#define UNUSED(x) (void)(x)
#endif
uintptr_t __attribute__((weak))
handle_misaligned_fetch(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
void __attribute__((weak)) handle_misaligned_fetch(uintptr_t *regs, uintptr_t cause)
{
dump_core("misaligned fetch", cause, epc, regs, fregs);
exit(1337);
return epc;
dump_core("misaligned fetch", regs, cause);
sys_exit(1337);
}
uintptr_t __attribute__((weak))
handle_fault_fetch(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
void __attribute__((weak)) handle_fault_fetch(uintptr_t *regs, uintptr_t cause)
{
dump_core("fault fetch", cause, epc, regs, fregs);
exit(1337);
return epc;
dump_core("fault fetch", regs, cause);
sys_exit(1337);
}
uintptr_t __attribute__((weak))
handle_illegal_instruction(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
void __attribute__((weak)) handle_illegal_instruction(uintptr_t *regs, uintptr_t cause)
{
dump_core("illegal instruction", cause, epc, regs, fregs);
exit(1337);
return epc;
dump_core("illegal instruction", regs, cause);
sys_exit(1337);
}
uintptr_t __attribute__((weak))
handle_breakpoint(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
void __attribute__((weak)) handle_breakpoint(uintptr_t *regs, uintptr_t cause)
{
dump_core("breakpoint", cause, epc, regs, fregs);
exit(1337);
return epc;
dump_core("breakpoint", regs, cause);
sys_exit(1337);
}
uintptr_t __attribute__((weak))
handle_misaligned_load(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
void __attribute__((weak)) handle_misaligned_load(uintptr_t *regs, uintptr_t cause)
{
dump_core("misaligned load", cause, epc, regs, fregs);
exit(1337);
return epc;
dump_core("misaligned load", regs, cause);
sys_exit(1337);
}
uintptr_t __attribute__((weak))
handle_fault_load(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
void __attribute__((weak)) handle_fault_load(uintptr_t *regs, uintptr_t cause)
{
dump_core("fault load", cause, epc, regs, fregs);
exit(1337);
return epc;
dump_core("fault load", regs, cause);
sys_exit(1337);
}
uintptr_t __attribute__((weak))
handle_misaligned_store(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
void __attribute__((weak)) handle_misaligned_store(uintptr_t *regs, uintptr_t cause)
{
dump_core("misaligned store", cause, epc, regs, fregs);
exit(1337);
return epc;
dump_core("misaligned store", regs, cause);
sys_exit(1337);
}
uintptr_t __attribute__((weak))
handle_fault_store(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
void __attribute__((weak)) handle_fault_store(uintptr_t *regs, uintptr_t cause)
{
dump_core("fault store", cause, epc, regs, fregs);
exit(1337);
return epc;
dump_core("fault store", regs, cause);
sys_exit(1337);
}
uintptr_t handle_except(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32])
void handle_except(uintptr_t *regs, uintptr_t cause)
{
static uintptr_t(*const cause_table[])(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32]) = {
static void (*const cause_table[])(uintptr_t * regs, uintptr_t cause) = {
[CAUSE_MISALIGNED_FETCH] = handle_misaligned_fetch,
[CAUSE_FAULT_FETCH] = handle_fault_fetch,
[CAUSE_ILLEGAL_INSTRUCTION] = handle_illegal_instruction,
@ -97,5 +78,5 @@ uintptr_t handle_except(uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uint
[CAUSE_FAULT_STORE] = handle_fault_store
};
return cause_table[cause](cause, epc, regs, fregs);
cause_table[cause & CAUSE_HYPERVISOR_IRQ_REASON_MASK](regs, cause);
}

View File

@ -22,7 +22,7 @@ extern "C"
{
#endif
void dump_core(const char* reason, uintptr_t cause, uintptr_t epc, uintptr_t regs[32], uintptr_t fregs[32]);
void dump_core(const char *reason, uintptr_t *regs, uintptr_t cause);
#ifdef __cplusplus
}

View File

@ -15,6 +15,10 @@
#ifndef _BSP_INTERRUPT_H
#define _BSP_INTERRUPT_H
#include <stdint.h>
#include <stdbool.h>
#include <core_sync.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -36,7 +40,13 @@ extern "C" {
/* Supervisor interrupt reason mask for 64 bit system, 0x7FFF FFFF FFFF FFFF */
#define CAUSE_SUPERVISOR_IRQ_REASON_MASK (CAUSE_SUPERVISOR_IRQ_MASK - 1)
/* clang-format on */
void handle_except(uintptr_t *regs, uintptr_t cause);
void handle_irq_m_soft(uintptr_t *regs, uintptr_t cause);
void handle_irq_m_timer(uintptr_t *regs, uintptr_t cause);
void handle_irq_m_ext(uintptr_t *regs, uintptr_t cause);
void handle_syscall(uintptr_t *regs, uintptr_t cause);
void __attribute__((noreturn)) sys_exit(int code);
#ifdef __cplusplus
}
#endif

View File

@ -12,51 +12,51 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "interrupt.h"
#include "dump.h"
#include <stdint.h>
#include <stdlib.h>
#include <syslog.h>
#include "interrupt.h"
#include "dump.h"
#include <task.h>
static const char* TAG = "INTERRUPT";
static const char *TAG = "INTERRUPT";
void __attribute__((weak))
handle_irq_dummy(uintptr_t cause, uintptr_t epc)
void __attribute__((weak)) handle_irq_dummy(uintptr_t *regs, uintptr_t cause)
{
LOGE(TAG, "unhandled interrupt: Cause 0x%016lx, EPC 0x%016lx\n", cause, epc);
LOGE(TAG, "unhandled interrupt: Cause 0x%016lx, EPC 0x%016lx\n", cause, regs[REG_EPC]);
exit(1337);
}
void __attribute__((weak, alias("handle_irq_dummy")))
handle_irq_m_soft(uintptr_t cause, uintptr_t epc);
void __attribute__((weak, alias("handle_irq_dummy")))
handle_irq_m_timer(uintptr_t cause, uintptr_t epc);
void __attribute__((weak, alias("handle_irq_dummy")))
handle_irq_m_ext(uintptr_t cause, uintptr_t epc);
void __attribute__((weak))
handle_irq(uintptr_t cause, uintptr_t epc)
uintptr_t *handle_irq(uintptr_t *regs, uintptr_t cause)
{
// NMI
if (cause & CAUSE_MACHINE_IRQ_MASK)
{
#if defined(__GNUC__)
#pragma GCC diagnostic ignored "-Woverride-init"
#endif
/* clang-format off */
static void(* const irq_table[])(
uintptr_t cause,
uintptr_t epc) = {
[0 ... 14] = handle_irq_dummy,
[IRQ_M_SOFT] = handle_irq_m_soft,
[IRQ_M_TIMER] = handle_irq_m_timer,
[IRQ_M_EXT] = handle_irq_m_ext,
};
/* clang-format on */
/* clang-format off */
static void(* const irq_table[])(
uintptr_t *regs, uintptr_t cause) = {
[0 ... 14] = handle_irq_dummy,
[IRQ_M_SOFT] = handle_irq_m_soft,
[IRQ_M_TIMER] = handle_irq_m_timer,
[IRQ_M_EXT] = handle_irq_m_ext,
};
/* clang-format on */
#if defined(__GNUC__)
#pragma GCC diagnostic warning "-Woverride-init"
#endif
irq_table[cause & CAUSE_MACHINE_IRQ_REASON_MASK](cause, epc);
irq_table[cause & CAUSE_HYPERVISOR_IRQ_REASON_MASK](regs, cause);
}
else if (cause > CAUSE_USER_ECALL)
{
handle_syscall(regs, cause);
}
else
{
handle_except(regs, cause);
}
return regs;
}

View File

@ -92,23 +92,11 @@
#define UNUSED(x) (void)(x)
#endif
#define SYS_RET(epc_val, err_val) \
syscall_ret_t ret = { \
.err = err_val, \
.epc = epc_val \
}; \
return ret;
typedef struct _syscall_ret
{
uintptr_t err;
uintptr_t epc;
} syscall_ret_t;
static const char *TAG = "SYSCALL";
extern char _heap_start[];
extern char _heap_end[];
extern void sys_apc_thunk();
char *_heap_cur = &_heap_start[0];
void __attribute__((noreturn)) sys_exit(int code)
@ -125,6 +113,9 @@ static int sys_nosys(long a0, long a1, long a2, long a3, long a4, long a5, unsig
UNUSED(a4);
UNUSED(a5);
LOGW(TAG, "Unimplemented syscall 0x%lx\n", (uint64_t)n);
exit(ENOSYS);
return -ENOSYS;
}
@ -284,7 +275,7 @@ static int sys_gettimeofday(struct timeval *tp, void *tzp)
return 0;
}
static syscall_ret_t handle_ecall(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t epc, uintptr_t n)
static void handle_ecall(uintptr_t *regs)
{
enum syscall_id_e
{
@ -313,94 +304,76 @@ static syscall_ret_t handle_ecall(uintptr_t a0, uintptr_t a1, uintptr_t a2, uint
[SYS_ID_FSTAT] = (void *)sys_fstat,
[SYS_ID_CLOSE] = (void *)sys_close,
[SYS_ID_GETTIMEOFDAY] = (void *)sys_gettimeofday,
[SYS_ID_LSEEK] = (void *)sys_lseek,
[SYS_ID_LSEEK] = (void *)sys_lseek
};
#if defined(__GNUC__)
#pragma GCC diagnostic ignored "-Woverride-init"
#endif
static const uint8_t syscall_id_table[0x100] = {
[0x00 ... 0xFF] = SYS_ID_NOSYS,
[0xFF & SYS_exit] = SYS_ID_EXIT,
[0xFF & SYS_exit_group] = SYS_ID_EXIT,
[0xFF & SYS_getpid] = SYS_ID_NOSYS,
[0xFF & SYS_kill] = SYS_ID_NOSYS,
[0xFF & SYS_read] = SYS_ID_READ,
[0xFF & SYS_write] = SYS_ID_WRITE,
[0xFF & SYS_open] = SYS_ID_OPEN,
[0xFF & SYS_openat] = SYS_ID_NOSYS,
[0xFF & SYS_close] = SYS_ID_CLOSE,
[0xFF & SYS_lseek] = SYS_ID_LSEEK,
[0xFF & SYS_brk] = SYS_ID_BRK,
[0xFF & SYS_link] = SYS_ID_NOSYS,
[0xFF & SYS_unlink] = SYS_ID_NOSYS,
[0xFF & SYS_mkdir] = SYS_ID_NOSYS,
[0xFF & SYS_chdir] = SYS_ID_NOSYS,
[0xFF & SYS_getcwd] = SYS_ID_NOSYS,
[0xFF & SYS_stat] = SYS_ID_NOSYS,
[0xFF & SYS_fstat] = SYS_ID_FSTAT,
[0xFF & SYS_lstat] = SYS_ID_NOSYS,
[0xFF & SYS_fstatat] = SYS_ID_NOSYS,
[0xFF & SYS_access] = SYS_ID_NOSYS,
[0xFF & SYS_faccessat] = SYS_ID_NOSYS,
[0xFF & SYS_pread] = SYS_ID_NOSYS,
[0xFF & SYS_pwrite] = SYS_ID_NOSYS,
[0xFF & SYS_uname] = SYS_ID_NOSYS,
[0xFF & SYS_getuid] = SYS_ID_NOSYS,
[0xFF & SYS_geteuid] = SYS_ID_NOSYS,
[0xFF & SYS_getgid] = SYS_ID_NOSYS,
[0xFF & SYS_getegid] = SYS_ID_NOSYS,
[0xFF & SYS_mmap] = SYS_ID_NOSYS,
[0xFF & SYS_munmap] = SYS_ID_NOSYS,
[0xFF & SYS_mremap] = SYS_ID_NOSYS,
[0xFF & SYS_time] = SYS_ID_NOSYS,
[0xFF & SYS_getmainvars] = SYS_ID_NOSYS,
[0xFF & SYS_rt_sigaction] = SYS_ID_NOSYS,
[0xFF & SYS_writev] = SYS_ID_NOSYS,
[0xFF & SYS_gettimeofday] = SYS_ID_GETTIMEOFDAY,
[0xFF & SYS_times] = SYS_ID_NOSYS,
[0xFF & SYS_fcntl] = SYS_ID_NOSYS,
[0xFF & SYS_getdents] = SYS_ID_NOSYS,
[0xFF & SYS_dup] = SYS_ID_NOSYS,
};
uintptr_t n = regs[REG_A7];
if (n == SYS_apc_return)
{
regs[REG_EPC] = regs[REG_APC_RET];
regs[REG_A7] = regs[REG_APC_PROC];
}
else
{
uintptr_t syscall_id = SYS_ID_NOSYS;
switch (n)
{
case SYS_exit:
case SYS_exit_group:
syscall_id = SYS_ID_EXIT;
break;
case SYS_read:
syscall_id = SYS_ID_READ;
break;
case SYS_write:
syscall_id = SYS_ID_WRITE;
break;
case SYS_open:
syscall_id = SYS_ID_OPEN;
break;
case SYS_close:
syscall_id = SYS_ID_CLOSE;
break;
case SYS_lseek:
syscall_id = SYS_ID_LSEEK;
break;
case SYS_brk:
syscall_id = SYS_ID_BRK;
break;
case SYS_fstat:
syscall_id = SYS_ID_FSTAT;
break;
case SYS_gettimeofday:
syscall_id = SYS_ID_GETTIMEOFDAY;
break;
}
#if defined(__GNUC__)
#pragma GCC diagnostic warning "-Woverride-init"
#endif
uintptr_t err = syscall_table[syscall_id_table[0xFF & n]](
a0, /* a0 */
a1, /* a1 */
a2, /* a2 */
a3, /* a3 */
a4, /* a4 */
a5, /* a5 */
n /* n */
);
epc += 4;
SYS_RET(epc, err);
regs[REG_APC_PROC] = (uintptr_t)syscall_table[syscall_id];
regs[REG_APC_RET] = regs[REG_EPC] + 4;
regs[REG_EPC] = (uintptr_t)sys_apc_thunk;
}
}
syscall_ret_t __attribute__((weak, alias("handle_ecall")))
handle_ecall_u(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t epc, uintptr_t n);
void __attribute__((weak, alias("handle_ecall"))) handle_ecall_u(uintptr_t *regs);
void __attribute__((weak, alias("handle_ecall"))) handle_ecall_h(uintptr_t *regs);
void __attribute__((weak, alias("handle_ecall"))) handle_ecall_s(uintptr_t *regs);
void __attribute__((weak, alias("handle_ecall"))) handle_ecall_m(uintptr_t *regs);
syscall_ret_t __attribute__((weak, alias("handle_ecall")))
handle_ecall_h(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t epc, uintptr_t n);
syscall_ret_t __attribute__((weak, alias("handle_ecall")))
handle_ecall_s(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t epc, uintptr_t n);
syscall_ret_t __attribute__((weak, alias("handle_ecall")))
handle_ecall_m(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t epc, uintptr_t n);
syscall_ret_t handle_syscall(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t epc, uintptr_t n)
void handle_syscall(uintptr_t *regs, uintptr_t cause)
{
static syscall_ret_t (*const cause_table[])(uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t epc, uintptr_t n) = {
static void (*const cause_table[])(uintptr_t * regs) = {
[CAUSE_USER_ECALL] = handle_ecall_u,
[CAUSE_SUPERVISOR_ECALL] = handle_ecall_h,
[CAUSE_HYPERVISOR_ECALL] = handle_ecall_s,
[CAUSE_MACHINE_ECALL] = handle_ecall_m,
};
return cause_table[read_csr(mcause)](a0, a1, a2, a3, a4, a5, epc, n);
cause_table[cause & CAUSE_MACHINE_IRQ_REASON_MASK](regs);
}

View File

@ -13,12 +13,14 @@
* limitations under the License.
*/
#include "syscalls.h"
#include <FreeRTOS.h>
#include <devices.h>
#include <filesystem.h>
#include <kernel/driver_impl.hpp>
#include <string.h>
#include <sys/fcntl.h>
#include <sys/unistd.h>
#include <task.h>
using namespace sys;

View File

@ -92,7 +92,7 @@ enum
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
/* memory */
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 1024 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 20480 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 1024 * 1024 ) )
#define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 1
@ -114,7 +114,7 @@ enum
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE )
/* Main task */
#define configMAIN_TASK_PRIORITY 1
#define configMAIN_TASK_PRIORITY 0
#define configMAIN_TASK_STACK_SIZE (4096 * 8)
/* Set the following definitions to 1 to include the API function, or zero to exclude the API function. */
@ -127,6 +127,7 @@ enum
#define INCLUDE_vTaskDelay 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xTaskAbortDelay 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xSemaphoreGetMutexHolder 1

View File

@ -12,25 +12,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "FreeRTOS.h"
#include "task.h"
#include <atomic.h>
#include <clint.h>
#include <core_sync.h>
#include <encoding.h>
#include <plic.h>
#include "FreeRTOS.h"
#include "task.h"
volatile UBaseType_t g_core_pending_switch[portNUM_PROCESSORS] = { 0 };
static volatile UBaseType_t s_core_sync_events[portNUM_PROCESSORS] = { 0 };
static volatile TaskHandle_t s_pending_to_add_tasks[portNUM_PROCESSORS] = { 0 };
static volatile UBaseType_t s_core_awake[portNUM_PROCESSORS] = { 1, 0 };
static volatile UBaseType_t s_core_sync_in_progress[portNUM_PROCESSORS] = { 0 };
extern UBaseType_t *volatile pxCurrentTCB[portNUM_PROCESSORS];
extern volatile uintptr_t g_wake_address;
void handle_irq_m_soft(uintptr_t cause, uintptr_t epc)
static volatile core_sync_event_t s_core_sync_events[portNUM_PROCESSORS];
static corelock_t s_core_sync_locks[portNUM_PROCESSORS] = { CORELOCK_INIT, CORELOCK_INIT };
static volatile TaskHandle_t s_pending_to_add_tasks[portNUM_PROCESSORS];
void handle_irq_m_soft(uintptr_t *regs, uintptr_t cause)
{
uint64_t core_id = uxPortGetProcessorId();
atomic_set(&s_core_sync_in_progress[core_id], 1);
clint_ipi_clear(core_id);
switch (s_core_sync_events[core_id])
{
case CORE_SYNC_ADD_TCB:
@ -43,8 +42,8 @@ void handle_irq_m_soft(uintptr_t cause, uintptr_t epc)
}
}
break;
case CORE_SYNC_WAKE_UP:
atomic_set(&s_core_awake[core_id], 1);
case CORE_SYNC_SWITCH_CONTEXT:
vTaskSwitchContext();
break;
default:
break;
@ -53,68 +52,33 @@ void handle_irq_m_soft(uintptr_t cause, uintptr_t epc)
core_sync_complete(core_id);
}
void handle_irq_m_timer(uintptr_t cause, uintptr_t epc)
void core_sync_request(uint64_t core_id, int event)
{
if (pxCurrentTCB[uxPortGetProcessorId()])
{
prvSetNextTimerInterrupt();
/* Increment the RTOS tick. */
if (xTaskIncrementTick() != pdFALSE)
{
core_sync_request_context_switch(uxPortGetProcessorId());
}
}
else
{
clear_csr(mie, MIP_MTIP);
}
}
void core_sync_request_context_switch(uint64_t core_id)
{
atomic_set(&g_core_pending_switch[core_id], 1);
corelock_lock(&s_core_sync_locks[core_id]);
while (s_core_sync_events[core_id] != CORE_SYNC_NONE)
;
s_core_sync_events[core_id] = event;
clint_ipi_send(core_id);
corelock_unlock(&s_core_sync_locks[core_id]);
}
void core_sync_complete(uint64_t core_id)
{
if (atomic_read(&g_core_pending_switch[core_id]) == 0)
clint_ipi_clear(core_id);
atomic_set(&s_core_sync_events[core_id], CORE_SYNC_NONE);
atomic_set(&s_core_sync_in_progress[core_id], 0);
}
void core_sync_complete_context_switch(uint64_t core_id)
void core_sync_awaken(uintptr_t address)
{
if (atomic_read(&s_core_sync_events[core_id]) == CORE_SYNC_NONE)
clint_ipi_clear(core_id);
atomic_set(&g_core_pending_switch[core_id], 0);
g_wake_address = address;
}
int core_sync_is_awake(uint64_t core_id)
void vPortAddNewTaskToReadyListAsync(UBaseType_t core_id, void *pxNewTaskHandle)
{
return !!atomic_read(&s_core_awake[core_id]);
}
void core_sync_awaken(uint64_t core_id)
{
while (atomic_cas(&s_core_sync_events[core_id], CORE_SYNC_NONE, CORE_SYNC_WAKE_UP) != CORE_SYNC_NONE)
corelock_lock(&s_core_sync_locks[core_id]);
while (s_core_sync_events[core_id] != CORE_SYNC_NONE)
;
s_pending_to_add_tasks[core_id] = pxNewTaskHandle;
s_core_sync_events[core_id] = CORE_SYNC_ADD_TCB;
clint_ipi_send(core_id);
}
int core_sync_is_in_progress(uint64_t core_id)
{
return !!atomic_read(&s_core_sync_in_progress[core_id]);
}
void vPortAddNewTaskToReadyListAsync(UBaseType_t uxPsrId, void* pxNewTaskHandle)
{
// Wait for last adding tcb complete
while (atomic_read(&s_pending_to_add_tasks[uxPsrId]));
atomic_set(&s_pending_to_add_tasks[uxPsrId], pxNewTaskHandle);
while (atomic_cas(&s_core_sync_events[uxPsrId], CORE_SYNC_NONE, CORE_SYNC_ADD_TCB) != CORE_SYNC_NONE)
;
clint_ipi_send(uxPsrId);
corelock_unlock(&s_core_sync_locks[core_id]);
}

View File

@ -29,15 +29,12 @@ typedef enum
{
CORE_SYNC_NONE,
CORE_SYNC_ADD_TCB,
CORE_SYNC_WAKE_UP
CORE_SYNC_SWITCH_CONTEXT
} core_sync_event_t;
void core_sync_request_context_switch(uint64_t core_id);
void core_sync_complete_context_switch(uint64_t core_id);
void core_sync_request(uint64_t core_id, int event);
void core_sync_complete(uint64_t core_id);
int core_sync_is_awake(uint64_t core_id);
void core_sync_awaken(uint64_t core_id);
int core_sync_is_in_progress(uint64_t core_id);
void core_sync_awaken(uintptr_t address);
#ifdef __cplusplus
}

View File

@ -1,26 +1,29 @@
#include <sys/lock.h>
#include <stdlib.h>
#include "FreeRTOS.h"
#include "semphr.h"
#include "portmacro.h"
#include "semphr.h"
#include "task.h"
#include <stdlib.h>
#include <sys/lock.h>
typedef long _lock_t;
static void lock_init_generic(_lock_t *lock, uint8_t mutex_type)
{
portENTER_CRITICAL();
if (*lock)
if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED)
{
/* nothing to do until the scheduler is running */
portEXIT_CRITICAL();
return;
}
else
if (!*lock)
{
xSemaphoreHandle new_sem = xQueueCreateMutex(mutex_type);
if (!new_sem)
{
abort();
}
*lock = (_lock_t)new_sem;
}
portEXIT_CRITICAL();
}
@ -42,12 +45,11 @@ void _lock_close(_lock_t *lock)
if (*lock)
{
xSemaphoreHandle h = (xSemaphoreHandle)(*lock);
#if (INCLUDE_xSemaphoreGetMutexHolder == 1)
configASSERT(xSemaphoreGetMutexHolder(h) == NULL);
#endif
vSemaphoreDelete(h);
*lock = 0;
}
portEXIT_CRITICAL();
}
@ -58,20 +60,43 @@ static int lock_acquire_generic(_lock_t *lock, uint32_t delay, uint8_t mutex_typ
xSemaphoreHandle h = (xSemaphoreHandle)(*lock);
if (!h)
{
if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED)
return 0; /* locking is a no-op before scheduler is up, so this "succeeds" */
lock_init_generic(lock, mutex_type);
h = (xSemaphoreHandle)(*lock);
configASSERT(h != NULL);
}
BaseType_t success;
if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX)
if (uxPortIsInISR())
{
success = xSemaphoreTakeRecursive(h, delay);
/* In ISR Context */
if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX)
{
vPortDebugBreak();
abort(); /* recursive mutexes make no sense in ISR context */
}
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
success = xSemaphoreTakeFromISR(h, &xHigherPriorityTaskWoken);
if (!success && delay > 0)
{
vPortDebugBreak();
abort(); /* Tried to block on mutex from ISR, couldn't... rewrite your program to avoid libc interactions in ISRs! */
}
if (xHigherPriorityTaskWoken)
portYIELD_FROM_ISR();
}
else
{
success = xSemaphoreTake(h, delay);
if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX)
success = xSemaphoreTakeRecursive(h, delay);
else
success = xSemaphoreTake(h, delay);
}
return (success == pdTRUE) ? 0 : -1;
}
@ -103,15 +128,30 @@ static void lock_release_generic(_lock_t *lock, uint8_t mutex_type)
return;
}
if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX)
if (uxPortIsInISR())
{
xSemaphoreGiveRecursive(h);
if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX)
{
vPortDebugBreak();
abort(); /* recursive mutexes make no sense in ISR context */
}
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(h, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken)
portYIELD_FROM_ISR();
}
else
{
xSemaphoreGive(h);
if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX)
{
xSemaphoreGiveRecursive(h);
}
else
{
xSemaphoreGive(h);
}
}
}
void _lock_release(_lock_t *lock)

View File

@ -28,67 +28,61 @@ typedef struct
int ret;
} main_thunk_param_t;
extern void __libc_init_array(void);
extern void __libc_fini_array(void);
static StaticTask_t s_idle_task;
static StackType_t s_idle_task_stack[configMINIMAL_STACK_SIZE];
void start_scheduler(int core_id);
static void main_thunk(void *p)
{
main_thunk_param_t *param = (main_thunk_param_t *)p;
param->ret = param->user_main(0, 0);
}
void enable_core(int core_id)
{
core_sync_awaken(core_id);
}
int __attribute__((weak)) configure_fpioa()
{
return 0;
}
int os_entry(int core_id, int number_of_cores, int (*user_main)(int, char **))
static void main_thunk(void *p)
{
/* Register finalization function */
atexit(__libc_fini_array);
/* Init libc array for C++ */
__libc_init_array();
install_hal();
install_drivers();
configure_fpioa();
main_thunk_param_t *param = (main_thunk_param_t *)p;
param->ret = param->user_main(0, 0);
}
static void os_entry_core1()
{
clear_csr(mie, MIP_MTIP);
clint_ipi_enable();
set_csr(mstatus, MSTATUS_MIE);
if (core_id == 0)
{
install_hal();
install_drivers();
configure_fpioa();
TaskHandle_t mainTask;
main_thunk_param_t param = {};
param.user_main = user_main;
if (xTaskCreate(main_thunk, "Core 0 Main", configMAIN_TASK_STACK_SIZE, &param, configMAIN_TASK_PRIORITY, &mainTask) != pdPASS)
{
return -1;
}
enable_core(1);
start_scheduler(core_id);
return param.ret;
}
else
{
while (!core_sync_is_awake(core_id))
{
asm volatile("wfi");
}
start_scheduler(core_id);
return 0;
}
vTaskStartScheduler();
}
void start_scheduler(int core_id)
int os_entry(int (*user_main)(int, char **))
{
clear_csr(mie, MIP_MTIP);
clint_ipi_enable();
set_csr(mstatus, MSTATUS_MIE);
TaskHandle_t mainTask;
main_thunk_param_t param = {};
param.user_main = user_main;
if (xTaskCreate(main_thunk, "Core 0 Main", configMAIN_TASK_STACK_SIZE, &param, configMAIN_TASK_PRIORITY, &mainTask) != pdPASS)
{
return -1;
}
//core_sync_awaken((uintptr_t)os_entry_core1);
vTaskStartScheduler();
return param.ret;
}
void vApplicationIdleHook(void)

View File

@ -44,6 +44,10 @@
*----------------------------------------------------------*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "core_sync.h"
#include "portmacro.h"
#include "task.h"
#include <atomic.h>
#include <clint.h>
#include <encoding.h>
@ -52,17 +56,15 @@
#include <string.h>
#include <sysctl.h>
#include <syslog.h>
#include "core_sync.h"
#include "FreeRTOS.h"
#include "portmacro.h"
#include "task.h"
extern volatile uintptr_t g_irq_count[portNUM_PROCESSORS];
/* A variable is used to keep track of the critical section nesting. This
variable has to be stored as part of the task context and must be initialised to
a non zero value to ensure interrupts don't inadvertently become unmasked before
the scheduler starts. As it is stored as part of the task context it will
automatically be set to 0 when the first task is started. */
static UBaseType_t uxCriticalNesting[portNUM_PROCESSORS] = {[0 ... portNUM_PROCESSORS - 1] = 0xaaaaaaaa};
static UBaseType_t uxCriticalNesting[portNUM_PROCESSORS] = { [0 ... portNUM_PROCESSORS - 1] = 0xaaaaaaaa };
PRIVILEGED_DATA static corelock_t xCoreLock = CORELOCK_INIT;
UBaseType_t uxCPUClockRate = 390000000;
@ -70,7 +72,7 @@ UBaseType_t uxCPUClockRate = 390000000;
/* Contains context when starting scheduler, save all 31 registers */
#ifdef __gracefulExit
#error Not ported
BaseType_t xStartContext[31] = {0};
BaseType_t xStartContext[31] = { 0 };
#endif
/*
@ -93,15 +95,9 @@ UBaseType_t uxPortGetProcessorId()
return (UBaseType_t)read_csr(mhartid);
}
/*-----------------------------------------------------------*/
/* Sets and enable the timer interrupt */
void vPortSetupTimer(void)
UBaseType_t uxPortIsInISR()
{
UBaseType_t uxPsrId = uxPortGetProcessorId();
clint->mtimecmp[uxPsrId] = clint->mtime + (configTICK_CLOCK_HZ / configTICK_RATE_HZ);
/* Enable timer interupt */
__asm volatile("csrs mie,%0" ::"r"(0x80));
return g_irq_count[uxPortGetProcessorId()] > 0;
}
/*-----------------------------------------------------------*/
@ -111,10 +107,30 @@ void vPortSetupTimer(void)
void prvSetNextTimerInterrupt(void)
{
UBaseType_t uxPsrId = uxPortGetProcessorId();
clint->mtimecmp[uxPsrId] += (configTICK_CLOCK_HZ / configTICK_RATE_HZ);
clint->mtimecmp[uxPsrId] = clint->mtime + (configTICK_CLOCK_HZ / configTICK_RATE_HZ);
}
/*-----------------------------------------------------------*/
/* Sets and enable the timer interrupt */
void vPortSetupTimer(void)
{
prvSetNextTimerInterrupt();
/* Enable timer interupt */
__asm volatile("csrs mie,%0" ::"r"(0x80));
}
/*-----------------------------------------------------------*/
void handle_irq_m_timer(uintptr_t *regs, uintptr_t cause)
{
prvSetNextTimerInterrupt();
if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED)
return;
/* Increment the RTOS tick. */
if (xTaskIncrementTick() != pdFALSE)
vTaskSwitchContext();
}
void prvTaskExitError(void)
{
/* A function that implements a task must not exit or attempt to return to
@ -144,7 +160,7 @@ int vPortSetInterruptMask(void)
int ret;
__asm volatile("csrr %0,mie"
: "=r"(ret));
__asm volatile("csrc mie,%0" ::"i"(7));
__asm volatile("csrc mie,%0" ::"r"(0x888));
return ret;
}
/*-----------------------------------------------------------*/
@ -152,49 +168,44 @@ int vPortSetInterruptMask(void)
/*
* See header file for description.
*/
StackType_t* pxPortInitialiseStack(StackType_t* pxTopOfStack, TaskFunction_t pxCode, void* pvParameters)
StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters)
{
/* Simulate the stack frame as it would be created by a context switch
interrupt. */
pxTopOfStack -= 64;
memset(pxTopOfStack, 0, sizeof(StackType_t) * 64);
pxTopOfStack -= NUM_XCEPT_REGS;
memset(pxTopOfStack, 0, sizeof(StackType_t) * NUM_XCEPT_REGS);
pxTopOfStack[0] = (portSTACK_TYPE)prvTaskExitError; /* Register ra */
pxTopOfStack[1] = (portSTACK_TYPE)pxTopOfStack;
pxTopOfStack[8] = (portSTACK_TYPE)pvParameters; /* Register a0 */
pxTopOfStack[30] = 0; /* Register fsr */
pxTopOfStack[31] = (portSTACK_TYPE)pxCode; /* Register mepc */
pxTopOfStack[REG_RA] = (portSTACK_TYPE)prvTaskExitError; /* Register ra */
pxTopOfStack[REG_SP] = (portSTACK_TYPE)pxTopOfStack;
pxTopOfStack[REG_A0] = (portSTACK_TYPE)pvParameters; /* Register a0 */
pxTopOfStack[REG_EPC] = (portSTACK_TYPE)pxCode; /* Register mepc */
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
void vPortSysTickHandler(void)
{
core_sync_complete_context_switch(uxPortGetProcessorId());
vTaskSwitchContext();
}
/*-----------------------------------------------------------*/
void vPortEnterCritical(void)
{
if (!core_sync_is_in_progress(uxPortGetProcessorId()))
vTaskEnterCritical();
vTaskEnterCritical();
corelock_lock(&xCoreLock);
}
void vPortExitCritical(void)
{
corelock_unlock(&xCoreLock);
if (!core_sync_is_in_progress(uxPortGetProcessorId()))
vTaskExitCritical();
vTaskExitCritical();
}
void vPortYield()
{
core_sync_request_context_switch(uxPortGetProcessorId());
core_sync_request(uxPortGetProcessorId(), CORE_SYNC_SWITCH_CONTEXT);
}
void vPortFatal(const char* file, int line, const char* message)
void vPortYieldFromISR(void)
{
vTaskSwitchContext();
}
void vPortFatal(const char *file, int line, const char *message)
{
portDISABLE_INTERRUPTS();
corelock_lock(&xCoreLock);
@ -210,3 +221,8 @@ UBaseType_t uxPortGetCPUClock()
{
return uxCPUClockRate;
}
void vPortDebugBreak(void)
{
asm volatile("sbreak");
}

View File

@ -1,287 +0,0 @@
# Copyright 2018 Canaan Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
# All rights reserved
# VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
# This file is part of the FreeRTOS distribution and was contributed
# to the project by Technolution B.V. (www.technolution.nl,
# freertos-riscv@technolution.eu) under the terms of the FreeRTOS
# contributors license.
# FreeRTOS is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License (version 2) as published by the
# Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
# ***************************************************************************
# >>! NOTE: The modification to the GPL is included to allow you to !<<
# >>! distribute a combined work that includes FreeRTOS without being !<<
# >>! obliged to provide the source code for proprietary components !<<
# >>! outside of the FreeRTOS kernel. !<<
# ***************************************************************************
# FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. Full license text is available on the following
# link: http://www.freertos.org/a00114.html
# ***************************************************************************
# * *
# * FreeRTOS provides completely free yet professionally developed, *
# * robust, strictly quality controlled, supported, and cross *
# * platform software that is more than just the market leader, it *
# * is the industry's de facto standard. *
# * *
# * Help yourself get started quickly while simultaneously helping *
# * to support the FreeRTOS project by purchasing a FreeRTOS *
# * tutorial book, reference manual, or both: *
# * http://www.FreeRTOS.org/Documentation *
# * *
# ***************************************************************************
# http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
# the FAQ page "My application does not run, what could be wrong?". Have you
# defined configASSERT()?
# http://www.FreeRTOS.org/support - In return for receiving this top quality
# embedded software for free we request you assist our global community by
# participating in the support forum.
# http://www.FreeRTOS.org/training - Investing in training allows your team to
# be as productive as possible as early as possible. Now you can receive
# FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
# Ltd, and the world's leading authority on the world's leading RTOS.
# http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
# including FreeRTOS+Trace - an indispensable productivity tool, a DOS
# compatible FAT file system, and our tiny thread aware UDP/IP stack.
# http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
# Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
# http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
# Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
# licenses offer ticketed support, indemnification and commercial middleware.
# http://www.SafeRTOS.com - High Integrity Systems also provide a safety
# engineered and independently SIL3 certified version for use in safety and
# mission critical applications that require provable dependability.
# 1 tab == 4 spaces!
#
# include "encoding.h"
# define REGBYTES 8
.global xPortSysTickInt
.global xPortStartScheduler
.global vPortYield
.global vTaskIncrementTick
.global vPortEndScheduler
.global xExitStack
.global uxPortGetProcessorId
# /* Macro for saving task context */
.macro portSAVE_CONTEXT
.global pxCurrentTCB
# /* make room in stack */
addi sp, sp, -REGBYTES * 64
# /* Save Context */
sd ra, 0 * REGBYTES(sp)
sd sp, 1 * REGBYTES(sp)
sd tp, 2 * REGBYTES(sp)
sd t0, 3 * REGBYTES(sp)
sd t1, 4 * REGBYTES(sp)
sd t2, 5 * REGBYTES(sp)
sd s0, 6 * REGBYTES(sp)
sd s1, 7 * REGBYTES(sp)
sd a0, 8 * REGBYTES(sp)
sd a1, 9 * REGBYTES(sp)
sd a2, 10 * REGBYTES(sp)
sd a3, 11 * REGBYTES(sp)
sd a4, 12 * REGBYTES(sp)
sd a5, 13 * REGBYTES(sp)
sd a6, 14 * REGBYTES(sp)
sd a7, 15 * REGBYTES(sp)
sd s2, 16 * REGBYTES(sp)
sd s3, 17 * REGBYTES(sp)
sd s4, 18 * REGBYTES(sp)
sd s5, 19 * REGBYTES(sp)
sd s6, 20 * REGBYTES(sp)
sd s7, 21 * REGBYTES(sp)
sd s8, 22 * REGBYTES(sp)
sd s9, 23 * REGBYTES(sp)
sd s10, 24 * REGBYTES(sp)
sd s11, 25 * REGBYTES(sp)
sd t3, 26 * REGBYTES(sp)
sd t4, 27 * REGBYTES(sp)
sd t5, 28 * REGBYTES(sp)
sd t6, 29 * REGBYTES(sp)
frsr t0
sd t0, 30 * REGBYTES(sp)
csrr t0, mepc
sd t0, 31 * REGBYTES(sp)
fsd f0, ( 0 + 32) * REGBYTES(sp)
fsd f1, ( 1 + 32) * REGBYTES(sp)
fsd f2, ( 2 + 32) * REGBYTES(sp)
fsd f3, ( 3 + 32) * REGBYTES(sp)
fsd f4, ( 4 + 32) * REGBYTES(sp)
fsd f5, ( 5 + 32) * REGBYTES(sp)
fsd f6, ( 6 + 32) * REGBYTES(sp)
fsd f7, ( 7 + 32) * REGBYTES(sp)
fsd f8, ( 8 + 32) * REGBYTES(sp)
fsd f9, ( 9 + 32) * REGBYTES(sp)
fsd f10, (10 + 32) * REGBYTES(sp)
fsd f11, (11 + 32) * REGBYTES(sp)
fsd f12, (12 + 32) * REGBYTES(sp)
fsd f13, (13 + 32) * REGBYTES(sp)
fsd f14, (14 + 32) * REGBYTES(sp)
fsd f15, (15 + 32) * REGBYTES(sp)
fsd f16, (16 + 32) * REGBYTES(sp)
fsd f17, (17 + 32) * REGBYTES(sp)
fsd f18, (18 + 32) * REGBYTES(sp)
fsd f19, (19 + 32) * REGBYTES(sp)
fsd f20, (20 + 32) * REGBYTES(sp)
fsd f21, (21 + 32) * REGBYTES(sp)
fsd f22, (22 + 32) * REGBYTES(sp)
fsd f23, (23 + 32) * REGBYTES(sp)
fsd f24, (24 + 32) * REGBYTES(sp)
fsd f25, (25 + 32) * REGBYTES(sp)
fsd f26, (26 + 32) * REGBYTES(sp)
fsd f27, (27 + 32) * REGBYTES(sp)
fsd f28, (28 + 32) * REGBYTES(sp)
fsd f29, (29 + 32) * REGBYTES(sp)
fsd f30, (30 + 32) * REGBYTES(sp)
fsd f31, (31 + 32) * REGBYTES(sp)
# /* Store current stackpointer in task control block (TCB) */
la t0, pxCurrentTCB
csrr t1, mhartid
slli t1, t1, 3
add t0, t0, t1
ld t0, 0x0(t0)
sd sp, 0x0(t0)
.endm
# /* Macro for restoring task context */
.macro portRESTORE_CONTEXT
.global pxCurrentTCB
# /* Load stack pointer from the current TCB */
la t0, pxCurrentTCB
csrr t1, mhartid
slli t1, t1, 3
add t0, t0, t1
ld sp, 0x0(t0)
ld sp, 0x0(sp)
ld t0, 30 * REGBYTES(sp)
fssr t0
ld t0, 31 * REGBYTES(sp)
csrw mepc, t0
# /* Run in machine mode */
li t0, MSTATUS_MPP | MSTATUS_MPIE
csrs mstatus, t0
# /* Restore registers */
ld ra, 0 * REGBYTES(sp)
ld sp, 1 * REGBYTES(sp)
ld tp, 2 * REGBYTES(sp)
ld t0, 3 * REGBYTES(sp)
ld t1, 4 * REGBYTES(sp)
ld t2, 5 * REGBYTES(sp)
ld s0, 6 * REGBYTES(sp)
ld s1, 7 * REGBYTES(sp)
ld a0, 8 * REGBYTES(sp)
ld a1, 9 * REGBYTES(sp)
ld a2, 10 * REGBYTES(sp)
ld a3, 11 * REGBYTES(sp)
ld a4, 12 * REGBYTES(sp)
ld a5, 13 * REGBYTES(sp)
ld a6, 14 * REGBYTES(sp)
ld a7, 15 * REGBYTES(sp)
ld s2, 16 * REGBYTES(sp)
ld s3, 17 * REGBYTES(sp)
ld s4, 18 * REGBYTES(sp)
ld s5, 19 * REGBYTES(sp)
ld s6, 20 * REGBYTES(sp)
ld s7, 21 * REGBYTES(sp)
ld s8, 22 * REGBYTES(sp)
ld s9, 23 * REGBYTES(sp)
ld s10, 24 * REGBYTES(sp)
ld s11, 25 * REGBYTES(sp)
ld t3, 26 * REGBYTES(sp)
ld t4, 27 * REGBYTES(sp)
ld t5, 28 * REGBYTES(sp)
ld t6, 29 * REGBYTES(sp)
fld f0, ( 0 + 32) * REGBYTES(sp)
fld f1, ( 1 + 32) * REGBYTES(sp)
fld f2, ( 2 + 32) * REGBYTES(sp)
fld f3, ( 3 + 32) * REGBYTES(sp)
fld f4, ( 4 + 32) * REGBYTES(sp)
fld f5, ( 5 + 32) * REGBYTES(sp)
fld f6, ( 6 + 32) * REGBYTES(sp)
fld f7, ( 7 + 32) * REGBYTES(sp)
fld f8, ( 8 + 32) * REGBYTES(sp)
fld f9, ( 9 + 32) * REGBYTES(sp)
fld f10, (10 + 32) * REGBYTES(sp)
fld f11, (11 + 32) * REGBYTES(sp)
fld f12, (12 + 32) * REGBYTES(sp)
fld f13, (13 + 32) * REGBYTES(sp)
fld f14, (14 + 32) * REGBYTES(sp)
fld f15, (15 + 32) * REGBYTES(sp)
fld f16, (16 + 32) * REGBYTES(sp)
fld f17, (17 + 32) * REGBYTES(sp)
fld f18, (18 + 32) * REGBYTES(sp)
fld f19, (19 + 32) * REGBYTES(sp)
fld f20, (20 + 32) * REGBYTES(sp)
fld f21, (21 + 32) * REGBYTES(sp)
fld f22, (22 + 32) * REGBYTES(sp)
fld f23, (23 + 32) * REGBYTES(sp)
fld f24, (24 + 32) * REGBYTES(sp)
fld f25, (25 + 32) * REGBYTES(sp)
fld f26, (26 + 32) * REGBYTES(sp)
fld f27, (27 + 32) * REGBYTES(sp)
fld f28, (28 + 32) * REGBYTES(sp)
fld f29, (29 + 32) * REGBYTES(sp)
fld f30, (30 + 32) * REGBYTES(sp)
fld f31, (31 + 32) * REGBYTES(sp)
addi sp, sp, REGBYTES * 64
mret
.endm
xPortStartScheduler:
jal vPortSetupTimer
portRESTORE_CONTEXT
vPortEndScheduler:
ret
.section .text.systick, "ax", @progbits
xPortSysTickInt:
portSAVE_CONTEXT
call vPortSysTickHandler
portRESTORE_CONTEXT

View File

@ -94,12 +94,11 @@ typedef unsigned long UBaseType_t;
#define portCRITICAL_NESTING_IN_TCB 1
/*-----------------------------------------------------------*/
/* Scheduler utilities. */
extern void vPortYield( void );
#define portYIELD() vPortYield()
extern void vPortYield(void);
extern void vPortYieldFromISR(void);
#define portYIELD() vPortYield()
#define portYIELD_FROM_ISR() vPortYieldFromISR()
/*-----------------------------------------------------------*/
/* Architecture specific optimisations. */
@ -136,7 +135,9 @@ void vPortAddNewTaskToReadyListAsync(UBaseType_t uxPsrId, void* pxNewTaskHandle)
void vPortEnterCritical(void);
void vPortExitCritical(void);
UBaseType_t uxPortGetCPUClock();
UBaseType_t uxPortGetCPUClock(void);
UBaseType_t uxPortIsInISR(void);
void vPortDebugBreak(void);
#define portGET_PROCESSOR_ID() uxPortGetProcessorId()

View File

@ -2096,7 +2096,7 @@ void vTaskSuspendAll( void )
post in the FreeRTOS support forum before reporting this as a bug! -
http://goo.gl/wu4acr */
UBaseType_t uxPsrId = uxPortGetProcessorId();
++uxSchedulerSuspended[uxPsrId];
++uxSchedulerSuspended[uxPsrId];
}
/*----------------------------------------------------------*/
@ -2924,7 +2924,11 @@ UBaseType_t uxPsrId = uxPortGetProcessorId();
void vTaskSwitchContext( void )
{
UBaseType_t uxPsrId = uxPortGetProcessorId();
if( uxSchedulerSuspended[uxPsrId] != ( UBaseType_t ) pdFALSE )
if (xSchedulerRunning[uxPsrId] != pdTRUE)
{
return;
}
else if( uxSchedulerSuspended[uxPsrId] != ( UBaseType_t ) pdFALSE )
{
/* The scheduler is currently suspended - do not allow a context
switch. */
@ -3870,7 +3874,7 @@ UBaseType_t uxPsrId = uxPortGetProcessorId();
}
else
{
if( uxSchedulerSuspended[uxPsrId] == ( UBaseType_t ) pdFALSE )
if( uxSchedulerSuspended[uxPortGetProcessorId()] == ( UBaseType_t ) pdFALSE )
{
xReturn = taskSCHEDULER_RUNNING;
}

View File

@ -196,7 +196,7 @@ int pthread_join(pthread_t pthread, void **retval)
(void)xSemaphoreTake(&k_thrd->join_barrier, portMAX_DELAY);
/* Create a critical section to clean up the joined thread. */
vTaskSuspendAll();
//vTaskSuspendAll();
/* Release xJoinBarrier and delete it. */
(void)xSemaphoreGive(&k_thrd->join_barrier);
@ -219,7 +219,7 @@ int pthread_join(pthread_t pthread, void **retval)
delete k_thrd;
/* End the critical section. */
xTaskResumeAll();
//xTaskResumeAll();
}
return iStatus;

View File

@ -5,7 +5,10 @@
#include "ff.h"
#include <FreeRTOS.h>
#include <task.h>
#include <semphr.h>
#include <stdlib.h>
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
@ -38,7 +41,6 @@ void ff_memfree (
#if FF_FS_REENTRANT /* Mutal exclusion */
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object */
/*------------------------------------------------------------------------*/
@ -90,8 +92,24 @@ int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a gran
FF_SYNC_t sobj /* Sync object to wait */
)
{
/* FreeRTOS */
return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE);
if (uxPortIsInISR())
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
int success = (int)xSemaphoreTakeFromISR(sobj, &xHigherPriorityTaskWoken);
if (!success && FF_FS_TIMEOUT > 0)
{
vPortDebugBreak();
abort(); /* Tried to block on mutex from ISR, couldn't... rewrite your program to avoid libc interactions in ISRs! */
}
if (xHigherPriorityTaskWoken)
portYIELD_FROM_ISR();
return success;
}
else
{
/* FreeRTOS */
return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE);
}
}
@ -105,8 +123,18 @@ void ff_rel_grant (
FF_SYNC_t sobj /* Sync object to be signaled */
)
{
/* FreeRTOS */
xSemaphoreGive(sobj);
if (uxPortIsInISR())
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(sobj, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken)
portYIELD_FROM_ISR();
}
else
{
/* FreeRTOS */
xSemaphoreGive(sobj);
}
}
#endif

View File

@ -18,8 +18,8 @@ typedef unsigned short WORD;
typedef unsigned short WCHAR;
/* These types MUST be 32-bit */
typedef long LONG;
typedef unsigned long DWORD;
typedef int LONG;
typedef unsigned int DWORD;
/* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */
typedef unsigned long long QWORD;