+/*\r
+ * FreeRTOS Kernel V10.2.0\r
+ * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://aws.amazon.com/freertos\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ */\r
+\r
+/* Standard includes. */\r
+#include <stdlib.h>\r
+\r
+/* Scheduler includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1\r
+ /* Check the configuration. */\r
+ #if( configMAX_PRIORITIES > 32 )\r
+ #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.\r
+ #endif\r
+#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */\r
+\r
+#ifndef configSETUP_TICK_INTERRUPT\r
+ #error configSETUP_TICK_INTERRUPT() must be defined in FreeRTOSConfig.h to call the function that sets up the tick interrupt.\r
+#endif\r
+\r
+#ifndef configCLEAR_TICK_INTERRUPT\r
+ #error configCLEAR_TICK_INTERRUPT must be defined in FreeRTOSConfig.h to clear which ever interrupt was used to generate the tick interrupt.\r
+#endif\r
+\r
+/* A critical section is exited when the critical section nesting count reaches\r
+this value. */\r
+#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )\r
+\r
+/* Tasks are not created with a floating point context, but can be given a\r
+floating point context after they have been created. A variable is stored as\r
+part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task\r
+does not have an FPU context, or any other value if the task does have an FPU\r
+context. */\r
+#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )\r
+\r
+/* Constants required to setup the initial task context. */\r
+#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, IRQ enabled FIQ enabled. */\r
+#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )\r
+#define portTHUMB_MODE_ADDRESS ( 0x01UL )\r
+\r
+/* Masks all bits in the APSR other than the mode bits. */\r
+#define portAPSR_MODE_BITS_MASK ( 0x1F )\r
+\r
+/* The value of the mode bits in the APSR when the CPU is executing in user\r
+mode. */\r
+#define portAPSR_USER_MODE ( 0x10 )\r
+\r
+/* Let the user override the pre-loading of the initial LR with the address of\r
+prvTaskExitError() in case it messes up unwinding of the stack in the\r
+debugger. */\r
+#ifdef configTASK_RETURN_ADDRESS\r
+ #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS\r
+#else\r
+ #define portTASK_RETURN_ADDRESS prvTaskExitError\r
+#endif\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Starts the first task executing. This function is necessarily written in\r
+ * assembly code so is implemented in portASM.s.\r
+ */\r
+extern void vPortRestoreTaskContext( void );\r
+\r
+/*\r
+ * Used to catch tasks that attempt to return from their implementing function.\r
+ */\r
+static void prvTaskExitError( void );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* A variable is used to keep track of the critical section nesting. This\r
+variable has to be stored as part of the task context and must be initialised to\r
+a non zero value to ensure interrupts don't inadvertently become unmasked before\r
+the scheduler starts. As it is stored as part of the task context it will\r
+automatically be set to 0 when the first task is started. */\r
+volatile uint32_t ulCriticalNesting = 9999UL;\r
+\r
+/* Saved as part of the task context. If ulPortTaskHasFPUContext is non-zero then\r
+a floating point context must be saved and restored for the task. */\r
+volatile uint32_t ulPortTaskHasFPUContext = pdFALSE;\r
+\r
+/* Set to 1 to pend a context switch from an ISR. */\r
+volatile uint32_t ulPortYieldRequired = pdFALSE;\r
+\r
+/* Counts the interrupt nesting depth. A context switch is only performed if\r
+if the nesting depth is 0. */\r
+volatile uint32_t ulPortInterruptNesting = 0UL;\r
+\r
+/* Used in the asm file to clear an interrupt. */\r
+__attribute__(( used )) const uint32_t ulICCEOIR = configEOI_ADDRESS;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * See header file for description.\r
+ */\r
+StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )\r
+{\r
+ /* Setup the initial stack of the task. The stack is set exactly as\r
+ expected by the portRESTORE_CONTEXT() macro.\r
+\r
+ The fist real value on the stack is the status register, which is set for\r
+ system mode, with interrupts enabled. A few NULLs are added first to ensure\r
+ GDB does not try decoding a non-existent return address. */\r
+ *pxTopOfStack = ( StackType_t ) NULL;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) NULL;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) NULL;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;\r
+\r
+ if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )\r
+ {\r
+ /* The task will start in THUMB mode. */\r
+ *pxTopOfStack |= portTHUMB_MODE_BIT;\r
+ }\r
+\r
+ pxTopOfStack--;\r
+\r
+ /* Next the return address, which in this case is the start of the task. */\r
+ *pxTopOfStack = ( StackType_t ) pxCode;\r
+ pxTopOfStack--;\r
+\r
+ /* Next all the registers other than the stack pointer. */\r
+ *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */\r
+ pxTopOfStack--;\r
+\r
+ /* The task will start with a critical nesting count of 0 as interrupts are\r
+ enabled. */\r
+ *pxTopOfStack = portNO_CRITICAL_NESTING;\r
+ pxTopOfStack--;\r
+\r
+ /* The task will start without a floating point context. A task that uses\r
+ the floating point hardware must call vPortTaskUsesFPU() before executing\r
+ any floating point instructions. */\r
+ *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;\r
+\r
+ return pxTopOfStack;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvTaskExitError( void )\r
+{\r
+ /* A function that implements a task must not exit or attempt to return to\r
+ its caller as there is nothing to return to. If a task wants to exit it\r
+ should instead call vTaskDelete( NULL ).\r
+\r
+ Artificially force an assert() to be triggered if configASSERT() is\r
+ defined, then stop here so application writers can catch the error. */\r
+ configASSERT( ulPortInterruptNesting == ~0UL );\r
+ portDISABLE_INTERRUPTS();\r
+ for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xPortStartScheduler( void )\r
+{\r
+uint32_t ulAPSR;\r
+\r
+ /* Only continue if the CPU is not in User mode. The CPU must be in a\r
+ Privileged mode for the scheduler to start. */\r
+ __asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) );\r
+ ulAPSR &= portAPSR_MODE_BITS_MASK;\r
+ configASSERT( ulAPSR != portAPSR_USER_MODE );\r
+\r
+ if( ulAPSR != portAPSR_USER_MODE )\r
+ {\r
+ /* Start the timer that generates the tick ISR. */\r
+ portDISABLE_INTERRUPTS();\r
+ configSETUP_TICK_INTERRUPT();\r
+\r
+ /* Start the first task executing. */\r
+ vPortRestoreTaskContext();\r
+ }\r
+\r
+ /* Will only get here if vTaskStartScheduler() was called with the CPU in\r
+ a non-privileged mode or the binary point register was not set to its lowest\r
+ possible value. prvTaskExitError() is referenced to prevent a compiler\r
+ warning about it being defined but not referenced in the case that the user\r
+ defines their own exit address. */\r
+ ( void ) prvTaskExitError;\r
+ return 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vPortEndScheduler( void )\r
+{\r
+ /* Not implemented in ports where there is nothing to return to.\r
+ Artificially force an assert. */\r
+ configASSERT( ulCriticalNesting == 1000UL );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vPortEnterCritical( void )\r
+{\r
+ portDISABLE_INTERRUPTS();\r
+\r
+ /* Now interrupts are disabled ulCriticalNesting can be accessed\r
+ directly. Increment ulCriticalNesting to keep a count of how many times\r
+ portENTER_CRITICAL() has been called. */\r
+ ulCriticalNesting++;\r
+\r
+ /* This is not the interrupt safe version of the enter critical function so\r
+ assert() if it is being called from an interrupt context. Only API\r
+ functions that end in "FromISR" can be used in an interrupt. Only assert if\r
+ the critical nesting count is 1 to protect against recursive calls if the\r
+ assert function also uses a critical section. */\r
+ if( ulCriticalNesting == 1 )\r
+ {\r
+ configASSERT( ulPortInterruptNesting == 0 );\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vPortExitCritical( void )\r
+{\r
+ if( ulCriticalNesting > portNO_CRITICAL_NESTING )\r
+ {\r
+ /* Decrement the nesting count as the critical section is being\r
+ exited. */\r
+ ulCriticalNesting--;\r
+\r
+ /* If the nesting level has reached zero then all interrupt\r
+ priorities must be re-enabled. */\r
+ if( ulCriticalNesting == portNO_CRITICAL_NESTING )\r
+ {\r
+ /* Critical nesting has reached zero so all interrupt priorities\r
+ should be unmasked. */\r
+ portENABLE_INTERRUPTS();\r
+ }\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FreeRTOS_Tick_Handler( void )\r
+{\r
+uint32_t ulInterruptStatus;\r
+\r
+ ulInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
+\r
+ /* Increment the RTOS tick. */\r
+ if( xTaskIncrementTick() != pdFALSE )\r
+ {\r
+ ulPortYieldRequired = pdTRUE;\r
+ }\r
+\r
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( ulInterruptStatus );\r
+\r
+ configCLEAR_TICK_INTERRUPT();\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vPortTaskUsesFPU( void )\r
+{\r
+#if configFPU == 1\r
+uint32_t ulInitialFPSCR = 0;\r
+\r
+ /* A task is registering the fact that it needs an FPU context. Set the\r
+ FPU flag (which is saved as part of the task context). */\r
+ ulPortTaskHasFPUContext = pdTRUE;\r
+\r
+ /* Initialise the floating point status register. */\r
+ __asm volatile ( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) );\r
+#else\r
+ /* If FreeRTOS was built without FPU support but a task is using the FPU, we have a problem */\r
+ configASSERT( 0 );\r
+#endif\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+\r