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 */