+/*This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief FreeRTOS port header 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 email: avr32@atmel.com\r
+ *\r
+ *****************************************************************************/\r
+\r
+/*\r
+ FreeRTOS.org V4.2.0 - Copyright (C) 2003-2007 Richard Barry.\r
+\r
+ This file is part of the FreeRTOS.org distribution.\r
+\r
+ FreeRTOS.org is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+\r
+ FreeRTOS.org is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with FreeRTOS.org; if not, write to the Free Software\r
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+\r
+ A special exception to the GPL can be applied should you wish to distribute\r
+ a combined work that includes FreeRTOS.org, without being obliged to provide\r
+ the source code for any proprietary components. See the licensing section\r
+ of http://www.FreeRTOS.org for full details of how and when the exception\r
+ can be applied.\r
+\r
+ ***************************************************************************\r
+ See http://www.FreeRTOS.org for documentation, latest information, license\r
+ and contact details. Please ensure to read the configuration and relevant\r
+ port sections of the online documentation.\r
+ ***************************************************************************\r
+*/\r
+\r
+\r
+#ifndef PORTMACRO_H\r
+#define PORTMACRO_H\r
+\r
+/*-----------------------------------------------------------\r
+ * Port specific definitions.\r
+ *\r
+ * The settings in this file configure FreeRTOS correctly for the\r
+ * given hardware and compiler.\r
+ *\r
+ * These settings should not be altered.\r
+ *-----------------------------------------------------------\r
+ */\r
+#include <avr32/io.h>\r
+#include "intc.h"\r
+#include "compiler.h"\r
+\r
+\r
+/* Type definitions. */\r
+#define portCHAR char\r
+#define portFLOAT float\r
+#define portDOUBLE double\r
+#define portLONG long\r
+#define portSHORT short\r
+#define portSTACK_TYPE unsigned portLONG\r
+#define portBASE_TYPE portLONG\r
+\r
+#define TASK_DELAY_MS(x) ( (x) /portTICK_RATE_MS )\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
+#else\r
+ typedef unsigned portLONG portTickType;\r
+ #define portMAX_DELAY ( portTickType ) 0xffffffff\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Architecture specifics. */\r
+#define portSTACK_GROWTH ( -1 )\r
+#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ )\r
+#define portBYTE_ALIGNMENT 4\r
+#define portNOP() {__asm__ __volatile__ ("nop");}\r
+/*-----------------------------------------------------------*/\r
+\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* INTC-specific. */\r
+#define DISABLE_ALL_EXCEPTIONS() Disable_global_exception()\r
+#define ENABLE_ALL_EXCEPTIONS() Enable_global_exception()\r
+\r
+#define DISABLE_ALL_INTERRUPTS() Disable_global_interrupt()\r
+#define ENABLE_ALL_INTERRUPTS() Enable_global_interrupt()\r
+\r
+#define DISABLE_INT_LEVEL(int_lev) Disable_interrupt_level(int_lev)\r
+#define ENABLE_INT_LEVEL(int_lev) Enable_interrupt_level(int_lev)\r
+\r
+\r
+/*\r
+ * Debug trace.\r
+ * Activated if and only if configDBG is nonzero.\r
+ * Prints a formatted string to stdout.\r
+ * The current source file name and line number are output with a colon before\r
+ * the formatted string.\r
+ * A carriage return and a linefeed are appended to the output.\r
+ * stdout is redirected by Newlib to the USART configured by configDBG_USART.\r
+ * The parameters are the same as for the standard printf function.\r
+ * There is no return value.\r
+ * SHALL NOT BE CALLED FROM WITHIN AN INTERRUPT as fputs and printf use malloc,\r
+ * which is interrupt-unsafe with the current __malloc_lock and __malloc_unlock.\r
+ */\r
+#if configDBG\r
+#define portDBG_TRACE(...) \\r
+{\\r
+ fputs(__FILE__ ":" ASTRINGZ(__LINE__) ": ", stdout);\\r
+ printf(__VA_ARGS__);\\r
+ fputs("\r\n", stdout);\\r
+}\r
+#else\r
+#define portDBG_TRACE(...)\r
+#endif\r
+\r
+\r
+/* Critical section management. */\r
+#define portDISABLE_INTERRUPTS() DISABLE_ALL_INTERRUPTS()\r
+#define portENABLE_INTERRUPTS() ENABLE_ALL_INTERRUPTS()\r
+\r
+\r
+extern void vPortEnterCritical( void );\r
+extern void vPortExitCritical( void );\r
+\r
+#define portENTER_CRITICAL() vPortEnterCritical();\r
+#define portEXIT_CRITICAL() vPortExitCritical();\r
+\r
+\r
+/* Added as there is no such function in FreeRTOS. */\r
+extern void *pvPortRealloc( void *pv, size_t xSize );\r
+/*-----------------------------------------------------------*/\r
+\r
+\r
+/*=============================================================================================*/\r
+\r
+/*\r
+ * Restore Context for cases other than INTi.\r
+ */\r
+#define portRESTORE_CONTEXT() \\r
+{ \\r
+ extern volatile unsigned portLONG ulCriticalNesting; \\r
+ extern volatile void *volatile pxCurrentTCB; \\r
+ \\r
+ __asm__ __volatile__ ( \\r
+ /* Set SP to point to new stack */ \\r
+ "mov r8, LO(%[pxCurrentTCB]) \n\t"\\r
+ "orh r8, HI(%[pxCurrentTCB]) \n\t"\\r
+ "ld.w r0, r8[0] \n\t"\\r
+ "ld.w sp, r0[0] \n\t"\\r
+ \\r
+ /* Restore ulCriticalNesting variable */ \\r
+ "ld.w r0, sp++ \n\t"\\r
+ "mov r8, LO(%[ulCriticalNesting]) \n\t"\\r
+ "orh r8, HI(%[ulCriticalNesting]) \n\t"\\r
+ "st.w r8[0], r0 \n\t"\\r
+ \\r
+ /* Restore R0..R7 */ \\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
+ /* Restore R8..R12 and LR */ \\r
+ "ldm sp++, r8-r12, lr \n\t"\\r
+ /* Restore SR */ \\r
+ "ld.w r0, sp[-8*4]\n\t" /* R0 is modified, is restored later. */ \\r
+ "mtsr %[SR], r0 \n\t"\\r
+ /* Restore r0 */ \\r
+ "ld.w r0, sp[-9*4] \n\t"\\r
+ /* Restore PC */ \\r
+ "ld.w pc, sp[-7*4]" /* Get PC from stack - PC is the 7th register saved */ \\r
+ : \\r
+ : [ulCriticalNesting] "i" (&ulCriticalNesting), \\r
+ [pxCurrentTCB] "i" (&pxCurrentTCB), \\r
+ [SR] "i" (AVR32_SR) \\r
+ ); \\r
+}\r
+\r
+\r
+/*\r
+ * portSAVE_CONTEXT_INT() and portRESTORE_CONTEXT_INT(): for INT0..3 exceptions.\r
+ * portSAVE_CONTEXT_SCALL() and portRESTORE_CONTEXT_SCALL(): for the scall exception.\r
+ *\r
+ * Had to make different versions because registers saved on the system stack\r
+ * are not the same between INT0..3 exceptions and the scall exception.\r
+ */\r
+\r
+// Task context stack layout:\r
+ // R8 (*)\r
+ // R9 (*)\r
+ // R10 (*)\r
+ // R11 (*)\r
+ // R12 (*)\r
+ // R14/LR (*)\r
+ // R15/PC (*)\r
+ // SR (*)\r
+ // R0\r
+ // R1\r
+ // R2\r
+ // R3\r
+ // R4\r
+ // R5\r
+ // R6\r
+ // R7\r
+ // ulCriticalNesting\r
+// (*) automatically done for INT0..INT3, but not for SCALL\r
+\r
+/*\r
+ * The ISR used for the scheduler tick depends on whether the cooperative or\r
+ * the preemptive scheduler is being used.\r
+ */\r
+#if configUSE_PREEMPTION == 0\r
+\r
+/*\r
+ * portSAVE_CONTEXT_OS_INT() for OS Tick exception.\r
+ */\r
+#define portSAVE_CONTEXT_OS_INT() \\r
+{ \\r
+ /* Save R0..R7 */ \\r
+ __asm__ __volatile__ ("stm --sp, r0-r7"); \\r
+ \\r
+ /* With the cooperative scheduler, as there is no context switch by interrupt, */ \\r
+ /* there is also no context save. */ \\r
+}\r
+\r
+/*\r
+ * portRESTORE_CONTEXT_OS_INT() for Tick exception.\r
+ */\r
+#define portRESTORE_CONTEXT_OS_INT() \\r
+{ \\r
+ __asm__ __volatile__ ( \\r
+ /* Restore R0..R7 */ \\r
+ "ldm sp++, r0-r7\n\t" \\r
+ \\r
+ /* With the cooperative scheduler, as there is no context switch by interrupt, */ \\r
+ /* there is also no context restore. */ \\r
+ "rete" \\r
+ ); \\r
+}\r
+\r
+#else\r
+\r
+/*\r
+ * portSAVE_CONTEXT_OS_INT() for OS Tick exception.\r
+ */\r
+#define portSAVE_CONTEXT_OS_INT() \\r
+{ \\r
+ extern volatile unsigned portLONG ulCriticalNesting; \\r
+ extern volatile void *volatile pxCurrentTCB; \\r
+ \\r
+ /* When we come here */ \\r
+ /* Registers R8..R12, LR, PC and SR had already been pushed to system stack */ \\r
+ \\r
+ __asm__ __volatile__ ( \\r
+ /* Save R0..R7 */ \\r
+ "stm --sp, r0-r7 \n\t"\\r
+ \\r
+ /* Save ulCriticalNesting variable - R0 is overwritten */ \\r
+ "mov r8, LO(%[ulCriticalNesting])\n\t" \\r
+ "orh r8, HI(%[ulCriticalNesting])\n\t" \\r
+ "ld.w r0, r8[0] \n\t"\\r
+ "st.w --sp, r0 \n\t"\\r
+ \\r
+ /* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \\r
+ /* interrupt handler (which was of a higher priority level but decided to lower its priority */ \\r
+ /* level and allow other lower interrupt level to occur). */ \\r
+ /* In this case we don't want to do a task switch because we don't know what the stack */ \\r
+ /* currently looks like (we don't know what the interrupted interrupt handler was doing). */ \\r
+ /* Saving SP in pxCurrentTCB and then later restoring it (thinking restoring the task) */ \\r
+ /* will just be restoring the interrupt handler, no way!!! */ \\r
+ /* So, since we won't do a vTaskSwitchContext(), it's of no use to save SP. */ \\r
+ "ld.w r0, sp[9*4]\n\t" /* Read SR in stack */ \\r
+ "bfextu r0, r0, 22, 3\n\t" /* Extract the mode bits to R0. */ \\r
+ "cp.w r0, 1\n\t" /* Compare the mode bits with supervisor mode(b'001) */ \\r
+ "brhi LABEL_INT_SKIP_SAVE_CONTEXT_%[LINE] \n\t"\\r
+ \\r
+ /* Store SP in the first member of the structure pointed to by pxCurrentTCB */ \\r
+ /* NOTE: we don't enter a critical section here because all interrupt handlers */ \\r
+ /* MUST perform a SAVE_CONTEXT/RESTORE_CONTEXT in the same way as */ \\r
+ /* portSAVE_CONTEXT_OS_INT/port_RESTORE_CONTEXT_OS_INT if they call OS functions. */ \\r
+ /* => all interrupt handlers must use portENTER_SWITCHING_ISR/portEXIT_SWITCHING_ISR. */ \\r
+ "mov r8, LO(%[pxCurrentTCB])\n\t" \\r
+ "orh r8, HI(%[pxCurrentTCB])\n\t" \\r
+ "ld.w r0, r8[0]\n\t" \\r
+ "st.w r0[0], sp\n" \\r
+ \\r
+ "LABEL_INT_SKIP_SAVE_CONTEXT_%[LINE]:" \\r
+ : \\r
+ : [ulCriticalNesting] "i" (&ulCriticalNesting), \\r
+ [pxCurrentTCB] "i" (&pxCurrentTCB), \\r
+ [LINE] "i" (__LINE__) \\r
+ ); \\r
+}\r
+\r
+/*\r
+ * portRESTORE_CONTEXT_OS_INT() for Tick exception.\r
+ */\r
+#define portRESTORE_CONTEXT_OS_INT() \\r
+{ \\r
+ extern volatile unsigned portLONG ulCriticalNesting; \\r
+ extern volatile void *volatile pxCurrentTCB; \\r
+ \\r
+ /* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \\r
+ /* interrupt handler (which was of a higher priority level but decided to lower its priority */ \\r
+ /* level and allow other lower interrupt level to occur). */ \\r
+ /* In this case we don't want to do a task switch because we don't know what the stack */ \\r
+ /* currently looks like (we don't know what the interrupted interrupt handler was doing). */ \\r
+ /* Saving SP in pxCurrentTCB and then later restoring it (thinking restoring the task) */ \\r
+ /* will just be restoring the interrupt handler, no way!!! */ \\r
+ __asm__ __volatile__ ( \\r
+ "ld.w r0, sp[9*4]\n\t" /* Read SR in stack */ \\r
+ "bfextu r0, r0, 22, 3\n\t" /* Extract the mode bits to R0. */ \\r
+ "cp.w r0, 1\n\t" /* Compare the mode bits with supervisor mode(b'001) */ \\r
+ "brhi LABEL_INT_SKIP_RESTORE_CONTEXT_%[LINE]" \\r
+ : \\r
+ : [LINE] "i" (__LINE__) \\r
+ ); \\r
+ \\r
+ /* Else */ \\r
+ /* because it is here safe, always call vTaskSwitchContext() since an OS tick occurred. */ \\r
+ /* A critical section has to be used here because vTaskSwitchContext handles FreeRTOS linked lists. */\\r
+ portENTER_CRITICAL(); \\r
+ vTaskSwitchContext(); \\r
+ portEXIT_CRITICAL(); \\r
+ \\r
+ /* Restore all registers */ \\r
+ \\r
+ __asm__ __volatile__ ( \\r
+ /* Set SP to point to new stack */ \\r
+ "mov r8, LO(%[pxCurrentTCB]) \n\t"\\r
+ "orh r8, HI(%[pxCurrentTCB]) \n\t"\\r
+ "ld.w r0, r8[0] \n\t"\\r
+ "ld.w sp, r0[0] \n"\\r
+ \\r
+ "LABEL_INT_SKIP_RESTORE_CONTEXT_%[LINE]: \n\t"\\r
+ \\r
+ /* Restore ulCriticalNesting variable */ \\r
+ "ld.w r0, sp++ \n\t" \\r
+ "mov r8, LO(%[ulCriticalNesting]) \n\t"\\r
+ "orh r8, HI(%[ulCriticalNesting]) \n\t"\\r
+ "st.w r8[0], r0 \n\t"\\r
+ \\r
+ /* Restore R0..R7 */ \\r
+ "ldm sp++, r0-r7 \n\t"\\r
+ \\r
+ /* Now, the stack should be R8..R12, LR, PC and SR */ \\r
+ "rete" \\r
+ : \\r
+ : [ulCriticalNesting] "i" (&ulCriticalNesting), \\r
+ [pxCurrentTCB] "i" (&pxCurrentTCB), \\r
+ [LINE] "i" (__LINE__) \\r
+ ); \\r
+}\r
+\r
+#endif\r
+\r
+\r
+/*\r
+ * portSAVE_CONTEXT_SCALL() for SupervisorCALL exception.\r
+ *\r
+ * NOTE: taskYIELD()(== SCALL) MUST NOT be called in a mode > supervisor mode.\r
+ *\r
+ */\r
+#define portSAVE_CONTEXT_SCALL() \\r
+{ \\r
+ extern volatile unsigned portLONG ulCriticalNesting; \\r
+ extern volatile void *volatile pxCurrentTCB; \\r
+ \\r
+ /* Warning: the stack layout after SCALL doesn't match the one after an interrupt. */ \\r
+ /* If SR[M2:M0] == 001 */ \\r
+ /* PC and SR are on the stack. */ \\r
+ /* Else (other modes) */ \\r
+ /* Nothing on the stack. */ \\r
+ \\r
+ /* WARNING NOTE: the else case cannot happen as it is strictly forbidden to call */ \\r
+ /* vTaskDelay() and vTaskDelayUntil() OS functions (that result in a taskYield()) */ \\r
+ /* in an interrupt|exception handler. */ \\r
+ \\r
+ __asm__ __volatile__ ( \\r
+ /* in order to save R0-R7 */ \\r
+ "sub sp, 6*4 \n\t"\\r
+ /* Save R0..R7 */ \\r
+ "stm --sp, r0-r7 \n\t"\\r
+ \\r
+ /* in order to save R8-R12 and LR */ \\r
+ /* do not use SP if interrupts occurs, SP must be left at bottom of stack */ \\r
+ "sub r7, sp,-16*4 \n\t"\\r
+ /* Copy PC and SR in other places in the stack. */ \\r
+ "ld.w r0, r7[-2*4] \n\t" /* Read SR */\\r
+ "st.w r7[-8*4], r0 \n\t" /* Copy SR */\\r
+ "ld.w r0, r7[-1*4] \n\t" /* Read PC */\\r
+ "st.w r7[-7*4], r0 \n\t" /* Copy PC */\\r
+ \\r
+ /* Save R8..R12 and LR on the stack. */ \\r
+ "stm --r7, r8-r12, lr \n\t"\\r
+ \\r
+ /* Arriving here we have the following stack organizations: */ \\r
+ /* R8..R12, LR, PC, SR, R0..R7. */ \\r
+ \\r
+ /* Now we can finalize the save. */ \\r
+ \\r
+ /* Save ulCriticalNesting variable - R0 is overwritten */ \\r
+ "mov r8, LO(%[ulCriticalNesting]) \n\t"\\r
+ "orh r8, HI(%[ulCriticalNesting]) \n\t"\\r
+ "ld.w r0, r8[0] \n\t"\\r
+ "st.w --sp, r0" \\r
+ : \\r
+ : [ulCriticalNesting] "i" (&ulCriticalNesting) \\r
+ ); \\r
+ \\r
+ /* Disable the its which may cause a context switch (i.e. cause a change of */ \\r
+ /* pxCurrentTCB). */ \\r
+ /* Basically, all accesses to the pxCurrentTCB structure should be put in a */ \\r
+ /* critical section because it is a global structure. */ \\r
+ portENTER_CRITICAL(); \\r
+ \\r
+ /* Store SP in the first member of the structure pointed to by pxCurrentTCB */ \\r
+ __asm__ __volatile__ ( \\r
+ "mov r8, LO(%[pxCurrentTCB]) \n\t"\\r
+ "orh r8, HI(%[pxCurrentTCB]) \n\t"\\r
+ "ld.w r0, r8[0] \n\t"\\r
+ "st.w r0[0], sp" \\r
+ : \\r
+ : [pxCurrentTCB] "i" (&pxCurrentTCB) \\r
+ ); \\r
+}\r
+\r
+/*\r
+ * portRESTORE_CONTEXT() for SupervisorCALL exception.\r
+ */\r
+#define portRESTORE_CONTEXT_SCALL() \\r
+{ \\r
+ extern volatile unsigned portLONG ulCriticalNesting; \\r
+ extern volatile void *volatile pxCurrentTCB; \\r
+ \\r
+ /* Restore all registers */ \\r
+ \\r
+ /* Set SP to point to new stack */ \\r
+ __asm__ __volatile__ ( \\r
+ "mov r8, LO(%[pxCurrentTCB]) \n\t"\\r
+ "orh r8, HI(%[pxCurrentTCB]) \n\t"\\r
+ "ld.w r0, r8[0] \n\t"\\r
+ "ld.w sp, r0[0]" \\r
+ : \\r
+ : [pxCurrentTCB] "i" (&pxCurrentTCB) \\r
+ ); \\r
+ \\r
+ /* Leave pxCurrentTCB variable access critical section */ \\r
+ portEXIT_CRITICAL(); \\r
+ \\r
+ __asm__ __volatile__ ( \\r
+ /* Restore ulCriticalNesting variable */ \\r
+ "ld.w r0, sp++ \n\t"\\r
+ "mov r8, LO(%[ulCriticalNesting]) \n\t"\\r
+ "orh r8, HI(%[ulCriticalNesting]) \n\t"\\r
+ "st.w r8[0], r0 \n\t"\\r
+ \\r
+ /* skip PC and SR */ \\r
+ /* do not use SP if interrupts occurs, SP must be left at bottom of stack */ \\r
+ "sub r7, sp, -10*4 \n\t"\\r
+ /* Restore r8-r12 and LR */ \\r
+ "ldm r7++, r8-r12, lr \n\t"\\r
+ \\r
+ /* RETS will take care of the extra PC and SR restore. */ \\r
+ /* So, we have to prepare the stack for this. */ \\r
+ "ld.w r0, r7[-8*4] \n\t" /* Read SR */\\r
+ "st.w r7[-2*4], r0 \n\t" /* Copy SR */\\r
+ "ld.w r0, r7[-7*4] \n\t" /* Read PC */\\r
+ "st.w r7[-1*4], r0 \n\t" /* Copy PC */\\r
+ \\r
+ /* Restore R0..R7 */ \\r
+ "ldm sp++, r0-r7 \n\t"\\r
+ \\r
+ "sub sp, -6*4 \n\t"\\r
+ \\r
+ "rets" \\r
+ : \\r
+ : [ulCriticalNesting] "i" (&ulCriticalNesting) \\r
+ ); \\r
+}\r
+\r
+\r
+/*\r
+ * The ISR used depends on whether the cooperative or\r
+ * the preemptive scheduler is being used.\r
+ */\r
+#if configUSE_PREEMPTION == 0\r
+\r
+/*\r
+ * ISR entry and exit macros. These are only required if a task switch\r
+ * is required from the ISR.\r
+ */\r
+#define portENTER_SWITCHING_ISR() \\r
+{ \\r
+ /* Save R0..R7 */ \\r
+ __asm__ __volatile__ ("stm --sp, r0-r7"); \\r
+ \\r
+ /* With the cooperative scheduler, as there is no context switch by interrupt, */ \\r
+ /* there is also no context save. */ \\r
+}\r
+\r
+/*\r
+ * Input parameter: in R12, boolean. Perform a vTaskSwitchContext() if 1\r
+ */\r
+#define portEXIT_SWITCHING_ISR() \\r
+{ \\r
+ __asm__ __volatile__ ( \\r
+ /* Restore R0..R7 */ \\r
+ "ldm sp++, r0-r7 \n\t"\\r
+ \\r
+ /* With the cooperative scheduler, as there is no context switch by interrupt, */ \\r
+ /* there is also no context restore. */ \\r
+ "rete" \\r
+ ); \\r
+}\r
+\r
+#else\r
+\r
+/*\r
+ * ISR entry and exit macros. These are only required if a task switch\r
+ * is required from the ISR.\r
+ */\r
+#define portENTER_SWITCHING_ISR() \\r
+{ \\r
+ extern volatile unsigned portLONG ulCriticalNesting; \\r
+ extern volatile void *volatile pxCurrentTCB; \\r
+ \\r
+ /* When we come here */ \\r
+ /* Registers R8..R12, LR, PC and SR had already been pushed to system stack */ \\r
+ \\r
+ __asm__ __volatile__ ( \\r
+ /* Save R0..R7 */ \\r
+ "stm --sp, r0-r7 \n\t"\\r
+ \\r
+ /* Save ulCriticalNesting variable - R0 is overwritten */ \\r
+ "mov r8, LO(%[ulCriticalNesting]) \n\t"\\r
+ "orh r8, HI(%[ulCriticalNesting]) \n\t"\\r
+ "ld.w r0, r8[0] \n\t"\\r
+ "st.w --sp, r0 \n\t"\\r
+ \\r
+ /* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \\r
+ /* interrupt handler (which was of a higher priority level but decided to lower its priority */ \\r
+ /* level and allow other lower interrupt level to occur). */ \\r
+ /* In this case we don't want to do a task switch because we don't know what the stack */ \\r
+ /* currently looks like (we don't know what the interrupted interrupt handler was doing). */ \\r
+ /* Saving SP in pxCurrentTCB and then later restoring it (thinking restoring the task) */ \\r
+ /* will just be restoring the interrupt handler, no way!!! */ \\r
+ /* So, since we won't do a vTaskSwitchContext(), it's of no use to save SP. */ \\r
+ "ld.w r0, sp[9*4] \n\t" /* Read SR in stack */\\r
+ "bfextu r0, r0, 22, 3 \n\t" /* Extract the mode bits to R0. */\\r
+ "cp.w r0, 1 \n\t" /* Compare the mode bits with supervisor mode(b'001) */\\r
+ "brhi LABEL_ISR_SKIP_SAVE_CONTEXT_%[LINE] \n\t"\\r
+ \\r
+ /* Store SP in the first member of the structure pointed to by pxCurrentTCB */ \\r
+ "mov r8, LO(%[pxCurrentTCB]) \n\t"\\r
+ "orh r8, HI(%[pxCurrentTCB]) \n\t"\\r
+ "ld.w r0, r8[0] \n\t"\\r
+ "st.w r0[0], sp \n"\\r
+ \\r
+ "LABEL_ISR_SKIP_SAVE_CONTEXT_%[LINE]:" \\r
+ : \\r
+ : [ulCriticalNesting] "i" (&ulCriticalNesting), \\r
+ [pxCurrentTCB] "i" (&pxCurrentTCB), \\r
+ [LINE] "i" (__LINE__) \\r
+ ); \\r
+}\r
+\r
+/*\r
+ * Input parameter: in R12, boolean. Perform a vTaskSwitchContext() if 1\r
+ */\r
+#define portEXIT_SWITCHING_ISR() \\r
+{ \\r
+ extern volatile unsigned portLONG ulCriticalNesting; \\r
+ extern volatile void *volatile pxCurrentTCB; \\r
+ \\r
+ __asm__ __volatile__ ( \\r
+ /* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \\r
+ /* interrupt handler (which was of a higher priority level but decided to lower its priority */ \\r
+ /* level and allow other lower interrupt level to occur). */ \\r
+ /* In this case it's of no use to switch context and restore a new SP because we purposedly */ \\r
+ /* did not previously save SP in its TCB. */ \\r
+ "ld.w r0, sp[9*4] \n\t" /* Read SR in stack */\\r
+ "bfextu r0, r0, 22, 3 \n\t" /* Extract the mode bits to R0. */\\r
+ "cp.w r0, 1 \n\t" /* Compare the mode bits with supervisor mode(b'001) */\\r
+ "brhi LABEL_ISR_SKIP_RESTORE_CONTEXT_%[LINE] \n\t"\\r
+ \\r
+ /* If a switch is required then we just need to call */ \\r
+ /* vTaskSwitchContext() as the context has already been */ \\r
+ /* saved. */ \\r
+ "cp.w r12, 1 \n\t" /* Check if Switch context is required. */\\r
+ "brne LABEL_ISR_RESTORE_CONTEXT_%[LINE]" \\r
+ : \\r
+ : [LINE] "i" (__LINE__) \\r
+ ); \\r
+ \\r
+ /* A critical section has to be used here because vTaskSwitchContext handles FreeRTOS linked lists. */ \\r
+ portENTER_CRITICAL(); \\r
+ vTaskSwitchContext(); \\r
+ portEXIT_CRITICAL(); \\r
+ \\r
+ __asm__ __volatile__ ( \\r
+ "LABEL_ISR_RESTORE_CONTEXT_%[LINE]: \n\t"\\r
+ /* Restore the context of which ever task is now the highest */ \\r
+ /* priority that is ready to run. */ \\r
+ \\r
+ /* Restore all registers */ \\r
+ \\r
+ /* Set SP to point to new stack */ \\r
+ "mov r8, LO(%[pxCurrentTCB]) \n\t"\\r
+ "orh r8, HI(%[pxCurrentTCB]) \n\t"\\r
+ "ld.w r0, r8[0] \n\t"\\r
+ "ld.w sp, r0[0] \n"\\r
+ \\r
+ "LABEL_ISR_SKIP_RESTORE_CONTEXT_%[LINE]: \n\t"\\r
+ \\r
+ /* Restore ulCriticalNesting variable */ \\r
+ "ld.w r0, sp++ \n\t"\\r
+ "mov r8, LO(%[ulCriticalNesting]) \n\t"\\r
+ "orh r8, HI(%[ulCriticalNesting]) \n\t"\\r
+ "st.w r8[0], r0 \n\t"\\r
+ \\r
+ /* Restore R0..R7 */ \\r
+ "ldm sp++, r0-r7 \n\t"\\r
+ \\r
+ /* Now, the stack should be R8..R12, LR, PC and SR */ \\r
+ "rete" \\r
+ : \\r
+ : [ulCriticalNesting] "i" (&ulCriticalNesting), \\r
+ [pxCurrentTCB] "i" (&pxCurrentTCB), \\r
+ [LINE] "i" (__LINE__) \\r
+ ); \\r
+}\r
+\r
+#endif\r
+\r
+\r
+#define portYIELD() {__asm__ __volatile__ ("scall");}\r
+\r
+/* Task function macros as described on the FreeRTOS.org WEB site. */\r
+#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
+#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
+\r
+\r
+#endif /* PORTMACRO_H */\r