blob: 964ddd96c124bbe808df7fd280f5a62ea6d4ad89 [file] [log] [blame]
/*
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
*
* SPDX-License-Identifier: MIT
*
* 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.
*
*/
/* 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(;;);
}