diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-06-08 18:10:55 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-06-08 18:10:55 +0000 |
commit | c626aec4434149e17e4cd98174e59095a3a06e05 (patch) | |
tree | 7c1b6cbe99bb7af241fce8d7455181d9c025b73c /nuttx/arch/avr | |
parent | 583f057b1912513fce544714949e29fbe8bdf253 (diff) | |
download | px4-nuttx-c626aec4434149e17e4cd98174e59095a3a06e05.tar.gz px4-nuttx-c626aec4434149e17e4cd98174e59095a3a06e05.tar.bz2 px4-nuttx-c626aec4434149e17e4cd98174e59095a3a06e05.zip |
More AVR context switching logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3683 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/arch/avr')
20 files changed, 1592 insertions, 218 deletions
diff --git a/nuttx/arch/avr/include/avr/irq.h b/nuttx/arch/avr/include/avr/irq.h index b387be671..d3026c185 100644 --- a/nuttx/arch/avr/include/avr/irq.h +++ b/nuttx/arch/avr/include/avr/irq.h @@ -89,9 +89,14 @@ #define REG_R0 33 /* r0 */ #define REG_R24 34 /* r24 */ +/* The program counter is automatically pushed when the interrupt occurs */ + +#define REG_PCH 35 /* PC */ +#define REG_PCL 36 + /* Size of the register state save array (in bytes) */ -#define XCPTCONTEXT_REGS 35 +#define XCPTCONTEXT_REGS 37 /**************************************************************************** * Public Types @@ -111,8 +116,9 @@ struct xcptcontext /* These are saved copies of PC and SR used during signal processing.*/ - uint16_t saved_pc; - uint8_t saved_sr; + uint8_t saved_pcl; + uint8_t saved_pch; + uint8_t saved_sreg; #endif /* Register save area */ diff --git a/nuttx/arch/avr/src/at32uc3/Make.defs b/nuttx/arch/avr/src/at32uc3/Make.defs index 94dc5d2dc..49d35ed4b 100644 --- a/nuttx/arch/avr/src/at32uc3/Make.defs +++ b/nuttx/arch/avr/src/at32uc3/Make.defs @@ -48,6 +48,12 @@ CMN_CSRCS = up_assert.c up_allocateheap.c up_blocktask.c up_copystate.c \ up_schedulesigaction.c up_sigdeliver.c up_unblocktask.c \ up_usestack.c up_doirq.c +# Configuration-dependent common files + +ifeq ($(CONFIG_ARCH_STACKDUMP),y) +CMN_CSRCS += up_dumpstate.c +endif + # Required AT32UC3 files CHIP_ASRCS = diff --git a/nuttx/arch/avr/src/at90usb/Make.defs b/nuttx/arch/avr/src/at90usb/Make.defs index a206f4f6f..dcff056b5 100644 --- a/nuttx/arch/avr/src/at90usb/Make.defs +++ b/nuttx/arch/avr/src/at90usb/Make.defs @@ -40,12 +40,20 @@ HEAD_ASRC = at90usb_head.S # Common AVR files CMN_ASRCS = up_switchcontext.S -CMN_CSRCS = up_allocateheap.c up_copystate.c up_createstack.c up_exit.c \ - up_idle.c up_initialize.c up_interruptcontext.c up_lowputs.c \ - up_mdelay.c up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c \ - up_puts.c up_releasestack.c up_udelay.c up_usestack.c +CMN_CSRCS = up_allocateheap.c up_assert.c up_blocktask.c up_copystate.c \ + up_createstack.c up_doirq.c up_exit.c up_idle.c up_initialize.c \ + up_interruptcontext.c up_lowputs.c up_mdelay.c up_modifyreg8.c \ + up_modifyreg16.c up_modifyreg32.c up_puts.c up_releasepending.c \ + up_releasestack.c up_reprioritizertr.c up_schedulesigaction.c \ + up_sigdeliver.c up_udelay.c up_unblocktask.c up_usestack.c -# Required aT90USB files +# Configuration-dependent common files + +ifeq ($(CONFIG_ARCH_STACKDUMP),y) +CMN_CSRCS += up_dumpstate.c +endif + +# Required AT90USB files CHIP_ASRCS = at90usb_exceptions.S CHIP_CSRCS = diff --git a/nuttx/arch/avr/src/at90usb/at90usb_exceptions.S b/nuttx/arch/avr/src/at90usb/at90usb_exceptions.S index 748fd5efc..862ea06ae 100755 --- a/nuttx/arch/avr/src/at90usb/at90usb_exceptions.S +++ b/nuttx/arch/avr/src/at90usb/at90usb_exceptions.S @@ -64,43 +64,43 @@ .section .handlers, "ax", @progbits
- HANDLER at90usb_int0, ATMEGA_IRQ_INT0, excpt_common /* External interrupt request 0 */
- HANDLER at90usb_int1, ATMEGA_IRQ_INT1, excpt_common /* External interrupt request 1 */
- HANDLER at90usb_int2, ATMEGA_IRQ_INT2, excpt_common /* External interrupt request 2 */
- HANDLER at90usb_int3, ATMEGA_IRQ_INT3, excpt_common /* External interrupt request 3 */
- HANDLER at90usb_int4, ATMEGA_IRQ_INT4, excpt_common /* External interrupt request 4 */
- HANDLER at90usb_int5, ATMEGA_IRQ_INT5, excpt_common /* External interrupt request 5 */
- HANDLER at90usb_int6, ATMEGA_IRQ_INT6, excpt_common /* External interrupt request 6 */
- HANDLER at90usb_int7, ATMEGA_IRQ_INT7, excpt_common /* External interrupt request 7 */
+ HANDLER at90usb_int0, AT90USB_IRQ_INT0, excpt_common /* External interrupt request 0 */
+ HANDLER at90usb_int1, AT90USB_IRQ_INT1, excpt_common /* External interrupt request 1 */
+ HANDLER at90usb_int2, AT90USB_IRQ_INT2, excpt_common /* External interrupt request 2 */
+ HANDLER at90usb_int3, AT90USB_IRQ_INT3, excpt_common /* External interrupt request 3 */
+ HANDLER at90usb_int4, AT90USB_IRQ_INT4, excpt_common /* External interrupt request 4 */
+ HANDLER at90usb_int5, AT90USB_IRQ_INT5, excpt_common /* External interrupt request 5 */
+ HANDLER at90usb_int6, AT90USB_IRQ_INT6, excpt_common /* External interrupt request 6 */
+ HANDLER at90usb_int7, AT90USB_IRQ_INT7, excpt_common /* External interrupt request 7 */
HANDLER at90usb_pcint0, AT90USB_IRQ_PCINT0, excpt_common /* Pin Change Interrupt Request 0 */
HANDLER at90usb_usbgen, AT90USB_IRQ_USBGEN, excpt_common /* USB General USB General Interrupt request */
HANDLER at90usb_usbep, AT90USB_IRQ_USBEP, excpt_common /* USB Endpoint/Pipe USB ENdpoint/Pipe Interrupt request */
HANDLER at90usb_wdt, AT90USB_IRQ_WDT, excpt_common /* Watchdog Time-out Interrupt */
HANDLER at90usb_t2compa, AT90USB_IRQ_T2COMPA, excpt_common /* TIMER2 COMPA Timer/Counter2 Compare Match A */
HANDLER at90usb_t2compb, AT90USB_IRQ_T2COMPB, excpt_common /* TIMER2 COMPA Timer/Counter2 Compare Match B */
- HANDLER at90usb_t2ovf, ATMEGA_IRQ_T2OVF, excpt_common /* TIMER2 OVF timer/counter2 overflow */
- HANDLER at90usb_t1capt, ATMEGA_IRQ_T1CAPT, excpt_common /* TIMER1 CAPT timer/counter1 capture event */
- HANDLER at90usb_t1compa, ATMEGA_IRQ_T1COMPA, excpt_common /* TIMER1 COMPA timer/counter1 compare match A */
- HANDLER at90usb_t1compb, ATMEGA_IRQ_T1COMPB, excpt_common /* TIMER1 COMPB timer/counter1 compare match B */
- HANDLER at90usb_t1compc, ATMEGA_IRQ_T1COMPC, excpt_common /* TIMER1 COMPC timer/counter1 compare match C */
- HANDLER at90usb_t1ovf, ATMEGA_IRQ_T1OVF, excpt_common /* TIMER1 OVF timer/counter1 overflow */
+ HANDLER at90usb_t2ovf, AT90USB_IRQ_T2OVF, excpt_common /* TIMER2 OVF timer/counter2 overflow */
+ HANDLER at90usb_t1capt, AT90USB_IRQ_T1CAPT, excpt_common /* TIMER1 CAPT timer/counter1 capture event */
+ HANDLER at90usb_t1compa, AT90USB_IRQ_T1COMPA, excpt_common /* TIMER1 COMPA timer/counter1 compare match A */
+ HANDLER at90usb_t1compb, AT90USB_IRQ_T1COMPB, excpt_common /* TIMER1 COMPB timer/counter1 compare match B */
+ HANDLER at90usb_t1compc, AT90USB_IRQ_T1COMPC, excpt_common /* TIMER1 COMPC timer/counter1 compare match C */
+ HANDLER at90usb_t1ovf, AT90USB_IRQ_T1OVF, excpt_common /* TIMER1 OVF timer/counter1 overflow */
HANDLER at90usb_t0compa, AT90USB_IRQ_T0COMPA, excpt_common /* TIMER0 COMPA Timer/Counter0 Compare Match A */
HANDLER at90usb_t0compb, AT90USB_IRQ_T0COMPB, excpt_common /* TIMER0 COMPB Timer/Counter0 Compare Match B */
- HANDLER at90usb_t0ovf, ATMEGA_IRQ_T0OVF, excpt_common /* TIMER0 OVF timer/counter0 overflow */
- HANDLER at90usb_spi, ATMEGA_IRQ_SPI, excpt_common /* STC SPI serial transfer complete */
- HANDLER at90usb_u1rx, ATMEGA_IRQ_U1RX, excpt_common /* USART1 RX complete */
- HANDLER at90usb_u1dre, ATMEGA_IRQ_U1DRE, excpt_common /* USART1 data register empty */
- HANDLER at90usb_u1tx, ATMEGA_IRQ_U1TX, excpt_common /* USART1 TX complete */
- HANDLER at90usb_anacomp, ATMEGA_IRQ_ANACOMP, excpt_common /* ANALOG COMP analog comparator */
- HANDLER at90usb_adc, ATMEGA_IRQ_ADC, excpt_common /* ADC conversion complete */
- HANDLER at90usb_ee, ATMEGA_IRQ_EE, excpt_common /* EEPROM ready */
- HANDLER at90usb_t3capt, ATMEGA_IRQ_T3CAPT, excpt_common /* TIMER3 CAPT timer/counter3 capture event */
- HANDLER at90usb_t3compa, ATMEGA_IRQ_T3COMPA, excpt_common /* TIMER3 COMPA timer/counter3 compare match a */
- HANDLER at90usb_t3compb, ATMEGA_IRQ_T3COMPB, excpt_common /* TIMER3 COMPB timer/counter3 compare match b */
- HANDLER at90usb_t3compc, ATMEGA_IRQ_T3COMPC, excpt_common /* TIMER3 COMPC timer/counter3 compare match c */
- HANDLER at90usb_t3ovf, ATMEGA_IRQ_T3OVF, excpt_common /* TIMER3 OVF timer/counter3 overflow */
- HANDLER at90usb_twi, ATMEGA_IRQ_TWI, excpt_common /* TWI two-wire serial interface */
- HANDLER at90usb_spmrdy, ATMEGA_IRQ_SPMRDY, excpt_common /* Store program memory ready */
+ HANDLER at90usb_t0ovf, AT90USB_IRQ_T0OVF, excpt_common /* TIMER0 OVF timer/counter0 overflow */
+ HANDLER at90usb_spi, AT90USB_IRQ_SPI, excpt_common /* STC SPI serial transfer complete */
+ HANDLER at90usb_u1rx, AT90USB_IRQ_U1RX, excpt_common /* USART1 RX complete */
+ HANDLER at90usb_u1dre, AT90USB_IRQ_U1DRE, excpt_common /* USART1 data register empty */
+ HANDLER at90usb_u1tx, AT90USB_IRQ_U1TX, excpt_common /* USART1 TX complete */
+ HANDLER at90usb_anacomp, AT90USB_IRQ_ANACOMP, excpt_common /* ANALOG COMP analog comparator */
+ HANDLER at90usb_adc, AT90USB_IRQ_ADC, excpt_common /* ADC conversion complete */
+ HANDLER at90usb_ee, AT90USB_IRQ_EE, excpt_common /* EEPROM ready */
+ HANDLER at90usb_t3capt, AT90USB_IRQ_T3CAPT, excpt_common /* TIMER3 CAPT timer/counter3 capture event */
+ HANDLER at90usb_t3compa, AT90USB_IRQ_T3COMPA, excpt_common /* TIMER3 COMPA timer/counter3 compare match a */
+ HANDLER at90usb_t3compb, AT90USB_IRQ_T3COMPB, excpt_common /* TIMER3 COMPB timer/counter3 compare match b */
+ HANDLER at90usb_t3compc, AT90USB_IRQ_T3COMPC, excpt_common /* TIMER3 COMPC timer/counter3 compare match c */
+ HANDLER at90usb_t3ovf, AT90USB_IRQ_T3OVF, excpt_common /* TIMER3 OVF timer/counter3 overflow */
+ HANDLER at90usb_twi, AT90USB_IRQ_TWI, excpt_common /* TWI two-wire serial interface */
+ HANDLER at90usb_spmrdy, AT90USB_IRQ_SPMRDY, excpt_common /* Store program memory ready */
/* Common exception handling logic. */
diff --git a/nuttx/arch/avr/src/at90usb/at90usb_head.S b/nuttx/arch/avr/src/at90usb/at90usb_head.S index 16d4abcc1..f951bac1d 100755 --- a/nuttx/arch/avr/src/at90usb/at90usb_head.S +++ b/nuttx/arch/avr/src/at90usb/at90usb_head.S @@ -193,6 +193,9 @@ __start: /* Copy initial global data values from FLASH into RAM */
+ .global __do_copy_data; /* Required to suppress dragging in logic from libgcc */
+__do_copy_data:
+
#ifdef HAVE_RAMPZ
ldi r17, hi8(_edata)
ldi r26, lo8(_sdata)
@@ -230,6 +233,9 @@ __start: /* Clear uninitialized data */
+ .global __do_clear_bss; /* Required to suppress dragging in logic from libgcc */
+__do_clear_bss:
+
ldi r17, hi8(_ebss)
ldi r26, lo8(_sbss)
ldi r27, hi8(_sbss)
diff --git a/nuttx/arch/avr/src/atmega/Make.defs b/nuttx/arch/avr/src/atmega/Make.defs index 3699543dd..9bcf64ea0 100644 --- a/nuttx/arch/avr/src/atmega/Make.defs +++ b/nuttx/arch/avr/src/atmega/Make.defs @@ -40,10 +40,18 @@ HEAD_ASRC = atmega_head.S # Common AVR files CMN_ASRCS = up_switchcontext.S -CMN_CSRCS = up_allocateheap.c up_copystate.c up_createstack.c up_exit.c \ - up_idle.c up_initialize.c up_interruptcontext.c up_lowputs.c \ - up_mdelay.c up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c \ - up_puts.c up_releasestack.c up_udelay.c up_usestack.c +CMN_CSRCS = up_allocateheap.c up_assert.c up_blocktask.c up_copystate.c \ + up_createstack.c up_doirq.c up_exit.c up_idle.c up_initialize.c \ + up_interruptcontext.c up_lowputs.c up_mdelay.c up_modifyreg8.c \ + up_modifyreg16.c up_modifyreg32.c up_puts.c up_releasepending.c \ + up_releasestack.c up_reprioritizertr.c up_schedulesigaction.c \ + up_sigdeliver.c up_udelay.c up_unblocktask.c up_usestack.c + +# Configuration-dependent common files + +ifeq ($(CONFIG_ARCH_STACKDUMP),y) +CMN_CSRCS += up_dumpstate.c +endif # Required ATMEGA files diff --git a/nuttx/arch/avr/src/atmega/atmega_head.S b/nuttx/arch/avr/src/atmega/atmega_head.S index aff46a39e..2ebd8ecec 100755 --- a/nuttx/arch/avr/src/atmega/atmega_head.S +++ b/nuttx/arch/avr/src/atmega/atmega_head.S @@ -39,6 +39,7 @@ #include <nuttx/config.h>
+#include <arch/irq.h>
#include <avr/io.h>
#include <avr/sfr_defs.h>
@@ -186,6 +187,9 @@ __start: /* Copy initial global data values from FLASH into RAM */
+ .global __do_copy_data; /* Required to suppress dragging in logic from libgcc */
+__do_copy_data:
+
#ifdef HAVE_RAMPZ
ldi r17, hi8(_edata)
ldi r26, lo8(_sdata)
@@ -223,6 +227,9 @@ __start: /* Clear uninitialized data */
+ .global __do_clear_bss; /* Required to suppress dragging in logic from libgcc */
+__do_clear_bss:
+
ldi r17, hi8(_ebss)
ldi r26, lo8(_sbss)
ldi r27, hi8(_sbss)
diff --git a/nuttx/arch/avr/src/avr/avr_internal.h b/nuttx/arch/avr/src/avr/avr_internal.h index 18265332e..c66103f00 100644 --- a/nuttx/arch/avr/src/avr/avr_internal.h +++ b/nuttx/arch/avr/src/avr/avr_internal.h @@ -94,7 +94,7 @@ extern void up_copystate(uint8_t *dest, uint8_t *src); extern int up_saveusercontext(uint8_t *saveregs); extern void up_fullcontextrestore(uint8_t *restoreregs) __attribute__ ((noreturn)); extern void up_switchcontext(uint8_t *saveregs, uint8_t *restoreregs); -extern uint8_t *up_doirq(int irq, uint8_t *regs); +extern uint8_t *up_doirq(uint8_t irq, uint8_t *regs); #endif /* __ASSEMBLY__ */ #endif /* __ARCH_AVR_SRC_AVR_AVR_INTERNAL_H */ diff --git a/nuttx/arch/avr/src/avr/excptmacros.h b/nuttx/arch/avr/src/avr/excptmacros.h index b4408f288..463b95296 100755 --- a/nuttx/arch/avr/src/avr/excptmacros.h +++ b/nuttx/arch/avr/src/avr/excptmacros.h @@ -1,22 +1,22 @@ /********************************************************************************************
* arch/avr/src/avr/excptmacros.h
*
- * Copyright (C) 2011 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* 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.
+ * 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.
+ * 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.
+ * 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
@@ -104,30 +104,39 @@ * RESTORE_STACK rx, ry - Undo the operations of USE_STACK
*
* EXCPT_EPILOGUE - Return to the context returned by handler()
+ * reti - Return from interrupt
*
********************************************************************************************/
-/****************************************************************************
- * Macros
- ****************************************************************************/
/********************************************************************************************
* Name: HANDLER
*
* Description:
- * This macro provides the exception entry logic. It simply saves one register on the
- * stack (r24) and passes the IRQ number to to common logic (see EXCPT_PROLOGUE).
+ * This macro provides the exception entry logic. It is called with the PC already on the
+ * stack. It simply saves one register on the stack (r24) and passes the IRQ number to
+ * common logic (see EXCPT_PROLOGUE).
*
* On Entry:
- * sp - Points to the top of the stack
- * Only the stack is available for storage
+ * sp - Points to the top of the stack. The PC is already on the stack.
+ * Only the stack is available for storage
+ *
+ * PCL
+ * PCH
+ * --- <- SP
*
* At completion:
- * Stack pointer is incremented by one, the saved r24 is on the stack, r24 now contains the
- * IRQ number
+ * Stack pointer is incremented by one, the saved r24 is on the stack, r24 now contains the
+ * IRQ number
+ *
+ * PCL
+ * PCH
+ * R0
+ * --- <- SP
*
********************************************************************************************/
- .macro HANDLER, label, irqno, common
+ .macro HANDLER, label, irqno, common
+ .global \label
\label:
push r24
ldi r24, \irqno
@@ -138,20 +147,26 @@ * Name: EXCPT_PROLOGUE
*
* Description:
- * Provides the common "prologue" logic that should appear at the beginning of the exception
- * handler.
+ * Provides the common "prologue" logic that should appear at the beginning of the exception
+ * handler.
*
* On Entry:
- * r0 - has already been pushed onto the stack and now holds the IRQ number
- * sp - Points to the top of the stack
- * Only the stack is available for storage
+ * r0 - has already been pushed onto the stack and now holds the IRQ number
+ * sp - Points to the top of the stack
+ * Only the stack is available for storage
+ *
+ * PCL
+ * PCH
+ * R0
+ * --- <- SP
*
* At completion:
- * Register state is saved on the stack; All registers are available for usage except sp.
+ * Register state is saved on the stack; All registers are available for usage except sp.
*
********************************************************************************************/
.macro EXCPT_PROLOGUE
+
/* Save R1 - The zero register (but might not be zero) */
push r1
@@ -228,15 +243,16 @@ * Name: EXCPT_EPILOGUE
*
* Description:
- * Provides the "epilogue" logic that should appear at the end of every exception handler.
+ * Provides the "epilogue" logic that should appear at the end of every exception handler.
*
* On input:
- * sp points to the address of the register save area (just as left by EXCPT_PROLOGUE).
- * All registers are available for use.
- * Interrupts are disabled.
+ * sp points to the address of the register save area (just as left by EXCPT_PROLOGUE).
+ * All registers are available for use.
+ * Interrupts are disabled.
*
* On completion:
- * All registers restored
+ * All registers restored except the PC which remains on the stack so that a return
+ * via reti can be performed.
*
********************************************************************************************/
@@ -312,16 +328,17 @@ * Name: USER_SAVE
*
* Description:
- * Similar to EXPCT_PROLOGUE except that (1) this saves values into a register save
- * data structure instead of on the stack, (2) the pointer is in r26;r27, and (3)
- * Call-used registers are not saved.
+ * Similar to EXPCT_PROLOGUE except that (1) this saves values into a register save
+ * data structure instead of on the stack, (2) the pointer is in r26;r27, and (3)
+ * Call-used registers are not saved.
*
* On Entry:
- * X [r26:r27] - Points to the register save structure.
- * Interrupts are disabled.
+ * X [r26:r27] - Points to the register save structure.
+ * Return address is already on the stack (due to CALL or RCALL instruction)/.
+ * Interrupts are disabled.
*
* At completion:
- * Register state is saved on the stack; All registers are available for usage except sp.
+ * Register state is saved on the stack; All registers are available for usage except sp.
*
********************************************************************************************/
@@ -377,35 +394,59 @@ st x+, r0
/* Skip R0 and r24 - These are scratch register and Call-used, "volatile" registers */
+
+ adiw r26, 2 /* Two registers: r0, r24 */
+
+ /* Pop and save the return address */
+
+ pop r0
+ st x+, r0
+ pop r0
+ st x+, r0
.endm
/********************************************************************************************
* Name: TCB_RESTORE
*
* Description:
- * Functionally equivalent to EXCPT_EPILOGUE excetp that register save area is not on the
- * stack but is held in a data structure.
+ * Functionally equivalent to EXCPT_EPILOGUE excetp that register save area is not on the
+ * stack but is held in a data structure.
*
* On input:
- * X [r26:r27] points to the data structure.
- * All registers are available for use.
- * Interrupts are disabled.
+ * X [r26:r27] points to the data structure.
+ * All registers are available for use.
+ * Interrupts are disabled.
*
* On completion:
- * All registers restored
+ * All registers restored except for the PC with now resides at the top of the new stack
+ * so that iret can be used to switch to the new context.
*
********************************************************************************************/
.macro TCB_RESTORE, regs
- /* Fetch the new stack pointer and the saved values of X [r26:r27]. Save X on the new
- * stack where we can recover it later.
- */
+ /* Fetch the new stack pointer */
ld r24, x+ /* Fetch stack pointer (post-incrementing) */
out __SP_L__, r24
ld r25, x+
out __SP_H__, r25
+
+ /* Fetch the return address and save it at the bottom of the new stack so
+ * that we can iret to switch contexts.
+ */
+
+ movw r28, r26 /* Get a pointer to the PCH/PCL storage location */
+ adiw r28, REG_PCH
+ ld r25, y+ /* Load PCH and PCL */
+ ld r24, y+
+ push r24 /* Push PCH and PCL on the stack */
+ push r25
+
+ /* Then get value of X [r26:r27]. Save X on the new stack where we can
+ * recover it later.
+ */
+
ld r25, x+ /* Fetch r26-r27 and save to the new stack */
ld r24, x+
push r24
@@ -466,7 +507,9 @@ ld r0, x+
ld r24, x+
- /* Finally, recover X [r26-r27] from the the new stack */
+ /* Finally, recover X [r26-r27] from the the new stack. The PC remains on the new
+ * stack so that the user of this macro can return with iret.
+ */
pop r27
pop r26
@@ -476,18 +519,18 @@ * Name: USE_INTSTACK
*
* Description:
- * Switch to the interrupt stack (if enabled in the configuration) and if the nesting level
- * is equal to 0. Increment the nesting level in any event.
+ * Switch to the interrupt stack (if enabled in the configuration) and if the nesting level
+ * is equal to 0. Increment the nesting level in any event.
*
* On Entry:
- * sp - Current value of the user stack pointer
- * tmp1, tmp2, and tmp3 are registers that can be used temporarily.
- * All interrupts should still be disabled.
+ * sp - Current value of the user stack pointer
+ * tmp1, tmp2, and tmp3 are registers that can be used temporarily.
+ * All interrupts should still be disabled.
*
* At completion:
- * If the nesting level is 0, then (1) the user stack pointer is saved at the base of the
- * interrupt stack and sp points to the interrupt stack.
- * The values of tmp1, tmp2, tmp3, and sp have been altered
+ * If the nesting level is 0, then (1) the user stack pointer is saved at the base of the
+ * interrupt stack and sp points to the interrupt stack.
+ * The values of tmp1, tmp2, tmp3, and sp have been altered
*
********************************************************************************************/
@@ -501,16 +544,16 @@ * Name: RESTORE_STACK
*
* Description:
- * Restore the user stack. Not really.. actually only decrements the nesting level. We
- * always get the new stack pointer for the register save array.
+ * Restore the user stack. Not really.. actually only decrements the nesting level. We
+ * always get the new stack pointer for the register save array.
*
* On Entry:
- * tmp1 and tmp2 are registers that can be used temporarily.
- * All interrupts must be disabled.
+ * tmp1 and tmp2 are registers that can be used temporarily.
+ * All interrupts must be disabled.
*
* At completion:
- * Current nesting level is decremented
- * The values of tmp1 and tmp2 have been altered
+ * Current nesting level is decremented
+ * The values of tmp1 and tmp2 have been altered
*
********************************************************************************************/
diff --git a/nuttx/arch/avr/src/avr/up_blocktask.c b/nuttx/arch/avr/src/avr/up_blocktask.c new file mode 100755 index 000000000..6444132e0 --- /dev/null +++ b/nuttx/arch/avr/src/avr/up_blocktask.c @@ -0,0 +1,168 @@ +/**************************************************************************** + * arch/avr/src/avr/up_blocktask.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <nuttx/config.h> + +#include <stdbool.h> +#include <sched.h> +#include <debug.h> + +#include <nuttx/arch.h> + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * 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(_TCB *tcb, tstate_t task_state) +{ + /* Verify that the context switch can be performed */ + + if ((tcb->task_state < FIRST_READY_TO_RUN_STATE) || + (tcb->task_state > LAST_READY_TO_RUN_STATE)) + { + PANIC(OSERR_BADBLOCKSTATE); + } + else + { + _TCB *rtcb = (_TCB*)g_readytorun.head; + bool switch_needed; + + /* 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 g_readytorun + * task list now + */ + + if (g_pendingtasks.head) + { + switch_needed |= sched_mergepending(); + } + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + /* Are we in an interrupt handler? */ + + if (current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (_TCB*)g_readytorun.head; + + /* Then switch contexts */ + + 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. + */ + + _TCB *nexttcb = (_TCB*)g_readytorun.head; + 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/nuttx/arch/avr/src/avr/up_doirq.c b/nuttx/arch/avr/src/avr/up_doirq.c new file mode 100644 index 000000000..764117abf --- /dev/null +++ b/nuttx/arch/avr/src/avr/up_doirq.c @@ -0,0 +1,116 @@ +/**************************************************************************** + * arch/avr/src/avr/up_doirq.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <nuttx/config.h> + +#include <stdint.h> +#include <assert.h> + +#include <nuttx/irq.h> +#include <nuttx/arch.h> +#include <arch/board/board.h> + +#include "up_arch.h" +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +uint8_t *up_doirq(uint8_t irq, uint8_t *regs) +{ + up_ledon(LED_INIRQ); +#ifdef CONFIG_SUPPRESS_INTERRUPTS + PANIC(OSERR_ERREXCEPTION); +#else + uint8_t *savestate; + + /* Nested interrupts are not supported in this implementation. If you want + * implemented nested interrupts, you would have to (1) change the way that + * current regs is handled and (2) the design associated with + * CONFIG_ARCH_INTERRUPTSTACK. + */ + + /* Current regs non-zero indicates that we are processing an interrupt; + * current_regs is also used to manage interrupt level context switches. + */ + + savestate = (uint8_t*)current_regs; + current_regs = regs; + + /* Deliver the IRQ */ + + irq_dispatch((int)irq, (uint32_t*)regs); + + /* If a context switch occurred while processing the interrupt then + * 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 = current_regs; + + /* Restore the previous value of current_regs. NULL would indicate that + * we are no longer in an interrupt handler. It will be non-NULL if we + * are returning from a nested interrupt. + */ + + current_regs = savestate; +#endif + up_ledoff(LED_INIRQ); + return regs; +} + diff --git a/nuttx/arch/avr/src/avr/up_dumpstate.c b/nuttx/arch/avr/src/avr/up_dumpstate.c new file mode 100644 index 000000000..e9d0859e8 --- /dev/null +++ b/nuttx/arch/avr/src/avr/up_dumpstate.c @@ -0,0 +1,263 @@ +/**************************************************************************** + * arch/avr/src/avr/up_dumpstate.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <nuttx/config.h> + +#include <stdint.h> +#include <stdlib.h> +#include <assert.h> +#include <debug.h> + +#include <nuttx/irq.h> +#include <nuttx/arch.h> +#include <arch/board/board.h> + +#include "up_arch.h" +#include "os_internal.h" +#include "up_internal.h" + +#ifdef CONFIG_ARCH_STACKDUMP + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Output debug info if stack dump is selected -- even if debug is not + * selected. + */ + +#undef lldbg +#define lldbg lib_lowprintf + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_getsp + ****************************************************************************/ + +/* There may be a built-in to do this, but I don't know if it is enabled */ + +static inline uint16_t up_getsp(void) +{ + uint8_t spl; + uint8_t sph; + + __asm__ __volatile__ + ( + "in %0, __SP_L__\n\t" + "in %1, __SP_H__\n" + : "=r" (spl), "=r" (sph) + : + ); + return (uint16_t)sph << 8 | spl; +} + +/**************************************************************************** + * Name: up_stackdump + ****************************************************************************/ + +static void up_stackdump(uint16_t sp, uint16_t stack_base) +{ + uint16_t stack ; + + for (stack = sp & ~3; stack < stack_base; stack += 12) + { + uint8_t *ptr = (uint8_t*)stack; + lldbg("%04x: %02x %02x %02x %02x %02x %02x %02x %02x" + " %02x %02x %02x %02x\n", + stack, + ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], + ptr[9], ptr[10], ptr[11]); + } +} + +/**************************************************************************** + * Name: up_registerdump + ****************************************************************************/ + +static inline void up_registerdump(void) +{ + /* Are user registers available from interrupt processing? */ + + if (current_regs) + { + lldbg("R%d: %02x %02x %02x %02x %02x %02x %02x %02x\n", + 0, + current_regs[REG_R0], current_regs[REG_R1], + current_regs[REG_R2], current_regs[REG_R3], + current_regs[REG_R4], current_regs[REG_R5], + current_regs[REG_R6], current_regs[REG_R7]); + + lldbg("R%d: %02x %02x %02x %02x %02x %02x %02x %02x\n", + 8, + current_regs[REG_R8], current_regs[REG_R9], + current_regs[REG_R10], current_regs[REG_R11], + current_regs[REG_R12], current_regs[REG_R13], + current_regs[REG_R14], current_regs[REG_R15]); + + lldbg("R%d: %02x %02x %02x %02x %02x %02x %02x %02x\n", + 16, + current_regs[REG_R16], current_regs[REG_R17], + current_regs[REG_R18], current_regs[REG_R19], + current_regs[REG_R20], current_regs[REG_R21], + current_regs[REG_R22], current_regs[REG_R23]); + + lldbg("R%d: %02x %02x %02x %02x %02x %02x %02x %02x\n", + 24, + current_regs[REG_R24], current_regs[REG_R25], + current_regs[REG_R26], current_regs[REG_R27], + current_regs[REG_R28], current_regs[REG_R29], + current_regs[REG_R30], current_regs[REG_R31]); + + lldbg("PC: %02x%02x SP: %02x%02x SREG: %02x\n", + current_regs[REG_PCH], current_regs[REG_PCL], + current_regs[REG_SPH], current_regs[REG_SPL], + current_regs[REG_SREG]); + } +} + +/**************************************************************************** + * Name: _up_assert + ****************************************************************************/ + +/**************************************************************************** + * Name: up_dumpstate + ****************************************************************************/ + +void up_dumpstate(void) +{ + _TCB *rtcb = (_TCB*)g_readytorun.head; + uint16_t sp = up_getsp(); + uint16_t ustackbase; + uint16_t ustacksize; +#if CONFIG_ARCH_INTERRUPTSTACK > 0 + uint16_t istackbase; + uint16_t istacksize; +#endif + + /* Get the limits on the user stack memory */ + + if (rtcb->pid == 0) + { + ustackbase = g_heapbase - 4; + ustacksize = CONFIG_IDLETHREAD_STACKSIZE; + } + else + { + ustackbase = (uint16_t)rtcb->adj_stack_ptr; + ustacksize = (uint16_t)rtcb->adj_stack_size; + } + + /* Get the limits on the interrupt stack memory */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + istackbase = (uint16_t)&g_intstackbase; + istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4; + + /* Show interrupt stack info */ + + lldbg("sp: %04x\n", sp); + lldbg("IRQ stack:\n"); + lldbg(" base: %04x\n", istackbase); + lldbg(" size: %04x\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 if we are in an interrupt handler. + * If we are not in an interrupt handler. Then sp is the user stack + * pointer (and the above range check should have failed). + */ + + if (current_regs) + { + sp = current_regs[REG_R13]; + lldbg("sp: %04x\n", sp); + } + + lldbg("User stack:\n"); + lldbg(" base: %04x\n", ustackbase); + lldbg(" size: %04x\n", ustacksize); + + /* Dump the user stack if the stack pointer lies within the allocated user + * stack memory. + */ + + if (sp <= ustackbase && sp > ustackbase - ustacksize) + { + up_stackdump(sp, ustackbase); + } +#else + lldbg("sp: %04x\n", sp); + lldbg("stack base: %04x\n", ustackbase); + lldbg("stack size: %04x\n", ustacksize); + + /* Dump the user stack if the stack pointer lies within the allocated user + * stack memory. + */ + + if (sp > ustackbase || sp <= ustackbase - ustacksize) + { + lldbg("ERROR: Stack pointer is not within allocated stack\n"); + } + else + { + up_stackdump(sp, ustackbase); + } +#endif + + /* Then dump the registers (if available) */ + + up_registerdump(); +} +#endif diff --git a/nuttx/arch/avr/src/avr/up_releasepending.c b/nuttx/arch/avr/src/avr/up_releasepending.c new file mode 100755 index 000000000..bd3537944 --- /dev/null +++ b/nuttx/arch/avr/src/avr/up_releasepending.c @@ -0,0 +1,131 @@ +/**************************************************************************** + * arch/avr/src/avr/up_releasepending.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <nuttx/config.h> + +#include <sched.h> +#include <debug.h> +#include <nuttx/arch.h> + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * 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) +{ + _TCB *rtcb = (_TCB*)g_readytorun.head; + + slldbg("From TCB=%p\n", rtcb); + + /* Merge the g_pendingtasks list into the g_readytorun task list */ + + /* sched_lock(); */ + if (sched_mergepending()) + { + /* The currently active task has changed! We will need to + * switch contexts. First check if we are operating in + * interrupt context: + */ + + if (current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (_TCB*)g_readytorun.head; + slldbg("New Active Task TCB=%p\n", rtcb); + + /* Then switch contexts */ + + 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. + */ + + _TCB *nexttcb = (_TCB*)g_readytorun.head; + 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/nuttx/arch/avr/src/avr/up_reprioritizertr.c b/nuttx/arch/avr/src/avr/up_reprioritizertr.c new file mode 100755 index 000000000..3983b3953 --- /dev/null +++ b/nuttx/arch/avr/src/avr/up_reprioritizertr.c @@ -0,0 +1,182 @@ +/**************************************************************************** + * arch/avr/src/avr/up_reprioritizertr.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <nuttx/config.h> + +#include <stdint.h> +#include <stdbool.h> +#include <sched.h> +#include <debug.h> +#include <nuttx/arch.h> + +#include "os_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_reprioritize_rtr + * + * Description: + * Called when the priority of a running or + * ready-to-run task changes and the reprioritization will + * cause a context switch. Two cases: + * + * 1) The priority of the currently running task drops and the next + * task in the ready to run list has priority. + * 2) An idle, ready to run task's priority has been raised above the + * the priority of the current, running task and it now has the + * priority. + * + * Inputs: + * tcb: The TCB of the task that has been reprioritized + * priority: The new task priority + * + ****************************************************************************/ + +void up_reprioritize_rtr(_TCB *tcb, uint8_t priority) +{ + /* Verify that the caller is sane */ + + if (tcb->task_state < FIRST_READY_TO_RUN_STATE || + tcb->task_state > LAST_READY_TO_RUN_STATE || + priority < SCHED_PRIORITY_MIN || + priority > SCHED_PRIORITY_MAX) + { + PANIC(OSERR_BADREPRIORITIZESTATE); + } + else + { + _TCB *rtcb = (_TCB*)g_readytorun.head; + bool switch_needed; + + slldbg("TCB=%p PRI=%d\n", tcb, priority); + + /* Remove the tcb task from the ready-to-run list. + * sched_removereadytorun will return true if we just + * remove the head of the ready to run list. + */ + + switch_needed = sched_removereadytorun(tcb); + + /* Setup up the new task priority */ + + tcb->sched_priority = (uint8_t)priority; + + /* Return the task to the specified blocked task list. + * sched_addreadytorun will return true if the task was + * added to the new list. We will need to perform a context + * switch only if the EXCLUSIVE or of the two calls is non-zero + * (i.e., one and only one the calls changes the head of the + * ready-to-run list). + */ + + switch_needed ^= sched_addreadytorun(tcb); + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + /* If we are going to do a context switch, then now is the right + * time to add any pending tasks back into the ready-to-run list. + * task list now + */ + + if (g_pendingtasks.head) + { + sched_mergepending(); + } + + /* Are we in an interrupt handler? */ + + if (current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (_TCB*)g_readytorun.head; + slldbg("New Active Task TCB=%p\n", rtcb); + + /* Then switch contexts */ + + 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. + */ + + _TCB *nexttcb = (_TCB*)g_readytorun.head; + 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/nuttx/arch/avr/src/avr/up_schedulesigaction.c b/nuttx/arch/avr/src/avr/up_schedulesigaction.c new file mode 100644 index 000000000..af9e917c6 --- /dev/null +++ b/nuttx/arch/avr/src/avr/up_schedulesigaction.c @@ -0,0 +1,209 @@ +/**************************************************************************** + * arch/avr/src/avr/up_schedulesigaction.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <nuttx/config.h> + +#include <stdint.h> +#include <sched.h> +#include <debug.h> + +#include <nuttx/arch.h> +#include <avr/io.h> + +#include "os_internal.h" +#include "up_internal.h" +#include "up_arch.h" + +#ifndef CONFIG_DISABLE_SIGNALS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_schedule_sigaction + * + * Description: + * This function is called by the OS when one or more + * signal handling actions have been queued for execution. + * The architecture specific code must configure things so + * that the 'igdeliver' callback is executed on the thread + * specified by 'tcb' as soon as possible. + * + * This function may be called from interrupt handling logic. + * + * This operation should not cause the task to be unblocked + * nor should it cause any immediate execution of sigdeliver. + * Typically, a few cases need to be considered: + * + * (1) This function may be called from an interrupt handler + * During interrupt processing, all xcptcontext structures + * should be valid for all tasks. That structure should + * be modified to invoke sigdeliver() either on return + * from (this) interrupt or on some subsequent context + * switch to the recipient task. + * (2) If not in an interrupt handler and the tcb is NOT + * the currently executing task, then again just modify + * the saved xcptcontext structure for the recipient + * task so it will invoke sigdeliver when that task is + * later resumed. + * (3) If not in an interrupt handler and the tcb IS the + * currently executing task -- just call the signal + * handler now. + * + ****************************************************************************/ + +void up_schedule_sigaction(_TCB *tcb, sig_deliver_t sigdeliver) +{ + /* Refuse to handle nested signal actions */ + + sdbg("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver); + + if (!tcb->xcp.sigdeliver) + { + irqstate_t flags; + + /* Make sure that interrupts are disabled */ + + flags = irqsave(); + + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ + + sdbg("rtcb=0x%p current_regs=0x%p\n", g_readytorun.head, current_regs); + + if (tcb == (_TCB*)g_readytorun.head) + { + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. + */ + + if (!current_regs) + { + /* In this case just deliver the signal now. */ + + sigdeliver(tcb); + } + + /* CASE 2: We are in an interrupt handler AND the + * interrupted task is the same as the one that + * must receive the signal, then we will have to modify + * the return state as well as the state in the TCB. + * + * Hmmm... there looks like a latent bug here: The following + * logic would fail in the strange case where we are in an + * interrupt handler, the thread is signalling itself, but + * a context switch to another task has occurred so that + * current_regs does not refer to the thread at g_readytorun.head! + */ + + else + { + /* Save registers that must be protected while the signal handler + * runs. These will be restored by the signal trampoline after + * the signal(s) have been delivered. + */ + + tcb->xcp.sigdeliver = sigdeliver; + tcb->xcp.saved_pcl = current_regs[REG_PCL]; + tcb->xcp.saved_pch = current_regs[REG_PCH]; + tcb->xcp.saved_sreg = current_regs[REG_SREG]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + current_regs[REG_PCL] = (uint16_t)up_sigdeliver & 0xff; + current_regs[REG_PCH] = (uint16_t)up_sigdeliver >> 8; + current_regs[REG_SREG] |= (1 << SREG_I); + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + up_savestate(tcb->xcp.regs); + } + } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save registers that must be protected while the signal handler + * runs. These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.sigdeliver = sigdeliver; + tcb->xcp.saved_pcl = tcb->xcp.regs[REG_PCL]; + tcb->xcp.saved_pch = tcb->xcp.regs[REG_PCH]; + tcb->xcp.saved_sreg = tcb->xcp.regs[REG_SREG]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_PCL] = (uint16_t)up_sigdeliver & 0xff; + tcb->xcp.regs[REG_PCH] = (uint16_t)up_sigdeliver >> 8; + tcb->xcp.regs[REG_SREG] |= (1 << SREG_I); + } + + irqrestore(flags); + } +} + +#endif /* !CONFIG_DISABLE_SIGNALS */ + diff --git a/nuttx/arch/avr/src/avr/up_sigdeliver.c b/nuttx/arch/avr/src/avr/up_sigdeliver.c new file mode 100644 index 000000000..bef283414 --- /dev/null +++ b/nuttx/arch/avr/src/avr/up_sigdeliver.c @@ -0,0 +1,154 @@ +/**************************************************************************** + * arch/avr/src/avr/up_sigdeliver.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <nuttx/config.h> + +#include <stdint.h> +#include <sched.h> +#include <debug.h> + +#include <nuttx/irq.h> +#include <nuttx/arch.h> +#include <arch/board/board.h> + +#include "os_internal.h" +#include "up_internal.h" +#include "up_arch.h" + +#ifndef CONFIG_DISABLE_SIGNALS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_sigdeliver + * + * Description: + * This is the a signal handling trampoline. When a signal action was + * posted. The task context was mucked with and forced to branch to this + * location with interrupts disabled. + * + ****************************************************************************/ + +void up_sigdeliver(void) +{ + _TCB *rtcb = (_TCB*)g_readytorun.head; + uint8_t regs[XCPTCONTEXT_REGS]; + sig_deliver_t sigdeliver; + + /* Save the errno. This must be preserved throughout the signal handling + * so that the user code final gets the correct errno value (probably EINTR). + */ + + int saved_errno = rtcb->pterrno; + + up_ledon(LED_SIGNAL); + + sdbg("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", + rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); + ASSERT(rtcb->xcp.sigdeliver != NULL); + + /* Save the real return state on the stack. */ + + up_copystate(regs, rtcb->xcp.regs); + regs[REG_PCL] = rtcb->xcp.saved_pcl; + regs[REG_PCH] = rtcb->xcp.saved_pch; + regs[REG_SREG] = rtcb->xcp.saved_sreg; + + /* Get a local copy of the sigdeliver function pointer. We do this so that + * we can nullify the sigdeliver function pointer in the TCB and accept + * more signal deliveries while processing the current pending signals. + */ + + sigdeliver = rtcb->xcp.sigdeliver; + rtcb->xcp.sigdeliver = NULL; + + /* Then restore the task interrupt state */ + + irqrestore(regs[REG_SREG]); + + /* Deliver the signals */ + + sigdeliver(rtcb); + + /* Output any debug messages BEFORE restoring errno (because they may + * alter errno), then disable interrupts again and restore the original + * errno that is needed by the user logic (it is probably EINTR). + */ + + sdbg("Resuming\n"); + (void)irqsave(); + rtcb->pterrno = saved_errno; + + /* Then restore the correct state for this thread of execution. This is an + * unusual case that must be handled by up_fullcontextresore. This case is + * unusal in two ways: + * + * 1. It is not a context switch between threads. Rather, up_fullcontextrestore + * must behave more it more like a longjmp within the same task, using + * he same stack. + * 2. In this case, up_fullcontextrestore is called with r12 pointing to + * a register save area on the stack to be destroyed. This is + * dangerous because there is the very real possibility that the new + * stack pointer might overlap with the register save area and hat stack + * usage in up_fullcontextrestore might corrupt the register save data + * before the state is restored. At present, there does not appear to + * be any stack overlap problems. If there were, then adding 3 words + * to the size of register save structure size will protect its contents. + */ + + up_ledoff(LED_SIGNAL); + up_fullcontextrestore(regs); +} + +#endif /* !CONFIG_DISABLE_SIGNALS */ + diff --git a/nuttx/arch/avr/src/avr/up_switchcontext.S b/nuttx/arch/avr/src/avr/up_switchcontext.S index b31173456..18653d305 100755 --- a/nuttx/arch/avr/src/avr/up_switchcontext.S +++ b/nuttx/arch/avr/src/avr/up_switchcontext.S @@ -129,6 +129,10 @@ up_fullcontextrestore: /* Restore the context from the TCB saved registers */ TCB_RESTORE + + /* And "return" to the new task. */ + + reti .endfunc .end diff --git a/nuttx/arch/avr/src/avr/up_unblocktask.c b/nuttx/arch/avr/src/avr/up_unblocktask.c new file mode 100755 index 000000000..a55b81e2c --- /dev/null +++ b/nuttx/arch/avr/src/avr/up_unblocktask.c @@ -0,0 +1,158 @@ +/**************************************************************************** + * arch/avr/src/avr/up_unblocktask.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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 <nuttx/config.h> + +#include <sched.h> +#include <debug.h> +#include <nuttx/arch.h> + +#include "os_internal.h" +#include "clock_internal.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * 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 taks, executed. + * + ****************************************************************************/ + +void up_unblock_task(_TCB *tcb) +{ + /* Verify that the context switch can be performed */ + + if ((tcb->task_state < FIRST_BLOCKED_STATE) || + (tcb->task_state > LAST_BLOCKED_STATE)) + { + PANIC(OSERR_BADUNBLOCKSTATE); + } + else + { + _TCB *rtcb = (_TCB*)g_readytorun.head; + + /* Remove the task from the blocked task list */ + + sched_removeblocked(tcb); + + /* Reset its timeslice. This is only meaningful for round + * robin tasks but it doesn't here to do it for everything + */ + +#if CONFIG_RR_INTERVAL > 0 + tcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK; +#endif + + /* Add the task in the correct location in the prioritized + * g_readytorun task list + */ + + if (sched_addreadytorun(tcb)) + { + /* The currently active task has changed! We need to do + * a context switch to the new task. + * + * Are we in an interrupt handler? + */ + + if (current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the g_readytorun task list. + */ + + rtcb = (_TCB*)g_readytorun.head; + + /* Then switch contexts */ + + 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. + */ + + _TCB *nexttcb = (_TCB*)g_readytorun.head; + 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/nuttx/arch/avr/src/avr32/up_assert.c b/nuttx/arch/avr/src/avr32/up_dumpstate.c index b335c71b2..71e35eea6 100644 --- a/nuttx/arch/avr/src/avr32/up_assert.c +++ b/nuttx/arch/avr/src/avr32/up_dumpstate.c @@ -1,7 +1,7 @@ /**************************************************************************** - * arch/avr/src/avr32/up_assert.c + * arch/avr/src/avr32/up_dumpstate.c * - * Copyright (C) 2010 Gregory Nutt. All rights reserved. + * Copyright (C) 2010-2011 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * Redistribution and use in source and binary forms, with or without @@ -52,6 +52,8 @@ #include "os_internal.h" #include "up_internal.h" +#ifdef CONFIG_ARCH_STACKDUMP + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -60,23 +62,8 @@ * selected. */ -#ifdef CONFIG_ARCH_STACKDUMP -# undef lldbg -# define lldbg lib_lowprintf -#endif - -/* The following is just intended to keep some ugliness out of the mainline - * code. We are going to print the task name if: - * - * CONFIG_TASK_NAME_SIZE > 0 && <-- The task has a name - * (defined(CONFIG_DEBUG) || <-- And the debug is enabled (lldbg used) - * defined(CONFIG_ARCH_STACKDUMP)) <-- Or lib_lowprintf() is used - */ - -#undef CONFIG_PRINT_TASKNAME -#if CONFIG_TASK_NAME_SIZE > 0 && (defined(CONFIG_DEBUG) || defined(CONFIG_ARCH_STACKDUMP)) -# define CONFIG_PRINT_TASKNAME 1 -#endif +#undef lldbg +#define lldbg lib_lowprintf /**************************************************************************** * Private Data @@ -107,7 +94,6 @@ static inline uint32_t up_getsp(void) * Name: up_stackdump ****************************************************************************/ -#ifdef CONFIG_ARCH_STACKDUMP static void up_stackdump(uint32_t sp, uint32_t stack_base) { uint32_t stack ; @@ -120,15 +106,11 @@ static void up_stackdump(uint32_t sp, uint32_t stack_base) ptr[4], ptr[5], ptr[6], ptr[7]); } } -#else -# define up_stackdump() -#endif /**************************************************************************** * Name: up_registerdump ****************************************************************************/ -#ifdef CONFIG_ARCH_STACKDUMP static inline void up_registerdump(void) { /* Are user registers available from interrupt processing? */ @@ -136,32 +118,32 @@ static inline void up_registerdump(void) if (current_regs) { lldbg("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n", - 0, - current_regs[REG_R0], current_regs[REG_R1], - current_regs[REG_R2], current_regs[REG_R3], - current_regs[REG_R4], current_regs[REG_R5], - current_regs[REG_R6], current_regs[REG_R7]); + 0, + current_regs[REG_R0], current_regs[REG_R1], + current_regs[REG_R2], current_regs[REG_R3], + current_regs[REG_R4], current_regs[REG_R5], + current_regs[REG_R6], current_regs[REG_R7]); lldbg("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n", - 8, - current_regs[REG_R8], current_regs[REG_R9], - current_regs[REG_R10], current_regs[REG_R11], - current_regs[REG_R12], current_regs[REG_R13], - current_regs[REG_R14], current_regs[REG_R15]); + 8, + current_regs[REG_R8], current_regs[REG_R9], + current_regs[REG_R10], current_regs[REG_R11], + current_regs[REG_R12], current_regs[REG_R13], + current_regs[REG_R14], current_regs[REG_R15]); lldbg("SR: %08x\n", current_regs[REG_SR]); } } -#else -# define up_registerdump() -#endif + +/**************************************************************************** + * Name: _up_assert + ****************************************************************************/ /**************************************************************************** * Name: up_dumpstate ****************************************************************************/ -#ifdef CONFIG_ARCH_STACKDUMP -static void up_dumpstate(void) +void up_dumpstate(void) { _TCB *rtcb = (_TCB*)g_readytorun.head; uint32_t sp = up_getsp(); @@ -255,82 +237,4 @@ static void up_dumpstate(void) up_registerdump(); } -#else -# define up_dumpstate() -#endif - -/**************************************************************************** - * Name: _up_assert - ****************************************************************************/ - -static void _up_assert(int errorcode) /* __attribute__ ((noreturn)) */ -{ - /* Are we in an interrupt handler or the idle task? */ - - if (current_regs || ((_TCB*)g_readytorun.head)->pid == 0) - { - (void)irqsave(); - for(;;) - { -#ifdef CONFIG_ARCH_LEDS - up_ledon(LED_PANIC); - up_mdelay(250); - up_ledoff(LED_PANIC); - up_mdelay(250); #endif - } - } - else - { - exit(errorcode); - } -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: up_assert - ****************************************************************************/ - -void up_assert(const uint8_t *filename, int lineno) -{ -#ifdef CONFIG_PRINT_TASKNAME - _TCB *rtcb = (_TCB*)g_readytorun.head; -#endif - - up_ledon(LED_ASSERTION); -#ifdef CONFIG_PRINT_TASKNAME - lldbg("Assertion failed at file:%s line: %d task: %s\n", - filename, lineno, rtcb->name); -#else - lldbg("Assertion failed at file:%s line: %d\n", - filename, lineno); -#endif - up_dumpstate(); - _up_assert(EXIT_FAILURE); -} - -/**************************************************************************** - * Name: up_assert_code - ****************************************************************************/ - -void up_assert_code(const uint8_t *filename, int lineno, int errorcode) -{ -#ifdef CONFIG_PRINT_TASKNAME - _TCB *rtcb = (_TCB*)g_readytorun.head; -#endif - - up_ledon(LED_ASSERTION); -#ifdef CONFIG_PRINT_TASKNAME - lldbg("Assertion failed at file:%s line: %d task: %s error code: %d\n", - filename, lineno, rtcb->name, errorcode); -#else - lldbg("Assertion failed at file:%s line: %d error code: %d\n", - filename, lineno, errorcode); -#endif - up_dumpstate(); - _up_assert(errorcode); -} - diff --git a/nuttx/arch/avr/src/common/up_internal.h b/nuttx/arch/avr/src/common/up_internal.h index c388b6153..e65b5627d 100644 --- a/nuttx/arch/avr/src/common/up_internal.h +++ b/nuttx/arch/avr/src/common/up_internal.h @@ -136,6 +136,7 @@ extern int up_timerisr(int irq, uint32_t *regs); extern void up_lowputc(char ch); extern void up_puts(const char *str); extern void up_lowputs(const char *str); +extern void up_dumpstate(void); /* Defined in common/up_allocateheap.c or chip/xxx_allocateheap.c */ |