--- /dev/null
+/*\r
+ FreeRTOS V7.4.0 - Copyright (C) 2013 Real Time Engineers Ltd.\r
+\r
+ FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT\r
+ http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+\r
+ >>>>>>NOTE<<<<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel.\r
+\r
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more\r
+ details. You should have received a copy of the GNU General Public License\r
+ and the FreeRTOS license exception along with FreeRTOS; if not itcan be\r
+ viewed here: http://www.freertos.org/a00114.html and also obtained by\r
+ writing to Real Time Engineers Ltd., contact details for whom are available\r
+ on the FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\r
+\r
+ ***************************************************************************\r
+ * *\r
+ * Having a problem? Start by reading the FAQ "My application does *\r
+ * not run, what could be wrong?" *\r
+ * *\r
+ * http://www.FreeRTOS.org/FAQHelp.html *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
+ license and Real Time Engineers Ltd. contact details.\r
+\r
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+ including FreeRTOS+Trace - an indispensable productivity tool, and our new\r
+ fully thread aware and reentrant UDP/IP stack.\r
+\r
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
+ Integrity Systems, who sell the code with commercial support,\r
+ indemnification and middleware, under the OpenRTOS brand.\r
+\r
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+ engineered and independently SIL3 certified version for use in safety and\r
+ mission critical applications that require provable dependability.\r
+*/\r
+\r
+/*-----------------------------------------------------------\r
+ * Implementation of functions defined in portable.h for the SH2A port.\r
+ *----------------------------------------------------------*/\r
+\r
+/* Standard C includes. */\r
+#include "limits.h"\r
+\r
+/* Scheduler includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+/* Library includes. */\r
+#include "string.h"\r
+\r
+/* Hardware specifics. */\r
+#include "iodefine.h"\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Tasks should start with interrupts enabled and in Supervisor mode, therefore\r
+PSW is set with U and I set, and PM and IPL clear. */\r
+#define portINITIAL_PSW ( ( portSTACK_TYPE ) 0x00030000 )\r
+\r
+/* The peripheral clock is divided by this value before being supplying the\r
+CMT. */\r
+#if ( configUSE_TICKLESS_IDLE == 0 )\r
+ /* If tickless idle is not used then the divisor can be fixed. */\r
+ #define portCLOCK_DIVISOR 8UL\r
+#elif ( configPERIPHERAL_CLOCK_HZ >= 12000000 )\r
+ #define portCLOCK_DIVISOR 512UL\r
+#elif ( configPERIPHERAL_CLOCK_HZ >= 6000000 )\r
+ #define portCLOCK_DIVISOR 128UL\r
+#elif ( configPERIPHERAL_CLOCK_HZ >= 1000000 )\r
+ #define portCLOCK_DIVISOR 32UL\r
+#else\r
+ #define portCLOCK_DIVISOR 8UL\r
+#endif\r
+\r
+/* These macros allow a critical section to be added around the call to\r
+vTaskIncrementTick(), which is only ever called from interrupts at the kernel\r
+priority - ie a known priority. Therefore these local macros are a slight\r
+optimisation compared to calling the global SET/CLEAR_INTERRUPT_MASK macros,\r
+which would require the old IPL to be read first and stored in a local variable. */\r
+#define portDISABLE_INTERRUPTS_FROM_KERNEL_ISR() __asm volatile ( "MVTIPL %0" ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) )\r
+#define portENABLE_INTERRUPTS_FROM_KERNEL_ISR() __asm volatile ( "MVTIPL %0" ::"i"(configKERNEL_INTERRUPT_PRIORITY) )\r
+\r
+/* Keys required to lock and unlock access to certain system registers\r
+respectively. */\r
+#define portUNLOCK_KEY 0xA50B\r
+#define portLOCK_KEY 0xA500\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Function to start the first task executing - written in asm code as direct\r
+ * access to registers is required.\r
+ */\r
+static void prvStartFirstTask( void ) __attribute__((naked));\r
+\r
+/*\r
+ * Software interrupt handler. Performs the actual context switch (saving and\r
+ * restoring of registers). Written in asm code as direct register access is\r
+ * required.\r
+ */\r
+void vPortSoftwareInterruptISR( void ) __attribute__((naked));\r
+\r
+/*\r
+ * The tick interrupt handler.\r
+ */\r
+void vPortTickISR( void ) __attribute__((interrupt));\r
+\r
+/*\r
+ * Sets up the periodic ISR used for the RTOS tick using the CMT.\r
+ * The application writer can define configSETUP_TICK_INTERRUPT() (in\r
+ * FreeRTOSConfig.h) such that their own tick interrupt configuration is used\r
+ * in place of prvSetupTimerInterrupt().\r
+ */\r
+static void prvSetupTimerInterrupt( void );\r
+#ifndef configSETUP_TICK_INTERRUPT\r
+ /* The user has not provided their own tick interrupt configuration so use\r
+ the definition in this file (which uses the interval timer). */\r
+ #define configSETUP_TICK_INTERRUPT() prvSetupTimerInterrupt()\r
+#endif /* configSETUP_TICK_INTERRUPT */\r
+\r
+/*\r
+ * Called after the sleep mode registers have been configured, prvSleep()\r
+ * executes the pre and post sleep macros, and actually calls the wait\r
+ * instruction.\r
+ */\r
+#if configUSE_TICKLESS_IDLE == 1\r
+ static void prvSleep( portTickType xExpectedIdleTime );\r
+#endif /* configUSE_TICKLESS_IDLE */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Used in the context save and restore code. */\r
+extern void *pxCurrentTCB;\r
+\r
+/* Calculate how many clock increments make up a single tick period. */\r
+static const unsigned long ulMatchValueForOneTick = ( ( configPERIPHERAL_CLOCK_HZ / portCLOCK_DIVISOR ) / configTICK_RATE_HZ );\r
+\r
+#if configUSE_TICKLESS_IDLE == 1\r
+\r
+ /* Holds the maximum number of ticks that can be suppressed - which is\r
+ basically how far into the future an interrupt can be generated. Set\r
+ during initialisation. This is the maximum possible value that the\r
+ compare match register can hold divided by ulMatchValueForOneTick. */\r
+ static const portTickType xMaximumPossibleSuppressedTicks = USHRT_MAX / ( ( configPERIPHERAL_CLOCK_HZ / portCLOCK_DIVISOR ) / configTICK_RATE_HZ );\r
+\r
+ /* Flag set from the tick interrupt to allow the sleep processing to know if\r
+ sleep mode was exited because of a tick interrupt, or an interrupt\r
+ generated by something else. */\r
+ static volatile uint32_t ulTickFlag = pdFALSE;\r
+\r
+ /* The CMT counter is stopped temporarily each time it is re-programmed.\r
+ The following constant offsets the CMT counter match value by the number of\r
+ CMT counts that would typically be missed while the counter was stopped to\r
+ compensate for the lost time. The large difference between the divided CMT\r
+ clock and the CPU clock means it is likely ulStoppedTimerCompensation will\r
+ equal zero - and be optimised away. */\r
+ static const unsigned long ulStoppedTimerCompensation = 100UL / ( configCPU_CLOCK_HZ / ( configPERIPHERAL_CLOCK_HZ / portCLOCK_DIVISOR ) );\r
+\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * See header file for description.\r
+ */\r
+portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )\r
+{\r
+ /* Offset to end up on 8 byte boundary. */\r
+ pxTopOfStack--;\r
+\r
+ /* R0 is not included as it is the stack pointer. */\r
+ *pxTopOfStack = 0x00;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = 0x00;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = portINITIAL_PSW;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( portSTACK_TYPE ) pxCode;\r
+\r
+ /* When debugging it can be useful if every register is set to a known\r
+ value. Otherwise code space can be saved by just setting the registers\r
+ that need to be set. */\r
+ #ifdef USE_FULL_REGISTER_INITIALISATION\r
+ {\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = 0x12345678; /* r15. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = 0xaaaabbbb;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = 0xdddddddd;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = 0xcccccccc;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = 0xbbbbbbbb;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = 0xaaaaaaaa;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = 0x99999999;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = 0x88888888;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = 0x77777777;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = 0x66666666;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = 0x55555555;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = 0x44444444;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = 0x33333333;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = 0x22222222;\r
+ pxTopOfStack--;\r
+ }\r
+ #else\r
+ {\r
+ /* Leave space for the registers that will get popped from the stack\r
+ when the task first starts executing. */\r
+ pxTopOfStack -= 15;\r
+ }\r
+ #endif\r
+\r
+ *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R1 */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = 0x12345678; /* Accumulator. */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = 0x87654321; /* Accumulator. */\r
+\r
+ return pxTopOfStack;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+portBASE_TYPE xPortStartScheduler( void )\r
+{\r
+ /* Use pxCurrentTCB just so it does not get optimised away. */\r
+ if( pxCurrentTCB != NULL )\r
+ {\r
+ /* Call an application function to set up the timer that will generate\r
+ the tick interrupt. This way the application can decide which\r
+ peripheral to use. If tickless mode is used then the default\r
+ implementation defined in this file (which uses CMT0) should not be\r
+ overridden. */\r
+ configSETUP_TICK_INTERRUPT();\r
+\r
+ /* Enable the software interrupt. */\r
+ _IEN( _ICU_SWINT ) = 1;\r
+\r
+ /* Ensure the software interrupt is clear. */\r
+ _IR( _ICU_SWINT ) = 0;\r
+\r
+ /* Ensure the software interrupt is set to the kernel priority. */\r
+ _IPR( _ICU_SWINT ) = configKERNEL_INTERRUPT_PRIORITY;\r
+\r
+ /* Start the first task. */\r
+ prvStartFirstTask();\r
+ }\r
+\r
+ /* Execution should not reach here as the tasks are now running!\r
+ prvSetupTimerInterrupt() is called here to prevent the compiler outputting\r
+ a warning about a statically declared function not being referenced in the\r
+ case that the application writer has provided their own tick interrupt\r
+ configuration routine (and defined configSETUP_TICK_INTERRUPT() such that\r
+ their own routine will be called in place of prvSetupTimerInterrupt()). */\r
+ prvSetupTimerInterrupt();\r
+\r
+ /* Should not get here. */\r
+ return pdFAIL;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vPortEndScheduler( void )\r
+{\r
+ /* Not implemented as there is nothing to return to. */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvStartFirstTask( void )\r
+{\r
+ __asm volatile\r
+ (\r
+ /* When starting the scheduler there is nothing that needs moving to the\r
+ interrupt stack because the function is not called from an interrupt.\r
+ Just ensure the current stack is the user stack. */\r
+ "SETPSW U \n" \\r
+\r
+ /* Obtain the location of the stack associated with which ever task\r
+ pxCurrentTCB is currently pointing to. */\r
+ "MOV.L #_pxCurrentTCB, R15 \n" \\r
+ "MOV.L [R15], R15 \n" \\r
+ "MOV.L [R15], R0 \n" \\r
+\r
+ /* Restore the registers from the stack of the task pointed to by\r
+ pxCurrentTCB. */\r
+ "POP R15 \n" \\r
+\r
+ /* Accumulator low 32 bits. */\r
+ "MVTACLO R15 \n" \\r
+ "POP R15 \n" \\r
+\r
+ /* Accumulator high 32 bits. */\r
+ "MVTACHI R15 \n" \\r
+\r
+ /* R1 to R15 - R0 is not included as it is the SP. */\r
+ "POPM R1-R15 \n" \\r
+\r
+ /* This pops the remaining registers. */\r
+ "RTE \n" \\r
+ "NOP \n" \\r
+ "NOP \n"\r
+ );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vPortSoftwareInterruptISR( void )\r
+{\r
+ __asm volatile\r
+ (\r
+ /* Re-enable interrupts. */\r
+ "SETPSW I \n" \\r
+\r
+ /* Move the data that was automatically pushed onto the interrupt stack when\r
+ the interrupt occurred from the interrupt stack to the user stack.\r
+\r
+ R15 is saved before it is clobbered. */\r
+ "PUSH.L R15 \n" \\r
+\r
+ /* Read the user stack pointer. */\r
+ "MVFC USP, R15 \n" \\r
+\r
+ /* Move the address down to the data being moved. */\r
+ "SUB #12, R15 \n" \\r
+ "MVTC R15, USP \n" \\r
+\r
+ /* Copy the data across, R15, then PC, then PSW. */\r
+ "MOV.L [ R0 ], [ R15 ] \n" \\r
+ "MOV.L 4[ R0 ], 4[ R15 ] \n" \\r
+ "MOV.L 8[ R0 ], 8[ R15 ] \n" \\r
+\r
+ /* Move the interrupt stack pointer to its new correct position. */\r
+ "ADD #12, R0 \n" \\r
+\r
+ /* All the rest of the registers are saved directly to the user stack. */\r
+ "SETPSW U \n" \\r
+\r
+ /* Save the rest of the general registers (R15 has been saved already). */\r
+ "PUSHM R1-R14 \n" \\r
+\r
+ /* Save the accumulator. */\r
+ "MVFACHI R15 \n" \\r
+ "PUSH.L R15 \n" \\r
+\r
+ /* Middle word. */\r
+ "MVFACMI R15 \n" \\r
+\r
+ /* Shifted left as it is restored to the low order word. */\r
+ "SHLL #16, R15 \n" \\r
+ "PUSH.L R15 \n" \\r
+\r
+ /* Save the stack pointer to the TCB. */\r
+ "MOV.L #_pxCurrentTCB, R15 \n" \\r
+ "MOV.L [ R15 ], R15 \n" \\r
+ "MOV.L R0, [ R15 ] \n" \\r
+\r
+ /* Ensure the interrupt mask is set to the syscall priority while the kernel\r
+ structures are being accessed. */\r
+ "MVTIPL %0 \n" \\r
+\r
+ /* Select the next task to run. */\r
+ "BSR.A _vTaskSwitchContext \n" \\r
+\r
+ /* Reset the interrupt mask as no more data structure access is required. */\r
+ "MVTIPL %1 \n" \\r
+\r
+ /* Load the stack pointer of the task that is now selected as the Running\r
+ state task from its TCB. */\r
+ "MOV.L #_pxCurrentTCB,R15 \n" \\r
+ "MOV.L [ R15 ], R15 \n" \\r
+ "MOV.L [ R15 ], R0 \n" \\r
+\r
+ /* Restore the context of the new task. The PSW (Program Status Word) and\r
+ PC will be popped by the RTE instruction. */\r
+ "POP R15 \n" \\r
+ "MVTACLO R15 \n" \\r
+ "POP R15 \n" \\r
+ "MVTACHI R15 \n" \\r
+ "POPM R1-R15 \n" \\r
+ "RTE \n" \\r
+ "NOP \n" \\r
+ "NOP "\r
+ :: "i"(configMAX_SYSCALL_INTERRUPT_PRIORITY), "i"(configKERNEL_INTERRUPT_PRIORITY)\r
+ );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vPortTickISR( void )\r
+{\r
+ /* Re-enabled interrupts. */\r
+ __asm volatile( "SETPSW I" );\r
+\r
+ /* Increment the tick, and perform any processing the new tick value\r
+ necessitates. Ensure IPL is at the max syscall value first. */\r
+ portDISABLE_INTERRUPTS_FROM_KERNEL_ISR();\r
+ {\r
+ vTaskIncrementTick();\r
+ }\r
+ portENABLE_INTERRUPTS_FROM_KERNEL_ISR();\r
+\r
+ /* Only select a new task if the preemptive scheduler is being used. */\r
+ #if( configUSE_PREEMPTION == 1 )\r
+ taskYIELD();\r
+ #endif\r
+\r
+ #if configUSE_TICKLESS_IDLE == 1\r
+ {\r
+ /* The CPU woke because of a tick. */\r
+ ulTickFlag = pdTRUE;\r
+\r
+ /* If this is the first tick since exiting tickless mode then the CMT\r
+ compare match value needs resetting. */\r
+ CMT0.CMCOR = ( unsigned short ) ulMatchValueForOneTick;\r
+ }\r
+ #endif\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+unsigned long ulPortGetIPL( void )\r
+{\r
+ __asm volatile\r
+ (\r
+ "MVFC PSW, R1 \n" \\r
+ "SHLR #24, R1 \n" \\r
+ "RTS "\r
+ );\r
+\r
+ /* This will never get executed, but keeps the compiler from complaining. */\r
+ return 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vPortSetIPL( unsigned long ulNewIPL )\r
+{\r
+ __asm volatile\r
+ (\r
+ "PUSH R5 \n" \\r
+ "MVFC PSW, R5 \n" \\r
+ "SHLL #24, R1 \n" \\r
+ "AND #-0F000001H, R5 \n" \\r
+ "OR R1, R5 \n" \\r
+ "MVTC R5, PSW \n" \\r
+ "POP R5 \n" \\r
+ "RTS "\r
+ );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSetupTimerInterrupt( void )\r
+{\r
+ /* Unlock. */\r
+ SYSTEM.PRCR.WORD = portUNLOCK_KEY;\r
+\r
+ /* Enable CMT0. */\r
+ MSTP( CMT0 ) = 0;\r
+\r
+ /* Lock again. */\r
+ SYSTEM.PRCR.WORD = portLOCK_KEY;\r
+\r
+ /* Interrupt on compare match. */\r
+ CMT0.CMCR.BIT.CMIE = 1;\r
+\r
+ /* Set the compare match value. */\r
+ CMT0.CMCOR = ( unsigned short ) ulMatchValueForOneTick;\r
+\r
+ /* Divide the PCLK. */\r
+ #if portCLOCK_DIVISOR == 512\r
+ {\r
+ CMT0.CMCR.BIT.CKS = 3;\r
+ }\r
+ #elif portCLOCK_DIVISOR == 128\r
+ {\r
+ CMT0.CMCR.BIT.CKS = 2;\r
+ }\r
+ #elif portCLOCK_DIVISOR == 32\r
+ {\r
+ CMT0.CMCR.BIT.CKS = 1;\r
+ }\r
+ #elif portCLOCK_DIVISOR == 8\r
+ {\r
+ CMT0.CMCR.BIT.CKS = 0;\r
+ }\r
+ #else\r
+ {\r
+ #error Invalid portCLOCK_DIVISOR setting\r
+ }\r
+ #endif\r
+\r
+ /* Enable the interrupt... */\r
+ _IEN( _CMT0_CMI0 ) = 1;\r
+\r
+ /* ...and set its priority to the application defined kernel priority. */\r
+ _IPR( _CMT0_CMI0 ) = configKERNEL_INTERRUPT_PRIORITY;\r
+\r
+ /* Start the timer. */\r
+ CMT.CMSTR0.BIT.STR0 = 1;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if configUSE_TICKLESS_IDLE == 1\r
+\r
+ static void prvSleep( portTickType xExpectedIdleTime )\r
+ {\r
+ /* Allow the application to define some pre-sleep processing. */\r
+ configPRE_SLEEP_PROCESSING( xExpectedIdleTime );\r
+\r
+ /* xExpectedIdleTime being set to 0 by configPRE_SLEEP_PROCESSING()\r
+ means the application defined code has already executed the WAIT\r
+ instruction. */\r
+ if( xExpectedIdleTime > 0 )\r
+ {\r
+ __asm volatile( "WAIT" );\r
+ }\r
+\r
+ /* Allow the application to define some post sleep processing. */\r
+ configPOST_SLEEP_PROCESSING( xExpectedIdleTime );\r
+ }\r
+\r
+#endif /* configUSE_TICKLESS_IDLE */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if configUSE_TICKLESS_IDLE == 1\r
+\r
+ void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )\r
+ {\r
+ unsigned long ulMatchValue, ulCompleteTickPeriods, ulCurrentCount;\r
+ eSleepModeStatus eSleepAction;\r
+\r
+ /* THIS FUNCTION IS CALLED WITH THE SCHEDULER SUSPENDED. */\r
+\r
+ /* Make sure the CMT reload value does not overflow the counter. */\r
+ if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )\r
+ {\r
+ xExpectedIdleTime = xMaximumPossibleSuppressedTicks;\r
+ }\r
+\r
+ /* Calculate the reload value required to wait xExpectedIdleTime tick\r
+ periods. -1 is used because this code will execute part way through\r
+ one of the tick periods, and the fraction of a tick period is accounted\r
+ for later. */\r
+ ulMatchValue = ( ulMatchValueForOneTick * ( xExpectedIdleTime - 1UL ) );\r
+ if( ulMatchValue > ulStoppedTimerCompensation )\r
+ {\r
+ /* Compensate for the fact that the CMT is going to be stopped\r
+ momentarily. */\r
+ ulMatchValue -= ulStoppedTimerCompensation;\r
+ }\r
+\r
+ /* Stop the CMT momentarily. The time the CMT is stopped for is\r
+ accounted for as best it can be, but using the tickless mode will\r
+ inevitably result in some tiny drift of the time maintained by the\r
+ kernel with respect to calendar time. */\r
+ CMT.CMSTR0.BIT.STR0 = 0;\r
+ while( CMT.CMSTR0.BIT.STR0 == 1 )\r
+ {\r
+ /* Nothing to do here. */\r
+ }\r
+\r
+ /* Critical section using the global interrupt bit as the i bit is\r
+ automatically reset by the WAIT instruction. */\r
+ __asm volatile( "CLRPSW i" );\r
+\r
+ /* The tick flag is set to false before sleeping. If it is true when\r
+ sleep mode is exited then sleep mode was probably exited because the\r
+ tick was suppressed for the entire xExpectedIdleTime period. */\r
+ ulTickFlag = pdFALSE;\r
+\r
+ /* If a context switch is pending then abandon the low power entry as\r
+ the context switch might have been pended by an external interrupt that\r
+ requires processing. */\r
+ eSleepAction = eTaskConfirmSleepModeStatus();\r
+ if( eSleepAction == eAbortSleep )\r
+ {\r
+ /* Restart tick. */\r
+ CMT.CMSTR0.BIT.STR0 = 1;\r
+ __asm volatile( "SETPSW i" );\r
+ }\r
+ else if( eSleepAction == eNoTasksWaitingTimeout )\r
+ {\r
+ /* Protection off. */\r
+ SYSTEM.PRCR.WORD = portUNLOCK_KEY;\r
+\r
+ /* Ready for software standby with all clocks stopped. */\r
+ SYSTEM.SBYCR.BIT.SSBY = 1;\r
+\r
+ /* Protection on. */\r
+ SYSTEM.PRCR.WORD = portLOCK_KEY;\r
+\r
+ /* Sleep until something happens. Calling prvSleep() will\r
+ automatically reset the i bit in the PSW. */\r
+ prvSleep( xExpectedIdleTime );\r
+\r
+ /* Restart the CMT. */\r
+ CMT.CMSTR0.BIT.STR0 = 1;\r
+ }\r
+ else\r
+ {\r
+ /* Protection off. */\r
+ SYSTEM.PRCR.WORD = portUNLOCK_KEY;\r
+\r
+ /* Ready for deep sleep mode. */\r
+ SYSTEM.MSTPCRC.BIT.DSLPE = 1;\r
+ SYSTEM.MSTPCRA.BIT.MSTPA28 = 1;\r
+ SYSTEM.SBYCR.BIT.SSBY = 0;\r
+\r
+ /* Protection on. */\r
+ SYSTEM.PRCR.WORD = portLOCK_KEY;\r
+\r
+ /* Adjust the match value to take into account that the current\r
+ time slice is already partially complete. */\r
+ ulMatchValue -= ( unsigned long ) CMT0.CMCNT;\r
+ CMT0.CMCOR = ( unsigned short ) ulMatchValue;\r
+\r
+ /* Restart the CMT to count up to the new match value. */\r
+ CMT0.CMCNT = 0;\r
+ CMT.CMSTR0.BIT.STR0 = 1;\r
+\r
+ /* Sleep until something happens. Calling prvSleep() will\r
+ automatically reset the i bit in the PSW. */\r
+ prvSleep( xExpectedIdleTime );\r
+\r
+ /* Stop CMT. Again, the time the SysTick is stopped for is\r
+ accounted for as best it can be, but using the tickless mode will\r
+ inevitably result in some tiny drift of the time maintained by the\r
+ kernel with respect to calendar time. */\r
+ CMT.CMSTR0.BIT.STR0 = 0;\r
+ while( CMT.CMSTR0.BIT.STR0 == 1 )\r
+ {\r
+ /* Nothing to do here. */\r
+ }\r
+\r
+ ulCurrentCount = ( unsigned long ) CMT0.CMCNT;\r
+\r
+ if( ulTickFlag != pdFALSE )\r
+ {\r
+ /* The tick interrupt has already executed, although because\r
+ this function is called with the scheduler suspended the actual\r
+ tick processing will not occur until after this function has\r
+ exited. Reset the match value with whatever remains of this\r
+ tick period. */\r
+ ulMatchValue = ulMatchValueForOneTick - ulCurrentCount;\r
+ CMT0.CMCOR = ( unsigned short ) ulMatchValue;\r
+\r
+ /* The tick interrupt handler will already have pended the tick\r
+ processing in the kernel. As the pending tick will be\r
+ processed as soon as this function exits, the tick value\r
+ maintained by the tick is stepped forward by one less than the\r
+ time spent sleeping. The actual stepping of the tick appears\r
+ later in this function. */\r
+ ulCompleteTickPeriods = xExpectedIdleTime - 1UL;\r
+ }\r
+ else\r
+ {\r
+ /* Something other than the tick interrupt ended the sleep.\r
+ How many complete tick periods passed while the processor was\r
+ sleeping? */\r
+ ulCompleteTickPeriods = ulCurrentCount / ulMatchValueForOneTick;\r
+\r
+ /* The match value is set to whatever fraction of a single tick\r
+ period remains. */\r
+ ulMatchValue = ulCurrentCount - ( ulCompleteTickPeriods * ulMatchValueForOneTick );\r
+ CMT0.CMCOR = ( unsigned short ) ulMatchValue;\r
+ }\r
+\r
+ /* Restart the CMT so it runs up to the match value. The match value\r
+ will get set to the value required to generate exactly one tick period\r
+ the next time the CMT interrupt executes. */\r
+ CMT0.CMCNT = 0;\r
+ CMT.CMSTR0.BIT.STR0 = 1;\r
+\r
+ /* Wind the tick forward by the number of tick periods that the CPU\r
+ remained in a low power state. */\r
+ vTaskStepTick( ulCompleteTickPeriods );\r
+ }\r
+ }\r
+\r
+#endif /* configUSE_TICKLESS_IDLE */\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V7.4.0 - Copyright (C) 2013 Real Time Engineers Ltd.\r
+\r
+ FEATURES AND PORTS ARE ADDED TO FREERTOS ALL THE TIME. PLEASE VISIT\r
+ http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS tutorial books are available in pdf and paperback. *\r
+ * Complete, revised, and edited pdf reference manuals are also *\r
+ * available. *\r
+ * *\r
+ * Purchasing FreeRTOS documentation will not only help you, by *\r
+ * ensuring you get running as quickly as possible and with an *\r
+ * in-depth knowledge of how to use FreeRTOS, it will also help *\r
+ * the FreeRTOS project to continue with its mission of providing *\r
+ * professional grade, cross platform, de facto standard solutions *\r
+ * for microcontrollers - completely free of charge! *\r
+ * *\r
+ * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *\r
+ * *\r
+ * Thank you for using FreeRTOS, and thank you for your support! *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
+\r
+ >>>>>>NOTE<<<<<< The modification to the GPL is included to allow you to\r
+ distribute a combined work that includes FreeRTOS without being obliged to\r
+ provide the source code for proprietary components outside of the FreeRTOS\r
+ kernel.\r
+\r
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more\r
+ details. You should have received a copy of the GNU General Public License\r
+ and the FreeRTOS license exception along with FreeRTOS; if not itcan be\r
+ viewed here: http://www.freertos.org/a00114.html and also obtained by\r
+ writing to Real Time Engineers Ltd., contact details for whom are available\r
+ on the FreeRTOS WEB site.\r
+\r
+ 1 tab == 4 spaces!\r
+\r
+ ***************************************************************************\r
+ * *\r
+ * Having a problem? Start by reading the FAQ "My application does *\r
+ * not run, what could be wrong?" *\r
+ * *\r
+ * http://www.FreeRTOS.org/FAQHelp.html *\r
+ * *\r
+ ***************************************************************************\r
+\r
+\r
+ http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
+ license and Real Time Engineers Ltd. contact details.\r
+\r
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+ including FreeRTOS+Trace - an indispensable productivity tool, and our new\r
+ fully thread aware and reentrant UDP/IP stack.\r
+\r
+ http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
+ Integrity Systems, who sell the code with commercial support,\r
+ indemnification and middleware, under the OpenRTOS brand.\r
+\r
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+ engineered and independently SIL3 certified version for use in safety and\r
+ mission critical applications that require provable dependability.\r
+*/\r
+\r
+\r
+#ifndef PORTMACRO_H\r
+#define PORTMACRO_H\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\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
+\r
+/* Type definitions - these are a bit legacy and not really used now, other than\r
+portSTACK_TYPE and portBASE_TYPE. */\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 long\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
+/* Hardware specifics. */\r
+#define portBYTE_ALIGNMENT 8 /* Could make four, according to manual. */\r
+#define portSTACK_GROWTH -1\r
+#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ )\r
+#define portNOP() __asm volatile( "NOP" )\r
+\r
+/* Save clobbered register, set ITU SWINR (at address 0x872E0), read the value\r
+back to ensure it is set before continuing, then restore the clobbered\r
+register. */\r
+#define portYIELD() \\r
+ __asm volatile \\r
+ ( \\r
+ "MOV.L #0x872E0, r5 \n\t" \\r
+ "MOV.B #1, [r5] \n\t" \\r
+ "MOV.L [r5], r5 \n\t" \\r
+ ::: "r5" \\r
+ )\r
+\r
+#define portYIELD_FROM_ISR( x ) if( x != pdFALSE ) { portYIELD(); }\r
+\r
+/*\r
+ * These macros should be called directly, but through the taskENTER_CRITICAL()\r
+ * and taskEXIT_CRITICAL() macros.\r
+ */\r
+#define portENABLE_INTERRUPTS() __asm volatile ( "MVTIPL #0" );\r
+#define portDISABLE_INTERRUPTS() __asm volatile ( "MVTIPL %0" ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) )\r
+\r
+/* Critical nesting counts are stored in the TCB. */\r
+#define portCRITICAL_NESTING_IN_TCB ( 1 )\r
+\r
+/* The critical nesting functions defined within tasks.c. */\r
+extern void vTaskEnterCritical( void );\r
+extern void vTaskExitCritical( void );\r
+#define portENTER_CRITICAL() vTaskEnterCritical()\r
+#define portEXIT_CRITICAL() vTaskExitCritical()\r
+\r
+/* As this port allows interrupt nesting... */\r
+unsigned long ulPortGetIPL( void ) __attribute__((naked));\r
+void vPortSetIPL( unsigned long ulNewIPL ) __attribute__((naked));\r
+#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortGetIPL(); portDISABLE_INTERRUPTS()\r
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ) vPortSetIPL( uxSavedInterruptStatus )\r
+\r
+/* Tickless idle/low power functionality. */\r
+#if configUSE_TICKLESS_IDLE == 1\r
+ #ifndef portSUPPRESS_TICKS_AND_SLEEP\r
+ extern void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime );\r
+ #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )\r
+ #endif\r
+#endif\r
+\r
+/* This macro is not appropriate for this port so is defined away. */\r
+#define portALIGNMENT_ASSERT_pxCurrentTCB( x )\r
+\r
+/*-----------------------------------------------------------*/\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
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* PORTMACRO_H */\r
+\r