FreeRTOS-Kernel/portable/ThirdParty/XCC/Xtensa/port.c
Joseph Julicher 989bc332b2
Feature: SMP (#278)
* Add XMOS XCore ports

Some minor modifications are also made to the kernel to support the
XCore compiler's automatic stack size calculation.

* Update kernel to support SMP

The XMOS XCore ports are also updated to support SMP.

* Fix compiler warnings in xcore ports

The port set and clear interrupt mask from ISR macros were removed from
the ports so that the default macros found in FreeRTOS.h are used
instead. The default macros do not result in warnings when they are
used.

* Remove inline function from timers.h

Inline function converted to macro. This should now build when
optimizations are off and inlining is disabled.

* Fix compiler warnings in xcore ports and tasks.c

* fixed documentation for ulTaskNotifyTake() and ulTaskNotifyTakeIndexed()

* spelling fixes for tasks.c

Co-authored-by: Michael Bruno <mikeb@xmos.com>
2021-03-15 17:29:08 -07:00

231 lines
8.2 KiB
C

/*
* FreeRTOS Kernel V10.4.3
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. 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. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* 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.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
* 1 tab == 4 spaces!
*/
/*
* Copyright (c) 2015-2019 Cadence Design Systems, Inc.
*
* 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.
*/
#include <stdlib.h>
#include <xtensa/config/core.h>
#include "xtensa_rtos.h"
#include "FreeRTOS.h"
#include "task.h"
/* Defined in portasm.h */
extern void _frxt_tick_timer_init(void);
/* Defined in xtensa_context.S */
extern void _xt_coproc_init(void);
/*-----------------------------------------------------------*/
/* We require the address of the pxCurrentTCB variable, but don't want to know
any details of its type. */
typedef void TCB_t;
extern volatile TCB_t * volatile pxCurrentTCB;
unsigned port_xSchedulerRunning = 0; // Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting
unsigned port_interruptNesting = 0; // Interrupt nesting level
/*-----------------------------------------------------------*/
// User exception dispatcher when exiting
void _xt_user_exit(void);
/*
* Stack initialization
*/
#if portUSING_MPU_WRAPPERS
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged )
#else
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
#endif
{
StackType_t * sp, * tp;
XtExcFrame * frame;
#if XCHAL_CP_NUM > 0
uint32_t * p;
#endif
/* Create interrupt stack frame aligned to 16 byte boundary */
sp = ( StackType_t * ) ( ( ( UBaseType_t ) pxTopOfStack - XT_CP_SIZE - XT_STK_FRMSZ ) & ~0xf );
/* Clear the entire frame (do not use memset() because we don't depend on C library) */
for( tp = sp; tp <= pxTopOfStack; ++tp )
{
*tp = 0;
}
frame = ( XtExcFrame * ) sp;
/* Explicitly initialize certain saved registers */
frame->pc = ( UBaseType_t ) pxCode; /* task entrypoint */
frame->a0 = 0; /* to terminate GDB backtrace */
frame->a1 = ( UBaseType_t ) sp + XT_STK_FRMSZ; /* physical top of stack frame */
frame->exit = ( UBaseType_t ) _xt_user_exit; /* user exception exit dispatcher */
/* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */
/* Also set entry point argument parameter. */
#ifdef __XTENSA_CALL0_ABI__
frame->a2 = ( UBaseType_t ) pvParameters;
frame->ps = PS_UM | PS_EXCM;
#else
/* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */
frame->a6 = ( UBaseType_t ) pvParameters;
frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC( 1 );
#endif
#ifdef XT_USE_SWPRI
/* Set the initial virtual priority mask value to all 1's. */
frame->vpri = 0xFFFFFFFF;
#endif
#if XCHAL_CP_NUM > 0
/* Init the coprocessor save area (see xtensa_context.h) */
/* No access to TCB here, so derive indirectly. Stack growth is top to bottom.
* //p = (uint32_t *) xMPUSettings->coproc_area;
*/
p = ( uint32_t * ) ( ( ( uint32_t ) pxTopOfStack - XT_CP_SIZE ) & ~0xf );
configASSERT( ( uint32_t ) p >= frame->a1 );
p[ 0 ] = 0;
p[ 1 ] = 0;
p[ 2 ] = ( ( ( uint32_t ) p ) + 12 + XCHAL_TOTAL_SA_ALIGN - 1 ) & -XCHAL_TOTAL_SA_ALIGN;
#endif
return sp;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* It is unlikely that the Xtensa port will get stopped. If required simply
disable the tick interrupt here. */
}
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void )
{
// Interrupts are disabled at this point and stack contains PS with enabled interrupts when task context is restored
#if XCHAL_CP_NUM > 0
/* Initialize co-processor management for tasks. Leave CPENABLE alone. */
_xt_coproc_init();
#endif
/* Init the tick divisor value */
_xt_tick_divisor_init();
/* Setup the hardware to generate the tick. */
_frxt_tick_timer_init();
#if XT_USE_THREAD_SAFE_CLIB
// Init C library
vPortClibInit();
#endif
port_xSchedulerRunning = 1;
// Cannot be directly called from C; never returns
__asm__ volatile ("call0 _frxt_dispatch\n");
/* Should not get here. */
return pdTRUE;
}
/*-----------------------------------------------------------*/
BaseType_t xPortSysTickHandler( void )
{
BaseType_t ret;
uint32_t interruptMask;
portbenchmarkIntLatency();
/* Interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY must be
* disabled before calling xTaskIncrementTick as it access the
* kernel lists. */
interruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
{
ret = xTaskIncrementTick();
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( interruptMask );
portYIELD_FROM_ISR( ret );
return ret;
}
/*-----------------------------------------------------------*/
/*
* Used to set coprocessor area in stack. Current hack is to reuse MPU pointer for coprocessor area.
*/
#if portUSING_MPU_WRAPPERS
void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
const struct xMEMORY_REGION * const xRegions,
StackType_t * pxBottomOfStack,
uint32_t ulStackDepth )
{
#if XCHAL_CP_NUM > 0
xMPUSettings->coproc_area = ( StackType_t * ) ( ( uint32_t ) ( pxBottomOfStack + ulStackDepth - 1 ));
xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) xMPUSettings->coproc_area ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( uint32_t ) xMPUSettings->coproc_area - XT_CP_SIZE ) & ~0xf );
/* NOTE: we cannot initialize the coprocessor save area here because FreeRTOS is going to
* clear the stack area after we return. This is done in pxPortInitialiseStack().
*/
#endif
}
#endif /* if portUSING_MPU_WRAPPERS */