diff --git a/arch/misoc/src/Makefile b/arch/misoc/src/Makefile index 6a92f22910d..6a0285810b2 100644 --- a/arch/misoc/src/Makefile +++ b/arch/misoc/src/Makefile @@ -3,6 +3,7 @@ # # Copyright (C) 2016 Gregory Nutt. All rights reserved. # Author: Gregory Nutt +# Ramtin Amin # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -43,7 +44,6 @@ ifeq ($(CONFIG_WINDOWS_NATIVE),y) NUTTX = "$(TOPDIR)\nuttx$(EXEEXT)" INCLUDES += -I "$(ARCH_SRCDIR)\chip" INCLUDES += -I "$(ARCH_SRCDIR)\common" - INCLUDES += -I "$(ARCH_SRCDIR)\generated" INCLUDES += -I "$(ARCH_SRCDIR)\$(ARCH_SUBDIR)" INCLUDES += -I "$(TOPDIR)\sched" else @@ -52,14 +52,12 @@ ifeq ($(WINTOOL),y) NUTTX = "${shell cygpath -w $(TOPDIR)/nuttx$(EXEEXT)}" INCLUDES += -I "${shell cygpath -w $(ARCH_SRCDIR)/chip}" INCLUDES += -I "${shell cygpath -w $(ARCH_SRCDIR)/common}" - INCLUDES += -I "${shell cygpath -w $(ARCH_SRCDIR)/generated}" INCLUDES += -I "${shell cygpath -w $(ARCH_SRCDIR)/$(ARCH_SUBDIR)}" INCLUDES += -I "${shell cygpath -w $(TOPDIR)/sched}" else NUTTX = "$(TOPDIR)/nuttx$(EXEEXT)" INCLUDES += -I "$(ARCH_SRCDIR)/chip" INCLUDES += -I "$(ARCH_SRCDIR)/common" - INCLUDES += -I "$(ARCH_SRCDIR)/generated" INCLUDES += -I "$(ARCH_SRCDIR)/$(ARCH_SUBDIR)" INCLUDES += -I "$(TOPDIR)/sched" endif diff --git a/arch/misoc/src/common/misoc_isr.c b/arch/misoc/src/common/misoc_isr.c new file mode 100644 index 00000000000..96c726b17c2 --- /dev/null +++ b/arch/misoc/src/common/misoc_isr.c @@ -0,0 +1,20 @@ +#include + +void uart_isr(); +void uart_isr() +{ + +} + +void isr(void); +void isr(void) +{ + unsigned int irqs; + + irqs = irq_pending() & irq_getmask(); + + if (irqs & (1 << UART_INTERRUPT)) + { + uart_isr(); + } +} diff --git a/arch/misoc/src/common/misoc_uart.c b/arch/misoc/src/common/misoc_uart.c new file mode 100644 index 00000000000..7a36e78199c --- /dev/null +++ b/arch/misoc/src/common/misoc_uart.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_SERIAL_TERMIOS +# include +#endif + +#include +#include +#include + +#include +#include + +#include "hw/flags.h" +#include "misoc_irqasm.h" +#include "misoc_uart.h" + +#include "lm32.h" + +/* Buffer sizes must be a power of 2 so that modulos can be computed + * with logical AND. + */ + +#define UART_RINGBUFFER_SIZE_RX 128 +#define UART_RINGBUFFER_MASK_RX (UART_RINGBUFFER_SIZE_RX-1) + +static char rx_buf[UART_RINGBUFFER_SIZE_RX]; +static volatile unsigned int rx_produce; +static unsigned int rx_consume; + +#define UART_RINGBUFFER_SIZE_TX 128 +#define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX-1) + +static char tx_buf[UART_RINGBUFFER_SIZE_TX]; +static unsigned int tx_produce; +static volatile unsigned int tx_consume; + +static int uart_interrupt(int irq, void *context); + +static int uart_interrupt(int irq, void *context) +{ + unsigned int stat, rx_produce_next; + + stat = uart_ev_pending_read(); + + if(stat & UART_EV_RX) { + while(!uart_rxempty_read()) { + rx_produce_next = (rx_produce + 1) & UART_RINGBUFFER_MASK_RX; + if(rx_produce_next != rx_consume) { + rx_buf[rx_produce] = uart_rxtx_read(); + rx_produce = rx_produce_next; + } + uart_ev_pending_write(UART_EV_RX); + } + } + + if(stat & UART_EV_TX) { + uart_ev_pending_write(UART_EV_TX); + while((tx_consume != tx_produce) && !uart_txfull_read()) { + uart_rxtx_write(tx_buf[tx_consume]); + tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX; + } + } + + return OK; +} + +/* Do not use in interrupt handlers! */ +char uart_read(void) +{ + char c; + + if(irq_getie()) { + while(rx_consume == rx_produce); + } else if (rx_consume == rx_produce) { + return 0; + } + + c = rx_buf[rx_consume]; + rx_consume = (rx_consume + 1) & UART_RINGBUFFER_MASK_RX; + return c; +} + +int uart_read_nonblock(void) +{ + return (rx_consume != rx_produce); +} + +int up_putc(int ch) +{ + unsigned int oldmask; + unsigned int tx_produce_next = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX; + + if(irq_getie()) { + while(tx_produce_next == tx_consume); + } else if(tx_produce_next == tx_consume) { + return ch; + } + + oldmask = irq_getmask(); + irq_setmask(oldmask & ~(1 << UART_INTERRUPT)); + if((tx_consume != tx_produce) || uart_txfull_read()) { + tx_buf[tx_produce] = ch; + tx_produce = tx_produce_next; + } else { + uart_rxtx_write(ch); + } + irq_setmask(oldmask); + return ch; +} + +void uart_init(void) +{ + rx_produce = 0; + rx_consume = 0; + + tx_produce = 0; + tx_consume = 0; + + uart_ev_pending_write(uart_ev_pending_read()); + uart_ev_enable_write(UART_EV_TX | UART_EV_RX); + irq_setmask(irq_getmask() | (1 << UART_INTERRUPT)); + + irq_attach(1 << UART_INTERRUPT, uart_interrupt); +} + +void uart_sync(void) +{ + while(tx_consume != tx_produce); +} + + + diff --git a/arch/misoc/src/lm32/Make.defs b/arch/misoc/src/lm32/Make.defs new file mode 100644 index 00000000000..1c12e0c5270 --- /dev/null +++ b/arch/misoc/src/lm32/Make.defs @@ -0,0 +1,49 @@ +############################################################################ +# arch/misoc/src/Makefile +# +# Copyright (C) 2016 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# Ramtin Amin +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +HEAD_ASRC = lm32_vectors.S + +CMN_ASRCS = +CMN_CSRCS = misoc_uart.c + +CHIP_ASRCS = lm32_start.S lm32_syscall.S + +CHIP_CSRCS = lm32_allocateheap.c lm32_assert.c lm32_blocktask.c +CHIP_CSRCS += lm32_copystate.c lm32_createstack.c lm32_doirq.c lm32_dumpstate.c +CHIP_CSRCS += lm32_dumpstate.c lm32_exit.c lm32_idle.c lm32_initialize.c +CHIP_CSRCS += lm32_initialstate.c lm32_interruptcontext.c lm32_irq.c +CHIP_CSRCS += lm32_releasepending.c lm32_releasestack.c lm32_stackframe.c +CHIP_CSRCS += lm32_swint.c lm32_unblocktask.c diff --git a/arch/misoc/src/lm32/lm32.h b/arch/misoc/src/lm32/lm32.h index 8335c6917dd..fe18969c758 100644 --- a/arch/misoc/src/lm32/lm32.h +++ b/arch/misoc/src/lm32/lm32.h @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/misoc/src/common/lm32.h + * arch/misoc/src/lm32/lm32.h * * Copyright (C) 2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt @@ -144,7 +144,6 @@ void lm32_irq_initialize(void); /* System timer *************************************************************/ void lm32_timer_initialize(void); -int lm32_timerisr(int irq, void *context); /* Software interrupts ******************************************************/ diff --git a/arch/misoc/src/lm32/lm32_allocateheap.c b/arch/misoc/src/lm32/lm32_allocateheap.c index 4df88cecaf6..882bed891aa 100644 --- a/arch/misoc/src/lm32/lm32_allocateheap.c +++ b/arch/misoc/src/lm32/lm32_allocateheap.c @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/misoc/src/common/lm32_allocateheap.c + * arch/misoc/src/lm32/lm32_allocateheap.c * * Copyright (C) 2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt diff --git a/arch/misoc/src/lm32/lm32_assert.c b/arch/misoc/src/lm32/lm32_assert.c new file mode 100644 index 00000000000..78e7d2b6680 --- /dev/null +++ b/arch/misoc/src/lm32/lm32_assert.c @@ -0,0 +1,162 @@ +/**************************************************************************** + * arch/misoc/src/lm32/lm32_assert.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Ramtin Amin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "sched/sched.h" +#include "lm32.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* USB trace dumping */ + +#ifndef CONFIG_USBDEV_TRACE +# undef CONFIG_ARCH_USBDUMP +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _up_assert + ****************************************************************************/ + +static void _up_assert(int errorcode) noreturn_function; +static void _up_assert(int errorcode) +{ + /* Are we in an interrupt handler or the idle task? */ + + if (g_current_regs || this_task()->pid == 0) + { + (void)up_irq_save(); + for (; ; ) + { +#ifdef CONFIG_ARCH_LEDS + board_autoled_on(LED_PANIC); + up_mdelay(250); + board_autoled_off(LED_PANIC); + up_mdelay(250); +#endif + } + } + else + { + exit(errorcode); + } +} + +/**************************************************************************** + * Name: assert_tracecallback + ****************************************************************************/ + +#ifdef CONFIG_ARCH_USBDUMP +static int usbtrace_syslog(FAR const char *fmt, ...) +{ + va_list ap; + int ret; + + /* Let vsyslog do the real work */ + + va_start(ap, fmt); + ret = vsyslog(LOG_EMERG, fmt, ap); + va_end(ap); + return ret; +} + +static int assert_tracecallback(FAR struct usbtrace_s *trace, FAR void *arg) +{ + usbtrace_trprintf(usbtrace_syslog, trace->event, trace->value); + return 0; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_assert + ****************************************************************************/ + +void up_assert(const uint8_t *filename, int lineno) +{ +#if CONFIG_TASK_NAME_SIZE > 0 && defined(CONFIG_DEBUG_ALERT) + struct tcb_s *rtcb = this_task(); +#endif + + board_autoled_on(LED_ASSERTION); + +#if CONFIG_TASK_NAME_SIZE > 0 + _alert("Assertion failed at file:%s line: %d task: %s\n", + filename, lineno, rtcb->name); +#else + _alert("Assertion failed at file:%s line: %d\n", + filename, lineno); +#endif + + lm32_dumpstate(); + +#ifdef CONFIG_ARCH_USBDUMP + /* Dump USB trace data */ + + (void)usbtrace_enumerate(assert_tracecallback, NULL); +#endif + +#ifdef CONFIG_BOARD_CRASHDUMP + board_crashdump(up_getsp(), this_task(), filename, lineno); +#endif + + _up_assert(EXIT_FAILURE); +} diff --git a/arch/misoc/src/lm32/lm32_blocktask.c b/arch/misoc/src/lm32/lm32_blocktask.c new file mode 100644 index 00000000000..f313da11cca --- /dev/null +++ b/arch/misoc/src/lm32/lm32_blocktask.c @@ -0,0 +1,180 @@ +/**************************************************************************** + * arch/misoc/src/lm32/lm32_blocktask.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Ramtin Amin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "sched/sched.h" +#include "group/group.h" +#include "lm32.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_block_task + * + * Description: + * The currently executing task at the head of + * the ready to run list must be stopped. Save its context + * and move it to the inactive list specified by task_state. + * + * Inputs: + * tcb: Refers to a task in the ready-to-run list (normally + * the task at the head of the list). It most be + * stopped, its context saved and moved into one of the + * waiting task lists. It it was the task at the head + * of the ready-to-run list, then a context to the new + * ready to run task must be performed. + * task_state: Specifies which waiting task list should be + * hold the blocked task TCB. + * + ****************************************************************************/ + +void up_block_task(struct tcb_s *tcb, tstate_t task_state) +{ + struct tcb_s *rtcb = this_task(); + bool switch_needed; + + /* Verify that the context switch can be performed */ + + ASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && + (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + + /* Remove the tcb task from the ready-to-run list. If we + * are blocking the task at the head of the task list (the + * most likely case), then a context switch to the next + * ready-to-run task is needed. In this case, it should + * also be true that rtcb == tcb. + */ + + switch_needed = sched_removereadytorun(tcb); + + /* Add the task to the specified blocked task list */ + + sched_addblocked(tcb, (tstate_t)task_state); + + /* If there are any pending tasks, then add them to the ready-to-run + * task list now + */ + + if (g_pendingtasks.head) + { + switch_needed |= sched_mergepending(); + } + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + /* Update scheduler parameters */ + + sched_suspend_scheduler(rtcb); + + /* Are we in an interrupt handler? */ + + if (g_current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + + /* Reset scheduler parameters */ + + sched_resume_scheduler(rtcb); + + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ + + up_restorestate(rtcb->xcp.regs); + } + + /* No, then we will need to perform the user context switch */ + + else + { + /* Get the context of the task at the head of the ready to + * run list. + */ + + struct tcb_s *nexttcb = this_task(); + +#ifdef CONFIG_ARCH_ADDRENV + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ + + (void)group_addrenv(nexttcb); +#endif + /* Reset scheduler parameters */ + + sched_resume_scheduler(nexttcb); + + /* Then switch contexts */ + + up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); + + /* up_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ + } + } +} diff --git a/arch/misoc/src/lm32/lm32_copystate.c b/arch/misoc/src/lm32/lm32_copystate.c new file mode 100644 index 00000000000..b3afa387b85 --- /dev/null +++ b/arch/misoc/src/lm32/lm32_copystate.c @@ -0,0 +1,87 @@ +/**************************************************************************** + * arch/misoc/src/lm32/lm32_copystate.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Ramtin Amin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "lm32.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lm32_copystate + ****************************************************************************/ + +/* A little faster than most memcpy's */ + +void lm32_copystate(uint32_t *dest, uint32_t *src) +{ + int i; + + /* In the LM32 model, the state is copied from the stack to the TCB, + * but only a reference is passed to get the state from the TCB. So the + * following check avoids copying the TCB save area onto itself: + */ + + if (src != dest) + { + for (i = 0; i < XCPTCONTEXT_REGS; i++) + { + *dest++ = *src++; + } + } +} + diff --git a/arch/misoc/src/lm32/lm32_createstack.c b/arch/misoc/src/lm32/lm32_createstack.c new file mode 100644 index 00000000000..31c7f242261 --- /dev/null +++ b/arch/misoc/src/lm32/lm32_createstack.c @@ -0,0 +1,214 @@ +/**************************************************************************** + * arch/misoc/src/lm32/lm32_createstack.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Ramtin Amin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "lm32.h" + +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ + +/* LM32 requires at least a 4-byte stack alignment. For floating point use, + * however, the stack must be aligned to 8-byte addresses. + */ + +#ifdef CONFIG_LIBC_FLOATINGPOINT +# define STACK_ALIGNMENT 8 +#else +# define STACK_ALIGNMENT 4 +#endif + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_create_stack + * + * Description: + * Allocate a stack for a new thread and setup up stack-related information + * in the TCB. + * + * The following TCB fields must be initialized by this function: + * + * - adj_stack_size: Stack size after adjustment for hardware, processor, + * etc. This value is retained only for debug purposes. + * - stack_alloc_ptr: Pointer to allocated stack + * - adj_stack_ptr: Adjusted stack_alloc_ptr for HW. The initial value of + * the stack pointer. + * + * Inputs: + * - tcb: The TCB of new task + * - stack_size: The requested stack size. At least this much + * must be allocated. + * - ttype: The thread type. This may be one of following (defined in + * include/nuttx/sched.h): + * + * TCB_FLAG_TTYPE_TASK Normal user task + * TCB_FLAG_TTYPE_PTHREAD User pthread + * TCB_FLAG_TTYPE_KERNEL Kernel thread + * + * This thread type is normally available in the flags field of the TCB, + * however, there are certain contexts where the TCB may not be fully + * initialized when up_create_stack is called. + * + * If CONFIG_BUILD_KERNEL is defined, then this thread type may affect + * how the stack is allocated. For example, kernel thread stacks should + * be allocated from protected kernel memory. Stacks for user tasks and + * threads must come from memory that is accessible to user code. + * + ****************************************************************************/ + +int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) +{ + /* Is there already a stack allocated of a different size? Because of + * alignment issues, stack_size might erroneously appear to be of a + * different size. Fortunately, this is not a critical operation. + */ + + if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) + { + /* Yes.. Release the old stack */ + + up_release_stack(tcb, ttype); + } + + /* Do we need to allocate a new stack? */ + + if (!tcb->stack_alloc_ptr) + { + /* Allocate the stack. If DEBUG is enabled (but not stack debug), + * then create a zeroed stack to make stack dumps easier to trace. + */ + +#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { + tcb->stack_alloc_ptr = (uint32_t *)kmm_malloc(stack_size); + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + + tcb->stack_alloc_ptr = (uint32_t *)kumm_malloc(stack_size); + } + +#ifdef CONFIG_DEBUG_FEATURES + /* Was the allocation successful? */ + + if (!tcb->stack_alloc_ptr) + { + serr("ERROR: Failed to allocate stack, size %d\n", stack_size); + } +#endif + } + + /* Did we successfully allocate a stack? */ + + if (tcb->stack_alloc_ptr) + { + size_t top_of_stack; + size_t size_of_stack; + + /* Yes.. If stack debug is enabled, then fill the stack with a + * recognizable value that we can use later to test for high + * water marks. + */ + +#ifdef CONFIG_STACK_COLORATION + memset(tcb->stack_alloc_ptr, 0xaa, stack_size); +#endif + + /* LM32 uses a push-down stack: the stack grows toward lower + * addresses in memory. The stack pointer register points to the + * lowest, valid working address (the "top" of the stack). Items on + * the stack are referenced as positive word offsets from sp. + */ + + top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4; + + /* The LM32 stack must be aligned at word (4 byte) boundaries; for + * floating point use, the stack must be aligned to 8-byte addresses. + * If necessary top_of_stack must be rounded down to the next + * boundary to meet these alignment requirements. + */ + + top_of_stack = STACK_ALIGN_DOWN(top_of_stack); + size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4; + + /* Save the adjusted stack values in the struct tcb_s */ + + tcb->adj_stack_ptr = (FAR uint32_t *)top_of_stack; + tcb->adj_stack_size = size_of_stack; + + board_autoled_on(LED_STACKCREATED); + return OK; + } + + return ERROR; +} diff --git a/arch/misoc/src/lm32/lm32_doirq.c b/arch/misoc/src/lm32/lm32_doirq.c new file mode 100644 index 00000000000..50b2e745fc5 --- /dev/null +++ b/arch/misoc/src/lm32/lm32_doirq.c @@ -0,0 +1,147 @@ +/**************************************************************************** + * arch/misoc/src/lm32/lm32_doirq.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Ramtin Amin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +#include "group/group.h" +#include "lm32.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +uint32_t *up_doirq(int irq, uint32_t *regs) +{ + board_autoled_on(LED_INIRQ); +#ifdef CONFIG_SUPPRESS_INTERRUPTS + PANIC(); +#else + /* Current regs non-zero indicates that we are processing an interrupt; + * g_current_regs is also used to manage interrupt level context switches. + * + * Nested interrupts are not supported + */ + + DEBUGASSERT(g_current_regs == NULL); + g_current_regs = regs; + + /* Disable further occurrences of this interrupt (until the interrupt sources + * have been clear by the driver). + */ + + up_disable_irq(irq); + + /* Deliver the IRQ */ + + irq_dispatch(irq, regs); + +#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV) + /* Check for a context switch. If a context switch occurred, then + * g_current_regs will have a different value than it did on entry. If an + * interrupt level context switch has occurred, then restore the floating + * point state and the establish the correct address environment before + * returning from the interrupt. + */ + + if (regs != g_current_regs) + { +#ifdef CONFIG_ARCH_FPU + /* Restore floating point registers */ + + up_restorefpu((uint32_t *)g_current_regs); +#endif + +#ifdef CONFIG_ARCH_ADDRENV + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ + + (void)group_addrenv(NULL); +#endif + } +#endif + + /* If a context switch occurred while processing the interrupt then + * g_current_regs may have change value. If we return any value different + * from the input regs, then the lower level will know that a context + * switch occurred during interrupt processing. + */ + + regs = (uint32_t *)g_current_regs; + + /* Set g_current_regs to NULL to indicate that we are no longer in an + * interrupt handler. + */ + + g_current_regs = NULL; + + /* Unmask the last interrupt (global interrupts are still disabled) */ + + up_enable_irq(irq); +#endif + board_autoled_off(LED_INIRQ); + return regs; +} diff --git a/arch/misoc/src/lm32/lm32_dumpstate.c b/arch/misoc/src/lm32/lm32_dumpstate.c new file mode 100644 index 00000000000..e847bec40c3 --- /dev/null +++ b/arch/misoc/src/lm32/lm32_dumpstate.c @@ -0,0 +1,228 @@ +/**************************************************************************** + * arch/misoc/src/lm32/lm32_dumpstate.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Ramtin Amin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "sched/sched.h" +#include "lm32.h" + +#ifdef CONFIG_ARCH_STACKDUMP + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_getsp + ****************************************************************************/ + +static inline uint32_t up_getsp(void) +{ + register uint32_t sp; + + __asm__ __volatile__("addi %0, sp, 0" : "=r" (sp)); + + return sp; +} + +/**************************************************************************** + * Name: up_stackdump + ****************************************************************************/ + +static void up_stackdump(uint32_t sp, uint32_t stack_base) +{ +# if 0 + uint32_t stack ; + + for (stack = sp & ~0x1f; stack < stack_base; stack += 32) + { + uint32_t *ptr = (uint32_t *)stack; + _alert("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n", + stack, ptr[0], ptr[1], ptr[2], ptr[3], + ptr[4], ptr[5], ptr[6], ptr[7]); + } +#endif +} + +/**************************************************************************** + * Name: up_registerdump + ****************************************************************************/ + +static inline void up_registerdump(void) +{ +#if 0 + /* Are user registers available from interrupt processing? */ + + if (g_current_regs) + { + _alert("EPC:%08x \n", + g_current_regs[REG_EPC]); + _alert("A0:%08x A1:%08x A2:%08x A3:%08x A4:%08x A5:%08x A6:%08x A7:%08x\n", + g_current_regs[REG_A0], g_current_regs[REG_A1], g_current_regs[REG_A2], + g_current_regs[REG_A3], g_current_regs[REG_A4], g_current_regs[REG_A5], + g_current_regs[REG_A6], g_current_regs[REG_A7]); + _alert("T0:%08x T1:%08x T2:%08x T3:%08x T4:%08x T5:%08x T6:%08x\n", + g_current_regs[REG_T0], g_current_regs[REG_T1], g_current_regs[REG_T2], + g_current_regs[REG_T3], g_current_regs[REG_T4], g_current_regs[REG_T5], + g_current_regs[REG_T6]); + _alert("S0:%08x S1:%08x S2:%08x S3:%08x S4:%08x S5:%08x S6:%08x S7:%08x\n", + g_current_regs[REG_S0], g_current_regs[REG_S1], g_current_regs[REG_S2], + g_current_regs[REG_S3], g_current_regs[REG_S4], g_current_regs[REG_S5], + g_current_regs[REG_S6], g_current_regs[REG_S7]); + _alert("S8:%08x S9:%08x S10:%08x S11:%08x\n", + g_current_regs[REG_S8], g_current_regs[REG_S9], g_current_regs[REG_S10], + g_current_regs[REG_S11]); +#ifdef RISCV_SAVE_GP + _alert("GP:%08x SP:%08x FP:%08x TP:%08x RA:%08x\n", + g_current_regs[REG_GP], g_current_regs[REG_SP], g_current_regs[REG_FP], + g_current_regs[REG_TP], g_current_regs[REG_RA]); +#else + _alert("SP:%08x FP:%08x TP:%08x RA:%08x\n", + g_current_regs[REG_SP], g_current_regs[REG_FP], g_current_regs[REG_TP], + g_current_regs[REG_RA]); +#endif + } +#endif +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lm32_dumpstate + ****************************************************************************/ + +void lm32_dumpstate(void) +{ + struct tcb_s *rtcb = this_task(); + uint32_t sp = up_getsp(); + uint32_t ustackbase; + uint32_t ustacksize; +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + uint32_t istackbase; + uint32_t istacksize; +#endif + + /* Get the limits on the user stack memory */ + + if (rtcb->pid == 0) + { + ustackbase = g_idle_topstack - 4; + ustacksize = CONFIG_IDLETHREAD_STACKSIZE; + } + else + { + ustackbase = (uint32_t)rtcb->adj_stack_ptr; + ustacksize = (uint32_t)rtcb->adj_stack_size; + } + + /* Get the limits on the interrupt stack memory */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + istackbase = (uint32_t)&g_intstackbase; + istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4; + + /* Show interrupt stack info */ + + _alert("sp: %08x\n", sp); + _alert("IRQ stack:\n"); + _alert(" base: %08x\n", istackbase); + _alert(" size: %08x\n", istacksize); + + /* Does the current stack pointer lie within the interrupt + * stack? + */ + + if (sp <= istackbase && sp > istackbase - istacksize) + { + /* Yes.. dump the interrupt stack */ + + up_stackdump(sp, istackbase); + + /* Extract the user stack pointer which should lie + * at the base of the interrupt stack. + */ + + sp = g_intstackbase; + _alert("sp: %08x\n", sp); + } + + /* Show user stack info */ + + _alert("User stack:\n"); + _alert(" base: %08x\n", ustackbase); + _alert(" size: %08x\n", ustacksize); +#else + _alert("sp: %08x\n", sp); + _alert("stack base: %08x\n", ustackbase); + _alert("stack size: %08x\n", ustacksize); +#endif + + /* Dump the user stack if the stack pointer lies within the allocated user + * stack memory. + */ + + if (sp > ustackbase || sp <= ustackbase - ustacksize) + { +#if !defined(CONFIG_ARCH_INTERRUPTSTACK) || CONFIG_ARCH_INTERRUPTSTACK < 4 + _alert("ERROR: Stack pointer is not within allocated stack\n"); +#endif + } + else + { + up_stackdump(sp, ustackbase); + } + + /* Then dump the registers (if available) */ + + up_registerdump(); +} + +#endif /* CONFIG_ARCH_STACKDUMP */ diff --git a/arch/misoc/src/lm32/lm32_exit.c b/arch/misoc/src/lm32/lm32_exit.c new file mode 100644 index 00000000000..688f0854263 --- /dev/null +++ b/arch/misoc/src/lm32/lm32_exit.c @@ -0,0 +1,82 @@ +/**************************************************************************** + * arch/misoc/src/lm32/lm32_exit.c + * + * Copyright (C) 2010, 2013-2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Ramtin Amin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#ifdef CONFIG_DUMP_ON_EXIT +# include +#endif + +#include "task/task.h" +#include "sched/sched.h" +#include "group/group.h" +#include "lm32.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _exit + * + * Description: + * This function causes the currently executing task to cease + * to exist. This is a special case of task_delete() where the task to + * be deleted is the currently executing task. It is more complex because + * a context switch must be perform to the next ready to run task. + * + ****************************************************************************/ + +void _exit(int status) +{ +#warning Missing logic +} diff --git a/arch/misoc/src/lm32/lm32_idle.c b/arch/misoc/src/lm32/lm32_idle.c new file mode 100644 index 00000000000..5b85bcc0c03 --- /dev/null +++ b/arch/misoc/src/lm32/lm32_idle.c @@ -0,0 +1,96 @@ +/**************************************************************************** + * arch/misoc/src/lm32/lm32_idle.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Ramtin Amin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "lm32.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_idle + * + * Description: + * up_idle() is the logic that will be executed when their is no other + * ready-to-run task. This is processor idle time and will continue until + * some interrupt occurs to cause a context switch from the idle task. + * + * Processing in this state may be processor-specific. e.g., this is where + * power management operations might be performed. + * + ****************************************************************************/ + +void up_idle(void) +{ +#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_TIMER_INTS) + /* If the system is idle and there are no timer interrupts, then process + * "fake" timer interrupts. Hopefully, something will wake up. + */ + + sched_process_timer(); +#else + + /* This would be an appropriate place to put some MCU-specific logic to + * sleep in a reduced power mode until an interrupt occurs to save power + */ + + /* This is a kludge that I still don't understand. The call to kmm_trysemaphore() + * in the os_start.c IDLE loop seems necessary for the good health of the IDLE + * loop. When the work queue is enabled, this logic is removed from the IDLE + * loop and it appears that we are somehow left idling with interrupts non- + * functional. The following should be no-op, it just disables then re-enables + * interrupts. But it fixes the problem and will stay here until I understand + * the problem/fix better. + * + * And no, the contents of the CP0 status register are not incorrect. But for + * some reason the status register needs to be re-written again on this thread + * for it to take effect. This might be a PIC32-only issue? + */ + +#ifdef CONFIG_SCHED_WORKQUEUE + irqstate_t flags = enter_critical_section(); + leave_critical_section(flags); +#endif +#endif +} diff --git a/arch/misoc/src/lm32/lm32_initialize.c b/arch/misoc/src/lm32/lm32_initialize.c new file mode 100644 index 00000000000..4efa2ecbf00 --- /dev/null +++ b/arch/misoc/src/lm32/lm32_initialize.c @@ -0,0 +1,77 @@ +/**************************************************************************** + * arch/misoc/src/lm32/lm32_initialize.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Ramtin Amin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "lm32.h" + +/**************************************************************************** + * Public Functionis + ****************************************************************************/ + +void up_initialize(void) +{ + /* Initialize the System Timer */ + + lm32_irq_initialize(); + + /* Initialize the serial driver */ + +#warning REVISIT: Here you should all lm32_serial_initialize(). That initializes the entire serial driver, a part of the operation is the uart initialization. + + uart_init(); +} diff --git a/arch/misoc/src/lm32/lm32_initialstate.c b/arch/misoc/src/lm32/lm32_initialstate.c new file mode 100644 index 00000000000..e42107e1450 --- /dev/null +++ b/arch/misoc/src/lm32/lm32_initialstate.c @@ -0,0 +1,120 @@ +/**************************************************************************** + * arch/misoc/src/lm32/up_initialstate.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Ramtin Amin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "lm32.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_initial_state + * + * Description: + * A new thread is being started and a new TCB + * has been created. This function is called to initialize + * the processor specific portions of the new TCB. + * + * This function must setup the intial architecture registers + * and/or stack so that execution will begin at tcb->start + * on the next context switch. + * + ****************************************************************************/ + +void up_initial_state(struct tcb_s *tcb) +{ + struct xcptcontext *xcp = &tcb->xcp; + + /* Initialize the initial exception register context structure */ + + memset(xcp, 0, sizeof(struct xcptcontext)); + + /* Save the initial stack pointer. Hmmm.. the stack is set to the very + * beginning of the stack region. Some functions may want to store data on + * the caller's stack and it might be good to reserve some space. However, + * only the start function would do that and we have control over that one + */ + + xcp->regs[REG_SP] = (uint32_t)tcb->adj_stack_ptr; + + /* Save the task entry point */ + + xcp->regs[REG_EPC] = (uint32_t)tcb->start; + + /* If this task is running PIC, then set the PIC base register to the + * address of the allocated D-Space region. + */ + +#ifdef CONFIG_PIC +# warning "Missing logic" +#endif + + /* Set privileged- or unprivileged-mode, depending on how NuttX is + * configured and what kind of thread is being started. + * + * If the kernel build is not selected, then all threads run in + * privileged thread mode. + */ + +#ifdef CONFIG_BUILD_KERNEL +# warning "Missing logic" +#endif +} diff --git a/arch/misoc/src/lm32/lm32_interruptcontext.c b/arch/misoc/src/lm32/lm32_interruptcontext.c new file mode 100644 index 00000000000..8edd5538532 --- /dev/null +++ b/arch/misoc/src/lm32/lm32_interruptcontext.c @@ -0,0 +1,62 @@ +/**************************************************************************** + * arch/misoc/src/lm32/up_interruptcontext.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Ramtin Amin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "lm32.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_interrupt_context + * + * Description: Return true is we are currently executing in + * the interrupt handler context. + ****************************************************************************/ + +bool up_interrupt_context(void) +{ + return g_current_regs != NULL; +} diff --git a/arch/misoc/src/lm32/lm32_irq.c b/arch/misoc/src/lm32/lm32_irq.c new file mode 100644 index 00000000000..b99bb443b43 --- /dev/null +++ b/arch/misoc/src/lm32/lm32_irq.c @@ -0,0 +1,121 @@ +/**************************************************************************** + * arch/misoc/src/lm32/_irq.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Ramtin Amin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include +#include +#include + +#include "misoc_irqasm.h" +#include "lm32.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +volatile uint32_t *g_current_regs; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lm32_irq_initialize + ****************************************************************************/ + +void lm32_irq_initialize(void) +{ + /* currents_regs is non-NULL only while processing an interrupt */ + + g_current_regs = NULL; + + /* Enable interrupt */ + + irq_setie(1); +} + +irqstate_t up_irq_save(void) +{ + irqstate_t flags; + irq_setie(0); + +#warning Return value MUST be the previous IE value. Returning 1 will not work. + return 1; +} + +void up_irq_restore(irqstate_t flags) +{ + irq_setie(1); +} + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Disable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_disable_irq(int irq) +{ + irqstate_t flags; + flags = irq_getmask(); + flags &= ~(1 < + * Ramtin Amin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "sched/sched.h" +#include "group/group.h" +#include "lm32.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_release_pending + * + * Description: + * Release and ready-to-run tasks that have + * collected in the pending task list. This can call a + * context switch if a new task is placed at the head of + * the ready to run list. + * + ****************************************************************************/ + +void up_release_pending(void) +{ + struct tcb_s *rtcb = this_task(); + + sinfo("From TCB=%p\n", rtcb); + + /* Merge the g_pendingtasks list into the ready-to-run task list */ + + /* sched_lock(); */ + if (sched_mergepending()) + { + /* The currently active task has changed! We will need to switch + * contexts. + * + * Update scheduler parameters. + */ + + sched_suspend_scheduler(rtcb); + + /* Are we operating in interrupt context? */ + + if (g_current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + + /* Update scheduler parameters */ + + sched_resume_scheduler(rtcb); + + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ + + up_restorestate(rtcb->xcp.regs); + } + + /* No, then we will need to perform the user context switch */ + + else + { + /* Switch context to the context of the task at the head of the + * ready to run list. + */ + + struct tcb_s *nexttcb = this_task(); + +#ifdef CONFIG_ARCH_ADDRENV + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ + + (void)group_addrenv(nexttcb); +#endif + /* Update scheduler parameters */ + + sched_resume_scheduler(nexttcb); + + /* Then switch contexts */ + + up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); + + /* up_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ + } + } +} diff --git a/arch/misoc/src/lm32/lm32_releasestack.c b/arch/misoc/src/lm32/lm32_releasestack.c new file mode 100644 index 00000000000..fa88500bf9d --- /dev/null +++ b/arch/misoc/src/lm32/lm32_releasestack.c @@ -0,0 +1,115 @@ +/**************************************************************************** + * arch/misoc/src/lm32/up_releasestack.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Ramtin Amin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include "lm32.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_release_stack + * + * Description: + * A task has been stopped. Free all stack related resources retained in + * the defunct TCB. + * + * Input Parmeters + * - dtcb: The TCB containing information about the stack to be released + * - ttype: The thread type. This may be one of following (defined in + * include/nuttx/sched.h): + * + * TCB_FLAG_TTYPE_TASK Normal user task + * TCB_FLAG_TTYPE_PTHREAD User pthread + * TCB_FLAG_TTYPE_KERNEL Kernel thread + * + * This thread type is normally available in the flags field of the TCB, + * however, there are certain error recovery contexts where the TCB may + * not be fully initialized when up_release_stack is called. + * + * If CONFIG_BUILD_KERNEL is defined, then this thread type may affect + * how the stack is freed. For example, kernel thread stacks may have + * been allocated from protected kernel memory. Stacks for user tasks + * and threads must have come from memory that is accessible to user + * code. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) +{ + /* Is there a stack allocated? */ + + if (dtcb->stack_alloc_ptr) + { +#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { + sched_kfree(dtcb->stack_alloc_ptr); + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + + sched_ufree(dtcb->stack_alloc_ptr); + } + + /* Mark the stack freed */ + + dtcb->stack_alloc_ptr = NULL; + } + + /* The size of the allocated stack is now zero */ + + dtcb->adj_stack_size = 0; +} diff --git a/arch/misoc/src/lm32/lm32_stackframe.c b/arch/misoc/src/lm32/lm32_stackframe.c new file mode 100644 index 00000000000..981c655f81f --- /dev/null +++ b/arch/misoc/src/lm32/lm32_stackframe.c @@ -0,0 +1,136 @@ +/**************************************************************************** + * arch/misoc/src/lm32/lm32_stackframe.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Ramtin Amin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "lm32.h" + +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ + +/* LM32 requires at least a 4-byte stack alignment. For floating point use, + * however, the stack must be aligned to 8-byte addresses. + */ + +#ifdef CONFIG_LIBC_FLOATINGPOINT +# define STACK_ALIGNMENT 8 +#else +# define STACK_ALIGNMENT 4 +#endif + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_stack_frame + * + * Description: + * Allocate a stack frame in the TCB's stack to hold thread-specific data. + * This function may be called anytime after up_create_stack() or + * up_use_stack() have been called but before the task has been started. + * + * Thread data may be kept in the stack (instead of in the TCB) if it is + * accessed by the user code directly. This includes such things as + * argv[]. The stack memory is guaranteed to be in the same protection + * domain as the thread. + * + * The following TCB fields will be re-initialized: + * + * - adj_stack_size: Stack size after removal of the stack frame from + * the stack + * - adj_stack_ptr: Adjusted initial stack pointer after the frame has + * been removed from the stack. This will still be the initial value + * of the stack pointer when the task is started. + * + * Inputs: + * - tcb: The TCB of new task + * - frame_size: The size of the stack frame to allocate. + * + * Returned Value: + * - A pointer to bottom of the allocated stack frame. NULL will be + * returned on any failures. The alignment of the returned value is + * the same as the alignment of the stack itself. + * + ****************************************************************************/ + +FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size) +{ + uintptr_t topaddr; + + /* Align the frame_size */ + + frame_size = STACK_ALIGN_UP(frame_size); + + /* Is there already a stack allocated? Is it big enough? */ + + if (!tcb->stack_alloc_ptr || tcb->adj_stack_size <= frame_size) + { + return NULL; + } + + /* Save the adjusted stack values in the struct tcb_s */ + + topaddr = (uintptr_t)tcb->adj_stack_ptr - frame_size; + tcb->adj_stack_ptr = (FAR void *)topaddr; + tcb->adj_stack_size -= frame_size; + + /* Reset the initial stack pointer */ + + tcb->xcp.regs[REG_SP] = (uint32_t)tcb->adj_stack_ptr; + + /* And return the pointer to the allocated region */ + + return (FAR void *)(topaddr + sizeof(uint32_t)); +} diff --git a/arch/misoc/src/lm32/lm32_swint.c b/arch/misoc/src/lm32/lm32_swint.c new file mode 100644 index 00000000000..c8148812cc5 --- /dev/null +++ b/arch/misoc/src/lm32/lm32_swint.c @@ -0,0 +1,330 @@ +/**************************************************************************** + * arch/misoc/src/lm32/lm32_swint.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Ramtin Amin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "lm32.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_registerdump + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_SYSCALL_INFO +static void up_registerdump(const uint32_t *regs) +{ +#if 0 + svcinfo("EPC:%08x\n", + regs[REG_EPC]); + svcinfo("A0:%08x A1:%08x A2:%08x A3:%08x A4:%08x A5:%08x A6:%08x A7:%08x\n", + regs[REG_A0], regs[REG_A1], regs[REG_A2], regs[REG_A3], + regs[REG_A4], regs[REG_A5], regs[REG_A6], regs[REG_A7]); + svcinfo("T0:%08x T1:%08x T2:%08x T3:%08x T4:%08x T5:%08x T6:%08x\n", + regs[REG_T0], regs[REG_T1], regs[REG_T2], regs[REG_T3], + regs[REG_T4], regs[REG_T5], regs[REG_T6]); + svcinfo("S0:%08x S1:%08x S2:%08x S3:%08x S4:%08x S5:%08x S6:%08x S7:%08x\n", + regs[REG_S0], regs[REG_S1], regs[REG_S2], regs[REG_S3], + regs[REG_S4], regs[REG_S5], regs[REG_S6], regs[REG_S7]); + svcinfo("S8:%08x S9:%08x S10:%08x S11:%08x\n", + regs[REG_S8], regs[REG_S9], regs[REG_S10], regs[REG_S11]); +#ifdef LM3232_SAVE_GP + svcinfo("GP:%08x SP:%08x FP:%08x TP:%08x RA:%08x\n", + regs[REG_GP], regs[REG_SP], regs[REG_FP], regs[REG_TP], regs[REG_RA]); +#else + svcinfo("SP:%08x FP:%08x TP:%08x RA:%08x\n", + regs[REG_SP], regs[REG_FP], regs[REG_TP], regs[REG_RA]); +#endif +#endif +} +#else +# define up_registerdump(regs) +#endif + +/**************************************************************************** + * Name: dispatch_syscall + * + * Description: + * Call the stub function corresponding to the system call. + * + ****************************************************************************/ + +#ifdef CONFIG_BUILD_KERNEL +static void dispatch_syscall(void) naked_function; +static void dispatch_syscall(void) +{ +# error "Missing logic" + +/* Refer to arch/arm/src/armv7-m/up_svcall.h for how this is done for ARM */ +/* __asm__ __volatile__ */ +/* ( */ +/* Save registers */ +/* Get the base of the stub lookup table */ +/* Get the offset of the stub for this syscall */ +/* Load the entry of the stub for this syscall */ +/* Call the stub */ +/* Restore regsisters */ +/* Return from the syscall */ +/* ); */ +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lm32_swint + * + * Description: + * This is software interrupt exception handler that performs context + * switching and manages system calls + * + ****************************************************************************/ + +uint32_t lm32_swint(int irq, FAR void *context) +{ + uint32_t *regs = (uint32_t *)context; + + DEBUGASSERT(g_current_regs == NULL); + g_current_regs = regs; + + /* Software interrupt 0 is invoked with REG_A0 (REG_X10) = system call + * command and REG_A1-6 = variable number of + * arguments depending on the system call. + */ + +#ifdef CONFIG_DEBUG_SYSCALL_INFO + svcinfo("Entry: regs: %p cmd: %d\n", regs, regs[REG_A0]); + up_registerdump(regs); +#endif + + /* Handle the SWInt according to the command in $a0 */ + + switch (regs[REG_A0]) + { + /* A0=SYS_restore_context: This a restore context command: + * + * void up_fullcontextrestore(uint32_t *restoreregs) noreturn_function; + * + * At this point, the following values are saved in context: + * + * A0 = SYS_restore_context + * A1 = restoreregs + * + * In this case, we simply need to set g_current_regs to restore register + * area referenced in the saved R1. context == g_current_regs is the normal + * exception return. By setting g_current_regs = context[R1], we force + * the return to the saved context referenced in $a1. + */ + + case SYS_restore_context: + { + DEBUGASSERT(regs[REG_A1] != 0); + g_current_regs = (uint32_t *)regs[REG_A1]; + } + break; + + /* A0=SYS_switch_context: This a switch context command: + * + * void up_switchcontext(uint32_t *saveregs, uint32_t *restoreregs); + * + * At this point, the following values are saved in context: + * + * A0 = SYS_switch_context + * A1 = saveregs + * A2 = restoreregs + * + * In this case, we save the context registers to the save register + * area reference by the saved contents of R5 and then set + * g_current_regs to to the save register area referenced by the saved + * contents of R6. + */ + + case SYS_switch_context: + { + DEBUGASSERT(regs[REG_A1] != 0 && regs[REG_A2] != 0); + lm32_copystate((uint32_t *)regs[REG_A1], regs); + g_current_regs = (uint32_t *)regs[REG_A2]; + } + break; + + /* A0=SYS_syscall_return: This a switch context command: + * + * void up_sycall_return(void); + * + * At this point, the following values are saved in context: + * + * A0 = SYS_syscall_return + * + * We need to restore the saved return address and return in + * unprivileged thread mode. + */ + +#ifdef CONFIG_BUILD_KERNEL + case SYS_syscall_return: + { + struct tcb_s *rtcb = sched_self(); + int index = (int)rtcb->xcp.nsyscalls - 1; + + /* Make sure that there is a saved syscall return address. */ + + DEBUGASSERT(index >= 0); + + /* Setup to return to the saved syscall return address in + * the original mode. + */ + + g_current_regs[REG_EPC] = rtcb->xcp.syscall[index].sysreturn; +#error "Missing logic -- need to restore the original mode" + rtcb->xcp.nsyscalls = index; + } + break; +#endif + + /* This is not an architecture-specify system call. If NuttX is built + * as a standalone kernel with a system call interface, then all of the + * additional system calls must be handled as in the default case. + */ + + default: + { +#ifdef CONFIG_BUILD_KERNEL + FAR struct tcb_s *rtcb = sched_self(); + int index = rtcb->xcp.nsyscalls; + + /* Verify that the SYS call number is within range */ + + DEBUGASSERT(g_current_regs[REG_A0] < SYS_maxsyscall); + + /* Make sure that we got here that there is a no saved syscall + * return address. We cannot yet handle nested system calls. + */ + + DEBUGASSERT(index < CONFIG_SYS_NNEST); + + /* Setup to return to dispatch_syscall in privileged mode. */ + + rtcb->xcpsyscall[index].sysreturn = regs[REG_EPC]; +#error "Missing logic -- Need to save mode" + rtcb->xcp.nsyscalls = index + 1; + + regs[REG_EPC] = (uint32_t)dispatch_syscall; +#error "Missing logic -- Need to set privileged mode" + + /* Offset R0 to account for the reserved values */ + + g_current_regs[REG_A0] -= CONFIG_SYS_RESERVED; +#else + svcerr("ERROR: Bad SYS call: %d\n", regs[REG_A0]); +#endif + } + break; + } + + /* Report what happened. That might difficult in the case of a context switch */ + +#ifdef CONFIG_DEBUG_SYSCALL_INFO + if (regs != g_current_regs) + { + svcinfo("SWInt Return: Context switch!\n"); + up_registerdump((const uint32_t *)g_current_regs); + } + else + { + svcinfo("SWInt Return: %d\n", regs[REG_A0]); + } +#endif + + +#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV) + /* Check for a context switch. If a context switch occurred, then + * g_current_regs will have a different value than it did on entry. If an + * interrupt level context switch has occurred, then restore the floating + * point state and the establish the correct address environment before + * returning from the interrupt. + */ + + if (regs != g_current_regs) + { +#ifdef CONFIG_ARCH_FPU + /* Restore floating point registers */ + + up_restorefpu((uint32_t *)g_current_regs); +#endif + +#ifdef CONFIG_ARCH_ADDRENV + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ + + (void)group_addrenv(NULL); +#endif + } +#endif + + /* If a context switch occurred while processing the interrupt then + * g_current_regs may have change value. If we return any value different + * from the input regs, then the lower level will know that a context + * switch occurred during interrupt processing. + */ + + regs = (uint32_t *)g_current_regs; + + /* Set g_current_regs to NULL to indicate that we are no longer in an + * interrupt handler. + */ + + g_current_regs = NULL; + return regs; +} diff --git a/arch/misoc/src/lm32/lm32_syscall.S b/arch/misoc/src/lm32/lm32_syscall.S new file mode 100644 index 00000000000..61b0b6ca7cf --- /dev/null +++ b/arch/misoc/src/lm32/lm32_syscall.S @@ -0,0 +1,103 @@ +/**************************************************************************** + * arch/misoc/src/lm32/lm32_syscall.S + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Ramtin Amin + * + * Derives from RISC-V version: + * + * Copyright (C) 2016 Ken Pettit. All rights reserved. + * Author: Ken Pettit + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + .file "up_syscall.S" + .global sys_call0 + .global sys_call1 + .global sys_call2 + .global sys_call3 + .global sys_call4 + .global sys_call5 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_syscall0, up_syscall1, up_syscall2, up_syscall3 + * + * Description: + * up_syscall0 - System call SYS_ argument and no additional parameters. + * up_syscall1 - System call SYS_ argument and one additional parameter. + * up_syscall2 - System call SYS_ argument and two additional parameters. + * up_syscall3 - System call SYS_ argument and three additional parameters. + * up_syscall4 - System call SYS_ argument and four additional parameters. + * up_syscall5 - System call SYS_ argument and five additional parameters. + * + * Assumption: + * All interrupts are disabled except for the software interrupts. + * + ****************************************************************************/ + + .text + +sys_call0: /* a0 holds the syscall number */ +sys_call1: /* a0 holds the syscall number, argument in a1 */ +sys_call2: /* a0 holds the syscall number, arguments in a1 and a2 */ +sys_call3: /* a0 holds the syscall number, arguments in a1, a2, and a3 */ +sys_call4: /* a0 holds the syscall number, arguments in a1, a2, a3 and a4 */ +sys_call5: /* a0 holds the syscall number, arguments in a1, a2, a3, a4 and a5 */ + + /* Issue the ECALL opcode to perform a SW interrupt to the OS */ + + scall + + /* The actual interrupt may not a occur for a few more cycles. Let's + * put a few nop's here in hope that the SW interrupt occurs during + * the sequence of nops. + */ + + nop + nop + + /* Then return with the result of the software interrupt in v0 */ + + ret + nop diff --git a/arch/misoc/src/lm32/lm32_unblocktask.c b/arch/misoc/src/lm32/lm32_unblocktask.c new file mode 100644 index 00000000000..74b1d92472c --- /dev/null +++ b/arch/misoc/src/lm32/lm32_unblocktask.c @@ -0,0 +1,164 @@ +/**************************************************************************** + * arch/misoc/src/lm32/lm32_unblocktask.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Ramtin Amin + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "sched/sched.h" +#include "group/group.h" +#include "clock/clock.h" +#include "lm32.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_unblock_task + * + * Description: + * A task is currently in an inactive task list + * but has been prepped to execute. Move the TCB to the + * ready-to-run list, restore its context, and start execution. + * + * Inputs: + * tcb: Refers to the tcb to be unblocked. This tcb is + * in one of the waiting tasks lists. It must be moved to + * the ready-to-run list and, if it is the highest priority + * ready to run task, executed. + * + ****************************************************************************/ + +void up_unblock_task(struct tcb_s *tcb) +{ + struct tcb_s *rtcb = this_task(); + + /* Verify that the context switch can be performed */ + + ASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && + (tcb->task_state <= LAST_BLOCKED_STATE)); + + /* Remove the task from the blocked task list */ + + sched_removeblocked(tcb); + + /* Add the task in the correct location in the prioritized + * ready-to-run task list + */ + + if (sched_addreadytorun(tcb)) + { + /* The currently active task has changed! We need to do + * a context switch to the new task. + */ + + /* Update scheduler parameters */ + + sched_suspend_scheduler(rtcb); + + /* Are we in an interrupt handler? */ + + if (g_current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + + /* Update scheduler parameters */ + + sched_resume_scheduler(rtcb); + + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ + + up_restorestate(rtcb->xcp.regs); + } + + /* No, then we will need to perform the user context switch */ + + else + { + /* Restore the exception context of the new task that is ready to + * run (probably tcb). This is the new rtcb at the head of the + * ready-to-run task list. + */ + + struct tcb_s *nexttcb = this_task(); + +#ifdef CONFIG_ARCH_ADDRENV + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ + + (void)group_addrenv(nexttcb); +#endif + /* Update scheduler parameters */ + + sched_resume_scheduler(nexttcb); + + /* Then switch contexts */ + + up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); + + /* up_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ + } + } +} diff --git a/arch/misoc/src/lm32/lm32_vectors.S b/arch/misoc/src/lm32/lm32_vectors.S new file mode 100644 index 00000000000..a5ca7a550de --- /dev/null +++ b/arch/misoc/src/lm32/lm32_vectors.S @@ -0,0 +1,251 @@ +/**************************************************************************** + * arch/misoc/src/lm32/lm32_allocateheap.c + * LM32 C startup code. + * + * Adapted for NuttX: + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Ramtin Amin + * + * Derives from LatticeMico32 C startup code. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Exception handlers - Must be 32 bytes long. + ****************************************************************************/ + + .section .text, "ax", @progbits + .global __start + +__start: +_reset_handler: + xor r0, r0, r0 + wcsr IE, r0 + mvhi r1, hi(_reset_handler) + ori r1, r1, lo(_reset_handler) + wcsr EBA, r1 + bi _do_reset + nop + nop + +_breakpoint_handler: + bi _breakpoint_handler + nop + nop + nop + nop + nop + nop + nop + +_instruction_bus_error_handler: + bi _instruction_bus_error_handler + nop + nop + nop + nop + nop + nop + nop + +_watchpoint_hander: + bi _watchpoint_hander + nop + nop + nop + nop + nop + nop + nop + +_data_bus_error_handler: + bi _data_bus_error_handler + nop + nop + nop + nop + nop + nop + nop + +_divide_by_zero_handler: + bi _divide_by_zero_handler + nop + nop + nop + nop + nop + nop + nop + +_interrupt_handler: + sw (sp+0), ra + calli .save_all + rcsr r1, IP + calli up_doirq + bi .restore_all_and_eret + nop + nop + nop + +_syscall_handler: + sw (sp+0), ra + calli .save_all + rcsr r1, IP + calli lm32_swint + bi .restore_all_and_eret + nop + nop + nop + +_do_reset: + /* Setup stack and global pointer */ + + mvhi sp, hi(_fstack) + ori sp, sp, lo(_fstack) + + /* Clear BSS */ + + mvhi r1, hi(_sbss) + ori r1, r1, lo(_sbss) + mvhi r3, hi(_ebss) + ori r3, r3, lo(_ebss) + +.clearBSS: + be r1, r3, .callMain + sw (r1+0), r0 + addi r1, r1, 4 + bi .clearBSS + +.callMain: + bi os_start + +.save_all: + addi sp, sp, -132 + sw (sp+REG_X0), r0 + sw (sp+REG_X1), r1 + sw (sp+REG_X2), r2 + sw (sp+REG_X3), r3 + sw (sp+REG_X4), r4 + sw (sp+REG_X5), r5 + sw (sp+REG_X6), r6 + sw (sp+REG_X7), r7 + sw (sp+REG_X8), r8 + sw (sp+REG_X9), r9 + sw (sp+REG_X10), r10 + sw (sp+REG_X11), r11 + sw (sp+REG_X12), r12 + sw (sp+REG_X13), r13 + sw (sp+REG_X14), r14 + sw (sp+REG_X15), r15 + sw (sp+REG_X16), r16 + sw (sp+REG_X17), r17 + sw (sp+REG_X18), r18 + sw (sp+REG_X19), r19 + sw (sp+REG_X20), r20 + sw (sp+REG_X21), r21 + sw (sp+REG_X22), r22 + sw (sp+REG_X23), r23 + sw (sp+REG_X24), r24 + sw (sp+REG_X25), r25 + + sw (sp+REG_GP), r26 + sw (sp+REG_FP), r27 + sw (sp+REG_SP), r28 + + /* reg RA done later */ + + sw (sp+REG_EA), r30 + sw (sp+REG_BA), r31 + + /* ra needs to be moved from initial stack location */ + + lw r1, (sp+ 132) + sw (sp+REG_RA), r1 + + /* the 2nd argument is the regs pointer */ + + addi r2, sp, 0 + ret + +.restore_all_and_eret: + /* r1 should have the place where we restore ! */ + + lw r2, (r1+REG_X2) + lw r3, (r1+REG_X3) + lw r4, (r1+REG_X4) + lw r5, (r1+REG_X5) + lw r6, (r1+REG_X6) + lw r7, (r1+REG_X7) + lw r8, (r1+REG_X8) + lw r9, (r1+REG_X9) + lw r10, (r1+REG_X10) + lw r11, (r1+REG_X11) + lw r12, (r1+REG_X12) + lw r13, (r1+REG_X13) + lw r14, (r1+REG_X14) + lw r15, (r1+REG_X15) + lw r16, (r1+REG_X16) + lw r17, (r1+REG_X17) + lw r18, (r1+REG_X18) + lw r19, (r1+REG_X19) + lw r20, (r1+REG_X20) + lw r21, (r1+REG_X21) + lw r22, (r1+REG_X22) + lw r23, (r1+REG_X23) + lw r24, (r1+REG_X24) + lw r25, (r1+REG_X25) + lw r26, (r1+REG_GP) + lw r27, (r1+REG_FP) + lw r28, (r1+REG_SP) + lw r29, (r1+REG_RA) + lw r30, (r1+REG_EA) + lw r31, (r1+REG_BA) + lw r1, (r1+REG_X1) + addi sp, sp, 132 + eret + + /* This global variable is unsigned long g_idle_topstack and is + * exported from here only because of its coupling to other + * uses of _ebss in this file + */ + + .data + .align 4 + .globl g_idle_topstack + .type g_idle_topstack, object + +g_idle_topstack: + .long _ebss+CONFIG_IDLETHREAD_STACKSIZE + .size g_idle_topstack, .-g_idle_topstack + .end