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