Nut/OS  4.10.3
API Reference
irqstack.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  */
00033 
00034 /*
00035  * $Log$
00036  * Revision 1.2  2008/08/11 06:59:17  haraldkipp
00037  * BSD types replaced by stdint types (feature request #1282721).
00038  *
00039  * Revision 1.1  2005/09/17 09:20:11  drsung
00040  * Moved from /dev
00041  *
00042  * Revision 1.7  2004/09/22 08:15:57  haraldkipp
00043  * Speparate IRQ stack configurable
00044  *
00045  * Revision 1.6  2004/04/25 17:05:56  drsung
00046  * Separate IRQ stack now compatible with nested interrupts.
00047  *
00048  * Revision 1.5  2004/02/03 11:28:40  drsung
00049  * Modified to support different target platforms.
00050  *
00051  * Revision 1.4  2004/02/02 15:35:31  drsung
00052  * Bloody 'no new line at end of file' error fixed... Grrrr..
00053  *
00054  * Revision 1.3  2004/02/01 10:47:51  drsung
00055  * #ifdef .. #endif inserted, to make iccavr compile.
00056  *
00057  * Revision 1.2  2004/01/31 13:59:14  drsung
00058  * Stupid attributes removed.
00059  *
00060  * Revision 1.1  2004/01/30 17:02:20  drsung
00061  * Separate interrupt stack for avr-gcc only added.
00062  *
00063  */
00064 
00065 #include <dev/irqreg.h>
00066 
00067 #ifdef IRQSTACK_SIZE
00068 
00069 static struct
00070 {
00071         uint8_t _nesting;
00072         uint8_t _temp;
00073         uint8_t _SPL;
00074         uint8_t _SPH;
00075         uint8_t _stack[IRQSTACK_SIZE];
00076 } _irq_stack; //__attribute__((section(".data.irqstack")));
00077 
00078 
00079 void _irq_interrupt (IRQ_HANDLER * irh) __attribute__ ((naked));
00080 void _irq_interrupt (IRQ_HANDLER * irh)
00081 {
00082     asm volatile ("sts %1, r24" "\n\t"
00083                   "lds r24, %2" "\n\t"          /* load _irq_nesting in r24 */
00084                   "tst r24" "\n\t"                              /* test for zero */
00085                   "brne L_%=" "\n\t"                    /* jump to no_switch1 if not zero */
00086                   "in r24, __SP_L__" "\n\t"                     /* load SP_L into r24 */ 
00087                   "sts %3, r24" "\n\t"                  /* and save it to _irq_SPL */ 
00088                   "in r24, __SP_H__" "\n\t"                     /* load SP_H into r24 */ 
00089                   "sts %4, r24" "\n\t"                  /* and save it to _irq_SPH */ 
00090                   "ldi r24, lo8(%0)" "\n\t"                     /* load lo addr of begin of irqstack to r24 */ 
00091                   "out __SP_L__, r24" "\n\t"                    /* write it to SP_L */ 
00092                   "ldi r24, hi8(%0)" "\n\t"                     /* load hi addr of begin of irqstack to r24 */ 
00093                   "out __SP_H__, r24" "\n\t"                    /* write it to SP_H */ 
00094                   "lds r24, %2" "\n\t"          /* load _irq_nesting to r24 */
00095                   "L_%=:" "\n\t"                                /* jump label */
00096                   "inc r24" "\n\t"                              /* increment r24 */
00097                   "sts %2, r24" "\n\t"          /* save it back to _irq_nesting */
00098                   ::                                    
00099                   "i" (_irq_stack._stack + IRQSTACK_SIZE - 1), 
00100                   "i" (&_irq_stack._temp),
00101                   "i" (&_irq_stack._nesting),
00102                   "i" (&_irq_stack._SPL),
00103                   "i" (&_irq_stack._SPH));
00104     asm volatile ("push __tmp_reg__" "\n\t"     
00105                   "push __zero_reg__" "\n\t"    
00106                   "clr __zero_reg__" "\n\t"     
00107                   "push r18" "\n\t"             
00108                   "push r19" "\n\t"             
00109                   "push r20" "\n\t"             
00110                   "push r21" "\n\t"             
00111                   "push r22" "\n\t"             
00112                   "push r23" "\n\t"             
00113                   "push r26" "\n\t"             
00114                   "push r27" "\n\t"             
00115                   "push r30" "\n\t"             
00116                   "push r31" "\n\t"::);
00117     asm volatile ("lds r24, %0" "\n\t"
00118                   "call CallHandler" "\n\t"::
00119                   "i" (&_irq_stack._temp));
00120     asm volatile ("pop r31" "\n\t"              
00121                   "pop r30" "\n\t"              
00122                   "pop r27" "\n\t"              
00123                   "pop r26" "\n\t"              
00124                   "pop r23" "\n\t"              
00125                   "pop r22" "\n\t"              
00126                   "pop r21" "\n\t"              
00127                   "pop r20" "\n\t"              
00128                   "pop r19" "\n\t"              
00129                   "pop r18" "\n\t"              
00130                   "pop __zero_reg__" "\n\t"
00131                   "pop __tmp_reg__" "\n\t"::);
00132     asm volatile ("cli" "\n\t"                                  /* disable interrupts */ 
00133                   "lds r24, %0" "\n\t"          /* load _irq_nesting in r24 */ 
00134                   "dec r24" "\n\t"                              /* decrement r24 */ 
00135                   "sts %0, r24" "\n\t"          /* save it back to _irq_nesting */ 
00136                   "brne L_%=" "\n\t"                    /* jump to no_switch2 if not zero */ 
00137                   "lds r24, %1" "\n\t"                  /* load _irq_SPL to r24 */ 
00138                   "out __SP_L__, r24" "\n\t"                    /* write it to SP_L */ 
00139                   "lds r24, %2" "\n\t"                  /* load _irq_SPH to r24 */ 
00140                   "out __SP_H__, r24" "\n\t"                    /* write it to SP_H */ 
00141                   "L_%=:" "\n\t"::                              /* jump label */ 
00142                   "i" (&_irq_stack._nesting),
00143                   "i" (&_irq_stack._SPL),
00144                   "i" (&_irq_stack._SPH));                              
00145     _irq_epilog
00146     asm volatile ("reti"::);                            /* will enable interrupts */ 
00147 }
00148 
00149 
00150 #endif /* #ifdef IRQSTACK_SIZE */