summaryrefslogtreecommitdiff
path: root/nuttx/arch/avr
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-06-08 18:10:55 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-06-08 18:10:55 +0000
commitc626aec4434149e17e4cd98174e59095a3a06e05 (patch)
tree7c1b6cbe99bb7af241fce8d7455181d9c025b73c /nuttx/arch/avr
parent583f057b1912513fce544714949e29fbe8bdf253 (diff)
downloadpx4-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')
-rw-r--r--nuttx/arch/avr/include/avr/irq.h12
-rw-r--r--nuttx/arch/avr/src/at32uc3/Make.defs6
-rw-r--r--nuttx/arch/avr/src/at90usb/Make.defs18
-rwxr-xr-xnuttx/arch/avr/src/at90usb/at90usb_exceptions.S58
-rwxr-xr-xnuttx/arch/avr/src/at90usb/at90usb_head.S6
-rw-r--r--nuttx/arch/avr/src/atmega/Make.defs16
-rwxr-xr-xnuttx/arch/avr/src/atmega/atmega_head.S7
-rw-r--r--nuttx/arch/avr/src/avr/avr_internal.h2
-rwxr-xr-xnuttx/arch/avr/src/avr/excptmacros.h161
-rwxr-xr-xnuttx/arch/avr/src/avr/up_blocktask.c168
-rw-r--r--nuttx/arch/avr/src/avr/up_doirq.c116
-rw-r--r--nuttx/arch/avr/src/avr/up_dumpstate.c263
-rwxr-xr-xnuttx/arch/avr/src/avr/up_releasepending.c131
-rwxr-xr-xnuttx/arch/avr/src/avr/up_reprioritizertr.c182
-rw-r--r--nuttx/arch/avr/src/avr/up_schedulesigaction.c209
-rw-r--r--nuttx/arch/avr/src/avr/up_sigdeliver.c154
-rwxr-xr-xnuttx/arch/avr/src/avr/up_switchcontext.S4
-rwxr-xr-xnuttx/arch/avr/src/avr/up_unblocktask.c158
-rw-r--r--nuttx/arch/avr/src/avr32/up_dumpstate.c (renamed from nuttx/arch/avr/src/avr32/up_assert.c)138
-rw-r--r--nuttx/arch/avr/src/common/up_internal.h1
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 */