+++ /dev/null
-/*This file is prepared for Doxygen automatic documentation generation.*/\r
-/*! \file *********************************************************************\r
- *\r
- * \brief Exception and interrupt vectors.\r
- *\r
- * This file maps all events supported by an AVR32UC.\r
- *\r
- * - Compiler: GNU GCC for AVR32\r
- * - Supported devices: All AVR32UC devices with an INTC module can be used.\r
- * - AppNote:\r
- *\r
- * \author Atmel Corporation: http://www.atmel.com \n\r
- * Support and FAQ: http://support.atmel.no/\r
- *\r
- ******************************************************************************/\r
-\r
-/* Copyright (c) 2007, Atmel Corporation All rights reserved.\r
- *\r
- * Redistribution and use in source and binary forms, with or without\r
- * modification, are permitted provided that the following conditions are met:\r
- *\r
- * 1. Redistributions of source code must retain the above copyright notice,\r
- * this list of conditions and the following disclaimer.\r
- *\r
- * 2. Redistributions in binary form must reproduce the above copyright notice,\r
- * this list of conditions and the following disclaimer in the documentation\r
- * and/or other materials provided with the distribution.\r
- *\r
- * 3. The name of ATMEL may not be used to endorse or promote products derived\r
- * from this software without specific prior written permission.\r
- *\r
- * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND\r
- * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,\r
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
- */\r
-\r
-\r
-#include <avr32/io.h>\r
-#include "intc.h"\r
-\r
-\r
-//! @{\r
-//! \verbatim\r
-\r
-\r
- .section .exception, "ax", @progbits\r
-\r
-\r
-// Start of Exception Vector Table.\r
-\r
- // EVBA must be aligned with a power of two strictly greater than the EVBA-\r
- // relative offset of the last vector.\r
- .balign 0x200\r
-\r
- // Export symbol.\r
- .global _evba\r
- .type _evba, @function\r
-_evba:\r
-\r
- .org 0x000\r
- // Unrecoverable Exception.\r
-_handle_Unrecoverable_Exception:\r
- rjmp $\r
-\r
- .org 0x004\r
- // TLB Multiple Hit: UNUSED IN AVR32UC.\r
-_handle_TLB_Multiple_Hit:\r
- rjmp $\r
-\r
- .org 0x008\r
- // Bus Error Data Fetch.\r
-_handle_Bus_Error_Data_Fetch:\r
- rjmp $\r
-\r
- .org 0x00C\r
- // Bus Error Instruction Fetch.\r
-_handle_Bus_Error_Instruction_Fetch:\r
- rjmp $\r
-\r
- .org 0x010\r
- // NMI.\r
-_handle_NMI:\r
- rjmp $\r
-\r
- .org 0x014\r
- // Instruction Address.\r
-_handle_Instruction_Address:\r
- rjmp $\r
-\r
- .org 0x018\r
- // ITLB Protection.\r
-_handle_ITLB_Protection:\r
- rjmp $\r
-\r
- .org 0x01C\r
- // Breakpoint.\r
-_handle_Breakpoint:\r
- rjmp $\r
-\r
- .org 0x020\r
- // Illegal Opcode.\r
-_handle_Illegal_Opcode:\r
- rjmp $\r
-\r
- .org 0x024\r
- // Unimplemented Instruction.\r
-_handle_Unimplemented_Instruction:\r
- rjmp $\r
-\r
- .org 0x028\r
- // Privilege Violation.\r
-_handle_Privilege_Violation:\r
- rjmp $\r
-\r
- .org 0x02C\r
- // Floating-Point: UNUSED IN AVR32UC.\r
-_handle_Floating_Point:\r
- rjmp $\r
-\r
- .org 0x030\r
- // Coprocessor Absent: UNUSED IN AVR32UC.\r
-_handle_Coprocessor_Absent:\r
- rjmp $\r
-\r
- .org 0x034\r
- // Data Address (Read).\r
-_handle_Data_Address_Read:\r
- rjmp $\r
-\r
- .org 0x038\r
- // Data Address (Write).\r
-_handle_Data_Address_Write:\r
- rjmp $\r
-\r
- .org 0x03C\r
- // DTLB Protection (Read).\r
-_handle_DTLB_Protection_Read:\r
- rjmp $\r
-\r
- .org 0x040\r
- // DTLB Protection (Write).\r
-_handle_DTLB_Protection_Write:\r
- rjmp $\r
-\r
- .org 0x044\r
- // DTLB Modified: UNUSED IN AVR32UC.\r
-_handle_DTLB_Modified:\r
- rjmp $\r
-\r
- .org 0x050\r
- // ITLB Miss: UNUSED IN AVR32UC.\r
-_handle_ITLB_Miss:\r
- rjmp $\r
-\r
- .org 0x060\r
- // DTLB Miss (Read): UNUSED IN AVR32UC.\r
-_handle_DTLB_Miss_Read:\r
- rjmp $\r
-\r
- .org 0x070\r
- // DTLB Miss (Write): UNUSED IN AVR32UC.\r
-_handle_DTLB_Miss_Write:\r
- rjmp $\r
-\r
- .org 0x100\r
- // Supervisor Call.\r
-_handle_Supervisor_Call:\r
- lda.w pc, SCALLYield\r
-\r
-\r
-// Interrupt support.\r
-// The interrupt controller must provide the offset address relative to EVBA.\r
-// Important note:\r
-// All interrupts call a C function named _get_interrupt_handler.\r
-// This function will read group and interrupt line number to then return in\r
-// R12 a pointer to a user-provided interrupt handler.\r
-\r
- .balign 4\r
-\r
-_int0:\r
- // R8-R12, LR, PC and SR are automatically pushed onto the system stack by the\r
- // CPU upon interrupt entry.\r
-#if 1 // B1832: interrupt stack changed to exception stack if exception is detected.\r
- mfsr r12, AVR32_SR\r
- bfextu r12, r12, AVR32_SR_M0_OFFSET, AVR32_SR_M0_SIZE + AVR32_SR_M1_SIZE + AVR32_SR_M2_SIZE\r
- cp.w r12, 0b110\r
- brlo _int0_normal\r
- lddsp r12, sp[0 * 4]\r
- stdsp sp[6 * 4], r12\r
- lddsp r12, sp[1 * 4]\r
- stdsp sp[7 * 4], r12\r
- lddsp r12, sp[3 * 4]\r
- sub sp, -6 * 4\r
- rete\r
-_int0_normal:\r
-#endif\r
- mov r12, 0 // Pass the int_lev parameter to the _get_interrupt_handler function.\r
- call _get_interrupt_handler\r
- cp.w r12, 0 // Get the pointer to the interrupt handler returned by the function.\r
- movne pc, r12 // If this was not a spurious interrupt (R12 != NULL), jump to the handler.\r
- rete // If this was a spurious interrupt (R12 == NULL), return from event handler.\r
-\r
-_int1:\r
- // R8-R12, LR, PC and SR are automatically pushed onto the system stack by the\r
- // CPU upon interrupt entry.\r
-#if 1 // B1832: interrupt stack changed to exception stack if exception is detected.\r
- mfsr r12, AVR32_SR\r
- bfextu r12, r12, AVR32_SR_M0_OFFSET, AVR32_SR_M0_SIZE + AVR32_SR_M1_SIZE + AVR32_SR_M2_SIZE\r
- cp.w r12, 0b110\r
- brlo _int1_normal\r
- lddsp r12, sp[0 * 4]\r
- stdsp sp[6 * 4], r12\r
- lddsp r12, sp[1 * 4]\r
- stdsp sp[7 * 4], r12\r
- lddsp r12, sp[3 * 4]\r
- sub sp, -6 * 4\r
- rete\r
-_int1_normal:\r
-#endif\r
- mov r12, 1 // Pass the int_lev parameter to the _get_interrupt_handler function.\r
- call _get_interrupt_handler\r
- cp.w r12, 0 // Get the pointer to the interrupt handler returned by the function.\r
- movne pc, r12 // If this was not a spurious interrupt (R12 != NULL), jump to the handler.\r
- rete // If this was a spurious interrupt (R12 == NULL), return from event handler.\r
-\r
-_int2:\r
- // R8-R12, LR, PC and SR are automatically pushed onto the system stack by the\r
- // CPU upon interrupt entry.\r
-#if 1 // B1832: interrupt stack changed to exception stack if exception is detected.\r
- mfsr r12, AVR32_SR\r
- bfextu r12, r12, AVR32_SR_M0_OFFSET, AVR32_SR_M0_SIZE + AVR32_SR_M1_SIZE + AVR32_SR_M2_SIZE\r
- cp.w r12, 0b110\r
- brlo _int2_normal\r
- lddsp r12, sp[0 * 4]\r
- stdsp sp[6 * 4], r12\r
- lddsp r12, sp[1 * 4]\r
- stdsp sp[7 * 4], r12\r
- lddsp r12, sp[3 * 4]\r
- sub sp, -6 * 4\r
- rete\r
-_int2_normal:\r
-#endif\r
- mov r12, 2 // Pass the int_lev parameter to the _get_interrupt_handler function.\r
- call _get_interrupt_handler\r
- cp.w r12, 0 // Get the pointer to the interrupt handler returned by the function.\r
- movne pc, r12 // If this was not a spurious interrupt (R12 != NULL), jump to the handler.\r
- rete // If this was a spurious interrupt (R12 == NULL), return from event handler.\r
-\r
-_int3:\r
- // R8-R12, LR, PC and SR are automatically pushed onto the system stack by the\r
- // CPU upon interrupt entry.\r
-#if 1 // B1832: interrupt stack changed to exception stack if exception is detected.\r
- mfsr r12, AVR32_SR\r
- bfextu r12, r12, AVR32_SR_M0_OFFSET, AVR32_SR_M0_SIZE + AVR32_SR_M1_SIZE + AVR32_SR_M2_SIZE\r
- cp.w r12, 0b110\r
- brlo _int3_normal\r
- lddsp r12, sp[0 * 4]\r
- stdsp sp[6 * 4], r12\r
- lddsp r12, sp[1 * 4]\r
- stdsp sp[7 * 4], r12\r
- lddsp r12, sp[3 * 4]\r
- sub sp, -6 * 4\r
- rete\r
-_int3_normal:\r
-#endif\r
- mov r12, 3 // Pass the int_lev parameter to the _get_interrupt_handler function.\r
- call _get_interrupt_handler\r
- cp.w r12, 0 // Get the pointer to the interrupt handler returned by the function.\r
- movne pc, r12 // If this was not a spurious interrupt (R12 != NULL), jump to the handler.\r
- rete // If this was a spurious interrupt (R12 == NULL), return from event handler.\r
-\r
-\r
-// Constant data area.\r
-\r
- .balign 4\r
-\r
- // Values to store in the interrupt priority registers for the various interrupt priority levels.\r
- // The interrupt priority registers contain the interrupt priority level and\r
- // the EVBA-relative interrupt vector offset.\r
- .global ipr_val\r
- .type ipr_val, @object\r
-ipr_val:\r
- .word (INT0 << AVR32_INTC_IPR0_INTLEV_OFFSET) | (_int0 - _evba),\\r
- (INT1 << AVR32_INTC_IPR0_INTLEV_OFFSET) | (_int1 - _evba),\\r
- (INT2 << AVR32_INTC_IPR0_INTLEV_OFFSET) | (_int2 - _evba),\\r
- (INT3 << AVR32_INTC_IPR0_INTLEV_OFFSET) | (_int3 - _evba)\r
-\r
-\r
-//! \endverbatim\r
-//! @}\r
-/*This file has been prepared for Doxygen automatic documentation generation.*/\r
-/*! \file *********************************************************************\r
- *\r
- * \brief FreeRTOS port source for AVR32 UC3.\r
- *\r
- * - Compiler: GNU GCC for AVR32\r
- * - Supported devices: All AVR32 devices can be used.\r
- * - AppNote:\r
- *\r
- * \author Atmel Corporation: http://www.atmel.com \n\r
- * Support and FAQ: http://support.atmel.no/\r
- *\r
- *****************************************************************************/\r
-\r
/*\r
FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.\r
\r
licensing and training services.\r
*/\r
\r
-\r
/* Standard includes. */\r
-#include <sys/cpu.h>\r
-#include <sys/usart.h>\r
+\r
#include <malloc.h>\r
\r
/* Scheduler includes. */\r
/* AVR32 UC3 includes. */\r
#include <avr32/io.h>\r
#include "gpio.h"\r
-#if( configTICK_USE_TC==1 )\r
- #include "tc.h"\r
-#endif\r
-\r
+#include <nlao_cpu.h>\r
+#include <nlao_usart.h>\r
\r
/* Constants required to setup the task context. */\r
#define portINITIAL_SR ( ( portSTACK_TYPE ) 0x00400000 ) /* AVR32 : [M2:M0]=001 I1M=0 I0M=0, GM=0 */\r
#define portNO_CRITICAL_NESTING ( ( unsigned long ) 0 )\r
volatile unsigned long ulCriticalNesting = 9999UL;\r
\r
-#if( configTICK_USE_TC==0 )\r
- static void prvScheduleNextTick( void );\r
-#else\r
- static void prvClearTcInt( void );\r
-#endif\r
+/* Clear the COUNT&COMPARE match Interrupt Flag. */\r
+static void prvClearCcInt( void );\r
\r
/* Setup the timer to generate the tick interrupts. */\r
static void prvSetupTimerInterrupt( void );\r
\r
#endif\r
\r
- /* Give the used CPU clock frequency to Newlib, so it can work properly. */\r
- set_cpu_hz( configCPU_CLOCK_HZ );\r
+ /* Give the used PBA clock frequency to Newlib, so it can work properly. */\r
+ set_cpu_hz( configPBA_CLOCK_HZ );\r
\r
/* Code section present if and only if the debug trace is activated. */\r
#if configDBG\r
/*-----------------------------------------------------------*/\r
\r
/* The cooperative scheduler requires a normal IRQ service routine to\r
-simply increment the system tick. */\r
-/* The preemptive scheduler is defined as "naked" as the full context is saved\r
+simply increment the system tick.\r
+The preemptive scheduler is defined as "naked" as the full context is saved\r
on entry as part of the context switch. */\r
__attribute__((__naked__)) static void vTick( void )\r
{\r
/* Save the context of the interrupted task. */\r
portSAVE_CONTEXT_OS_INT();\r
\r
- #if( configTICK_USE_TC==1 )\r
- /* Clear the interrupt flag. */\r
- prvClearTcInt();\r
- #else\r
- /* Schedule the COUNT&COMPARE match interrupt in (configCPU_CLOCK_HZ/configTICK_RATE_HZ)\r
- clock cycles from now. */\r
- prvScheduleNextTick();\r
- #endif\r
+ /* Clear the interrupt flag. */\r
+ prvClearCcInt();\r
\r
/* Because FreeRTOS is not supposed to run with nested interrupts, put all OS\r
calls in a critical section . */\r
}\r
/*-----------------------------------------------------------*/\r
\r
+/* Note that the scall handler in the framework 'exception.x' must\r
+ * jump to this handler.\r
+ * In file: 'AVR32_UC3/Drivers/INTC/exception.x' replace the line after\r
+ * '_handle_Supervisor_Call:' which might be 'rjmp $'\r
+ * with the instruction:\r
+ * 'lda.w pc, SCALLYield'\r
+ */\r
__attribute__((__naked__)) void SCALLYield( void )\r
{\r
/* Save the context of the interrupted task. */\r
*pxTopOfStack-- = ( portSTACK_TYPE ) 0x04040404; /* R4 */\r
*pxTopOfStack-- = ( portSTACK_TYPE ) 0x05050505; /* R5 */\r
*pxTopOfStack-- = ( portSTACK_TYPE ) 0x06060606; /* R6 */\r
- *pxTopOfStack-- = ( portSTACK_TYPE ) 0x07070707; /* R7 */\r
+ *pxTopOfStack-- = ( portSTACK_TYPE ) 0x00000000; /* R7 aka Frame Pointer */\r
*pxTopOfStack = ( portSTACK_TYPE ) portNO_CRITICAL_NESTING; /* ulCriticalNesting */\r
\r
return pxTopOfStack;\r
\r
/* Schedule the COUNT&COMPARE match interrupt in (configCPU_CLOCK_HZ/configTICK_RATE_HZ)\r
clock cycles from now. */\r
-#if( configTICK_USE_TC==0 )\r
- static void prvScheduleFirstTick(void)\r
- {\r
- unsigned long lCycles;\r
-\r
- lCycles = Get_system_register(AVR32_COUNT);\r
- lCycles += (configCPU_CLOCK_HZ/configTICK_RATE_HZ);\r
- // If lCycles ends up to be 0, make it 1 so that the COMPARE and exception\r
- // generation feature does not get disabled.\r
- if(0 == lCycles)\r
- {\r
- lCycles++;\r
- }\r
- Set_system_register(AVR32_COMPARE, lCycles);\r
- }\r
- \r
- __attribute__((__noinline__)) static void prvScheduleNextTick(void)\r
- {\r
- unsigned long lCycles, lCount;\r
+static void prvScheduleFirstTick(void)\r
+{\r
+ Set_system_register(AVR32_COMPARE, configCPU_CLOCK_HZ/configTICK_RATE_HZ);\r
+ Set_system_register(AVR32_COUNT, 0);\r
+}\r
+/*-----------------------------------------------------------*/\r
\r
- lCycles = Get_system_register(AVR32_COMPARE);\r
- lCycles += (configCPU_CLOCK_HZ/configTICK_RATE_HZ);\r
- // If lCycles ends up to be 0, make it 1 so that the COMPARE and exception\r
- // generation feature does not get disabled.\r
- if(0 == lCycles)\r
- {\r
- lCycles++;\r
- }\r
- lCount = Get_system_register(AVR32_COUNT);\r
- if( lCycles < lCount )\r
- { // We missed a tick, recover for the next.\r
- lCycles += (configCPU_CLOCK_HZ/configTICK_RATE_HZ);\r
- }\r
- Set_system_register(AVR32_COMPARE, lCycles);\r
- }\r
-#else\r
- __attribute__((__noinline__)) static void prvClearTcInt(void)\r
- {\r
- AVR32_TC.channel[configTICK_TC_CHANNEL].sr;\r
- }\r
-#endif\r
+__attribute__((__noinline__)) static void prvClearCcInt(void)\r
+{\r
+ Set_system_register(AVR32_COMPARE, Get_system_register(AVR32_COMPARE));\r
+}\r
/*-----------------------------------------------------------*/\r
\r
/* Setup the timer to generate the tick interrupts. */\r
static void prvSetupTimerInterrupt(void)\r
{\r
-#if( configTICK_USE_TC==1 )\r
-\r
- volatile avr32_tc_t *tc = &AVR32_TC;\r
-\r
- // Options for waveform genration.\r
- tc_waveform_opt_t waveform_opt =\r
- {\r
- .channel = configTICK_TC_CHANNEL, /* Channel selection. */\r
-\r
- .bswtrg = TC_EVT_EFFECT_NOOP, /* Software trigger effect on TIOB. */\r
- .beevt = TC_EVT_EFFECT_NOOP, /* External event effect on TIOB. */\r
- .bcpc = TC_EVT_EFFECT_NOOP, /* RC compare effect on TIOB. */\r
- .bcpb = TC_EVT_EFFECT_NOOP, /* RB compare effect on TIOB. */\r
-\r
- .aswtrg = TC_EVT_EFFECT_NOOP, /* Software trigger effect on TIOA. */\r
- .aeevt = TC_EVT_EFFECT_NOOP, /* External event effect on TIOA. */\r
- .acpc = TC_EVT_EFFECT_NOOP, /* RC compare effect on TIOA: toggle. */\r
- .acpa = TC_EVT_EFFECT_NOOP, /* RA compare effect on TIOA: toggle (other possibilities are none, set and clear). */\r
-\r
- .wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER,/* Waveform selection: Up mode without automatic trigger on RC compare. */\r
- .enetrg = FALSE, /* External event trigger enable. */\r
- .eevt = 0, /* External event selection. */\r
- .eevtedg = TC_SEL_NO_EDGE, /* External event edge selection. */\r
- .cpcdis = FALSE, /* Counter disable when RC compare. */\r
- .cpcstop = FALSE, /* Counter clock stopped with RC compare. */\r
-\r
- .burst = FALSE, /* Burst signal selection. */\r
- .clki = FALSE, /* Clock inversion. */\r
- .tcclks = TC_CLOCK_SOURCE_TC2 /* Internal source clock 2. */\r
- };\r
-\r
- tc_interrupt_t tc_interrupt =\r
- {\r
- .etrgs=0,\r
- .ldrbs=0,\r
- .ldras=0,\r
- .cpcs =1,\r
- .cpbs =0,\r
- .cpas =0,\r
- .lovrs=0,\r
- .covfs=0,\r
- };\r
-\r
-#endif\r
-\r
/* Disable all interrupt/exception. */\r
portDISABLE_INTERRUPTS();\r
\r
/* Register the compare interrupt handler to the interrupt controller and\r
enable the compare interrupt. */\r
-\r
- #if( configTICK_USE_TC==1 )\r
- {\r
- INTC_register_interrupt(&vTick, configTICK_TC_IRQ, INT0);\r
-\r
- /* Initialize the timer/counter. */\r
- tc_init_waveform(tc, &waveform_opt);\r
-\r
- /* Set the compare triggers.\r
- Remember TC counter is 16-bits, so counting second is not possible!\r
- That's why we configure it to count ms. */\r
- tc_write_rc( tc, configTICK_TC_CHANNEL, ( configPBA_CLOCK_HZ / 4) / configTICK_RATE_HZ );\r
-\r
- tc_configure_interrupts( tc, configTICK_TC_CHANNEL, &tc_interrupt );\r
-\r
- /* Start the timer/counter. */\r
- tc_start(tc, configTICK_TC_CHANNEL);\r
- }\r
- #else\r
- {\r
- INTC_register_interrupt(&vTick, AVR32_CORE_COMPARE_IRQ, INT0);\r
- prvScheduleFirstTick();\r
- }\r
- #endif\r
+ INTC_register_interrupt(&vTick, AVR32_CORE_COMPARE_IRQ, AVR32_INTC_INT0);\r
+ prvScheduleFirstTick();\r
}\r
+/*-----------------------------------------------------------*/\r
-/*This file has been prepared for Doxygen automatic documentation generation.*/\r
-/*! \file *********************************************************************\r
- *\r
- * \brief FreeRTOS port source for AVR32 UC3.\r
- *\r
- * - Compiler: GNU GCC for AVR32\r
- * - Supported devices: All AVR32 devices can be used.\r
- * - AppNote:\r
- *\r
- * \author Atmel Corporation: http://www.atmel.com \n\r
- * Support and FAQ: http://support.atmel.no/\r
- *\r
- *****************************************************************************/\r
-\r
/*\r
FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.\r
\r
#define TASK_DELAY_S(x) ( (x)*1000 /portTICK_RATE_MS )\r
#define TASK_DELAY_MIN(x) ( (x)*60*1000/portTICK_RATE_MS )\r
\r
-#define configTICK_TC_IRQ ATPASTE2(AVR32_TC_IRQ, configTICK_TC_CHANNEL)\r
-\r
#if( configUSE_16_BIT_TICKS == 1 )\r
typedef unsigned portSHORT portTickType;\r
#define portMAX_DELAY ( portTickType ) 0xffff\r
"st.w r8[0], r0 \n\t"\\r
\\r
/* Restore R0..R7 */ \\r
- "ldm sp++, r0-r7 \n\t"\\r
+ "ldm sp++, r0-r7 \n\t"\\r
/* R0-R7 should not be used below this line */ \\r
/* Skip PC and SR (will do it at the end) */ \\r
"sub sp, -2*4 \n\t"\\r