/* * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * 1 tab == 4 spaces! */ /* Kernel includes. */ #include "FreeRTOS.h" #include "task.h" extern void vPortStartTask(void); /* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This will be set to 0 prior to the first task being started. */ portLONG ulCriticalNesting = 0x9999UL; /* Used to record one tack want to swtich task after enter critical area, we need know it * and implement task switch after exit critical area */ portLONG pendsvflag = 0; StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) { StackType_t *stk = NULL; stk = pxTopOfStack; *(--stk) = (uint32_t)pxCode; /* Entry Point */ *(--stk) = (uint32_t)0xE0000140L; /* PSR */ *(--stk) = (uint32_t)0xFFFFFFFEL; /* R15 (LR) (init value will cause fault if ever used) */ *(--stk) = (uint32_t)0x13131313L; /* R13 */ *(--stk) = (uint32_t)0x12121212L; /* R12 */ *(--stk) = (uint32_t)0x11111111L; /* R11 */ *(--stk) = (uint32_t)0x10101010L; /* R10 */ *(--stk) = (uint32_t)0x09090909L; /* R9 */ *(--stk) = (uint32_t)0x08080808L; /* R8 */ *(--stk) = (uint32_t)0x07070707L; /* R7 */ *(--stk) = (uint32_t)0x06060606L; /* R6 */ *(--stk) = (uint32_t)0x05050505L; /* R5 */ *(--stk) = (uint32_t)0x04040404L; /* R4 */ *(--stk) = (uint32_t)0x03030303L; /* R3 */ *(--stk) = (uint32_t)0x02020202L; /* R2 */ *(--stk) = (uint32_t)0x01010101L; /* R1 */ *(--stk) = (uint32_t)pvParameters; /* R0 : argument */ return stk; } BaseType_t xPortStartScheduler( void ) { ulCriticalNesting = 0UL; vPortStartTask(); return pdFALSE; } void vPortEndScheduler( void ) { /* Not implemented as there is nothing to return to. */ } void vPortEnterCritical( void ) { portDISABLE_INTERRUPTS(); ulCriticalNesting ++; } void vPortExitCritical( void ) { if (ulCriticalNesting == 0) { while(1); } ulCriticalNesting --; if (ulCriticalNesting == 0) { portENABLE_INTERRUPTS(); if (pendsvflag) { pendsvflag = 0; portYIELD(); } } } #if configUSE_PREEMPTION == 0 void xPortSysTickHandler( void ) { portLONG ulDummy; ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); xTaskIncrementTick(); portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); } #else void xPortSysTickHandler( void ) { portLONG ulDummy; ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); { if (xTaskIncrementTick() != pdFALSE) { portYIELD_FROM_ISR(pdTRUE); } } portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); } #endif void vPortYieldHandler( void ) { uint32_t ulSavedInterruptMask; ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR(); vTaskSwitchContext(); portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask ); } __attribute__((weak)) void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName ) { for(;;); } __attribute__((weak)) void vApplicationMallocFailedHook( void ) { for(;;); }