tested with basic multithreaded app
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/8d6b13e6 Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/8d6b13e6 Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/8d6b13e6 Branch: refs/heads/develop Commit: 8d6b13e631ea831fd0a47dd7de682b62558d9150 Parents: 61a406f Author: julian <[email protected]> Authored: Tue Oct 18 15:02:16 2016 +0100 Committer: julian <[email protected]> Committed: Mon Nov 21 11:07:25 2016 +0000 ---------------------------------------------------------------------- libs/os/src/arch/mips/asm/ctx.S | 32 +++++++++++------- libs/os/src/arch/mips/os_arch_mips.c | 56 +++++++++++-------------------- 2 files changed, 40 insertions(+), 48 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8d6b13e6/libs/os/src/arch/mips/asm/ctx.S ---------------------------------------------------------------------- diff --git a/libs/os/src/arch/mips/asm/ctx.S b/libs/os/src/arch/mips/asm/ctx.S index c5a36fd..a851f90 100644 --- a/libs/os/src/arch/mips/asm/ctx.S +++ b/libs/os/src/arch/mips/asm/ctx.S @@ -34,6 +34,7 @@ #include <mips/hal.h> # note that k0 is not saved when using these macros. +# The cause register is saved but not resored. # saves to location k0 .macro _gpctx_save @@ -83,6 +84,8 @@ REG_S $9, CTX_BADVADDR(k0) mfc0 $9, C0_SR sw $9, CTX_STATUS(k0) + mfc0 $9, C0_CR + sw $9, CTX_CAUSE(k0) move $11, $0 move $12, $0 @@ -169,21 +172,26 @@ get_global_pointer: .global _mips_isr_sw0 .ent _mips_isr_sw0 _mips_isr_sw0: - /* context switch */ + # context switch .set noat - /* save k0 */ - REG_S $26, (CTX_REG(25) - CTX_SIZE) (sp) - addi k0, sp, 0 - CTX_SIZE - _gpctx_save /* save the context to sp - CTX_SIZE */ + # save k0 + REG_S $26, (CTX_REG(25) - CTX_SIZE) (sp) + addi k0, sp, -((((CTX_SIZE - 1) / 8) + 1) * 8) + _gpctx_save # save the context .set at - lw t0, g_current_task /* get current task */ - beqz t0, 1f - sw k0, 0(t0) /* update stored sp */ + lw t0, g_current_task # get current task + beqz t0, 1f + sw k0, 0(t0) # update stored sp 1: - lw t1, g_os_run_list /* get new task */ - sw t1, g_current_task /* g_current_task = g_os_run_list */ - lw a0, 0(t1) + lw t1, g_os_run_list # get new task + sw t1, g_current_task # g_current_task = g_os_run_list + mfc0 k0, C0_CR + andi k0, k0, 0xfeff # clear interrupt in cause register + lui k1, 0x0080 # make sure IV is set + or k0, k0, k1 + mtc0 k0, C0_CR + lw a0, 0(t1) .set noat - _gpctx_load /* update actual sp */ + _gpctx_load # updates actual sp eret .end http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8d6b13e6/libs/os/src/arch/mips/os_arch_mips.c ---------------------------------------------------------------------- diff --git a/libs/os/src/arch/mips/os_arch_mips.c b/libs/os/src/arch/mips/os_arch_mips.c index 3ca779b..7ac01a9 100644 --- a/libs/os/src/arch/mips/os_arch_mips.c +++ b/libs/os/src/arch/mips/os_arch_mips.c @@ -27,61 +27,43 @@ #include <mips/hal.h> #include <mips/uhi_syscalls.h> +#include <string.h> + extern void SVC_Handler(void); extern void PendSV_Handler(void); extern void SysTick_Handler(void); -/* XXX: determine how we will deal with running un-privileged */ +/* XXX: determine how to deal with running un-privileged */ /* only priv currently supported */ uint32_t os_flags = OS_RUN_PRIV; -/* fucntion to call from syscall */ -void (* volatile os_ftc)(void) = 0; extern struct os_task g_idle_task; -/* exception handler */ -void -_mips_handle_exception (struct gpctx* ctx, int exception) -{ - switch (exception) { - case EXC_SYS: - if (os_ftc != 0) { - os_ftc(); - os_ftc = 0; - return; - } - } - /* default handler for anything not handled above */ - __exception_handle(ctx, exception); -} - /* core timer interrupt */ void __attribute__((interrupt, keep_interrupts_masked)) _mips_isr_hw5(void) { + mips_setcompare(mips_getcompare() + 273000); timer_handler(); } static int os_in_isr(void) { - /* check the EXL bit XXX: Actually, that breaks it for some reason. */ - return 0; //(mips_getsr() & (1 << 1)) ? 1 : 0; + /* check the EXL bit */ + return (mips_getsr() & (1 << 1)) ? 1 : 0; } void timer_handler(void) { - /* This actually does the context switch by calling the below function if - necessary */ os_time_advance(1); } void os_arch_ctx_sw(struct os_task *t) { - if ((os_sched_get_current_task() != 0) && (t != 0)) - { + if ((os_sched_get_current_task() != 0) && (t != 0)) { os_sched_ctx_sw_hook(t); } @@ -111,26 +93,27 @@ os_arch_in_critical(void) reg_t get_global_pointer(void); +/* assumes stack_top will be 8 aligned */ + os_stack_t * os_arch_task_stack_init(struct os_task *t, os_stack_t *stack_top, int size) { - const size_t frame_size = sizeof(struct gpctx); - os_stack_t *s = stack_top - frame_size; + os_stack_t *s = stack_top - ((((sizeof(struct gpctx) - 1) / + OS_STACK_ALIGNMENT) + 1) * 2); struct gpctx ctx = { .r = { [3] = (reg_t)t->t_arg, [27] = get_global_pointer(), - [28] = (reg_t)stack_top + [28] = (reg_t)(stack_top - 4) }, - /* XXX: copying the status register from when the task was created - * seems like a modreately sensible thing to do? */ .status = mips_getsr(), + .cause = mips_getcr(), .epc = (reg_t)t->t_func }; /* copy struct onto the stack */ - *((struct gpctx*)s) = ctx; + memcpy(s, &ctx, sizeof(struct gpctx)); return (s); } @@ -138,6 +121,7 @@ os_arch_task_stack_init(struct os_task *t, os_stack_t *stack_top, int size) void os_arch_init(void) { + mips_bissr((1 << 15) | (1 << 8)); os_init_idle_task(); } @@ -168,13 +152,13 @@ os_arch_start(void) t = os_sched_next_task(); /* set the core timer compare register */ - /* XXX: take this magic number (for a 1ms tick from a 550MHz clock) and put + /* XXX: take this magic number (for a 1ms tick from a 546MHz clock) and put ** it in bsp or mcu somewhere */ - mips_setcompare(275000); + mips_setcompare(mips_getcount() + 273000); - /* enable core timer and software0 interupts and global enable */ - mips_bissr((1 << 15) | (1 << 8) | 1); + /* global interrupt enable */ + mips_bissr(1); /* Mark the OS as started, right before we run our first task */ g_os_started = 1; @@ -191,7 +175,7 @@ os_arch_os_start(void) os_error_t err; err = OS_ERR_IN_ISR; - if (os_in_isr() == 0) { // cause + if (os_in_isr() == 0) { err = OS_OK; /* should be in kernel mode here */ os_arch_start();
