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: irqstack.c,v $
00036  * Revision 1.1  2005/09/17 09:20:11  drsung
00037  * Moved from /dev
00038  *
00039  * Revision 1.7  2004/09/22 08:15:57  haraldkipp
00040  * Speparate IRQ stack configurable
00041  *
00042  * Revision 1.6  2004/04/25 17:05:56  drsung
00043  * Separate IRQ stack now compatible with nested interrupts.
00044  *
00045  * Revision 1.5  2004/02/03 11:28:40  drsung
00046  * Modified to support different target platforms.
00047  *
00048  * Revision 1.4  2004/02/02 15:35:31  drsung
00049  * Bloody 'no new line at end of file' error fixed... Grrrr..
00050  *
00051  * Revision 1.3  2004/02/01 10:47:51  drsung
00052  * #ifdef .. #endif inserted, to make iccavr compile.
00053  *
00054  * Revision 1.2  2004/01/31 13:59:14  drsung
00055  * Stupid attributes removed.
00056  *
00057  * Revision 1.1  2004/01/30 17:02:20  drsung
00058  * Separate interrupt stack for avr-gcc only added.
00059  *
00060  */
00061 
00062 #include <dev/irqreg.h>
00063 
00064 #ifdef IRQSTACK_SIZE
00065 
00066 static struct
00067 {
00068     u_char _nesting;
00069     u_char _temp;
00070     u_char _SPL;
00071     u_char _SPH;
00072     u_char _stack[IRQSTACK_SIZE];
00073 } _irq_stack; //__attribute__((section(".data.irqstack")));
00074 
00075 
00076 void _irq_interrupt (IRQ_HANDLER * irh) __attribute__ ((naked));
00077 void _irq_interrupt (IRQ_HANDLER * irh)
00078 {
00079     asm volatile ("sts %1, r24" "\n\t"
00080                   "lds r24, %2" "\n\t"      /* load _irq_nesting in r24 */
00081                   "tst r24" "\n\t"              /* test for zero */
00082                   "brne L_%=" "\n\t"            /* jump to no_switch1 if not zero */
00083                   "in r24, __SP_L__" "\n\t"         /* load SP_L into r24 */ 
00084                   "sts %3, r24" "\n\t"          /* and save it to _irq_SPL */ 
00085                   "in r24, __SP_H__" "\n\t"         /* load SP_H into r24 */ 
00086                   "sts %4, r24" "\n\t"          /* and save it to _irq_SPH */ 
00087                   "ldi r24, lo8(%0)" "\n\t"         /* load lo addr of begin of irqstack to r24 */ 
00088                   "out __SP_L__, r24" "\n\t"            /* write it to SP_L */ 
00089                   "ldi r24, hi8(%0)" "\n\t"         /* load hi addr of begin of irqstack to r24 */ 
00090                   "out __SP_H__, r24" "\n\t"            /* write it to SP_H */ 
00091                   "lds r24, %2" "\n\t"      /* load _irq_nesting to r24 */
00092                   "L_%=:" "\n\t"                /* jump label */
00093                   "inc r24" "\n\t"              /* increment r24 */
00094                   "sts %2, r24" "\n\t"      /* save it back to _irq_nesting */
00095                   ::                    
00096                   "i" (_irq_stack._stack + IRQSTACK_SIZE - 1), 
00097                   "i" (&_irq_stack._temp),
00098                   "i" (&_irq_stack._nesting),
00099                   "i" (&_irq_stack._SPL),
00100                   "i" (&_irq_stack._SPH));
00101     asm volatile ("push __tmp_reg__" "\n\t" 
00102                   "push __zero_reg__" "\n\t"    
00103                   "clr __zero_reg__" "\n\t" 
00104                   "push r18" "\n\t"     
00105                   "push r19" "\n\t"     
00106                   "push r20" "\n\t"     
00107                   "push r21" "\n\t"     
00108                   "push r22" "\n\t"     
00109                   "push r23" "\n\t"     
00110                   "push r26" "\n\t"     
00111                   "push r27" "\n\t"     
00112                   "push r30" "\n\t"     
00113                   "push r31" "\n\t"::);
00114     asm volatile ("lds r24, %0" "\n\t"
00115                   "call CallHandler" "\n\t"::
00116                   "i" (&_irq_stack._temp));
00117     asm volatile ("pop r31" "\n\t"      
00118                   "pop r30" "\n\t"      
00119                   "pop r27" "\n\t"      
00120                   "pop r26" "\n\t"      
00121                   "pop r23" "\n\t"      
00122                   "pop r22" "\n\t"      
00123                   "pop r21" "\n\t"      
00124                   "pop r20" "\n\t"      
00125                   "pop r19" "\n\t"      
00126                   "pop r18" "\n\t"      
00127                   "pop __zero_reg__" "\n\t"
00128                   "pop __tmp_reg__" "\n\t"::);
00129     asm volatile ("cli" "\n\t"                  /* disable interrupts */ 
00130                   "lds r24, %0" "\n\t"      /* load _irq_nesting in r24 */ 
00131                   "dec r24" "\n\t"              /* decrement r24 */ 
00132                   "sts %0, r24" "\n\t"      /* save it back to _irq_nesting */ 
00133                   "brne L_%=" "\n\t"            /* jump to no_switch2 if not zero */ 
00134                   "lds r24, %1" "\n\t"          /* load _irq_SPL to r24 */ 
00135                   "out __SP_L__, r24" "\n\t"            /* write it to SP_L */ 
00136                   "lds r24, %2" "\n\t"          /* load _irq_SPH to r24 */ 
00137                   "out __SP_H__, r24" "\n\t"            /* write it to SP_H */ 
00138                   "L_%=:" "\n\t"::              /* jump label */ 
00139                   "i" (&_irq_stack._nesting),
00140                   "i" (&_irq_stack._SPL),
00141                   "i" (&_irq_stack._SPH));              
00142     _irq_epilog
00143     asm volatile ("reti"::);                /* will enable interrupts */ 
00144 }
00145 
00146 
00147 #endif /* #ifdef IRQSTACK_SIZE */

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/