Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FreeRTOS/FreeRTOS-Kernel-Partner-Supported-Ports.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'TI/CORTEX_A53_64-BIT_TI_AM64_SMP/port.c')
-rw-r--r--TI/CORTEX_A53_64-BIT_TI_AM64_SMP/port.c401
1 files changed, 401 insertions, 0 deletions
diff --git a/TI/CORTEX_A53_64-BIT_TI_AM64_SMP/port.c b/TI/CORTEX_A53_64-BIT_TI_AM64_SMP/port.c
new file mode 100644
index 0000000..5a84b6e
--- /dev/null
+++ b/TI/CORTEX_A53_64-BIT_TI_AM64_SMP/port.c
@@ -0,0 +1,401 @@
+/*
+ * FreeRTOS Kernel <DEVELOPMENT BRANCH>
+ * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. 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.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+/*
+ * Copyright (C) 2018-2022 Texas Instruments Incorporated
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Standard includes. */
+#include <stdlib.h>
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+#include <kernel/dpl/ClockP.h>
+#include <drivers/hw_include/cslr.h>
+
+#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
+ /* Check the configuration. */
+ #if( configMAX_PRIORITIES > 32 )
+ #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.
+ #endif
+#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
+
+/* A critical section is exited when the critical section nesting count reaches
+this value. */
+#define portNO_CRITICAL_NESTING ( ( size_t ) 0 )
+
+/* Tasks are not created with a floating point context, but can be given a
+floating point context after they have been created. A variable is stored as
+part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
+does not have an FPU context, or any other value if the task does have an FPU
+context. */
+#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
+
+/* Constants required to setup the initial task context. */
+#define portSP_EL0 ( ( StackType_t ) 0x00 )
+#define portEL1 ( ( StackType_t ) 0x04 )
+#define portINITIAL_PSTATE ( portEL1 | portSP_EL0 )
+
+/* Masks all bits in the APSR other than the mode bits. */
+#define portAPSR_MODE_BITS_MASK ( 0x0C )
+
+/*
+ * Starts the first task executing. This function is necessarily written in
+ * assembly code so is implemented in portASM.s.
+ */
+extern void vPortRestoreTaskContext( void );
+
+/* Saved as part of the task context. If ullPortTaskHasFPUContext is non-zero
+then floating point context must be saved and restored for the task. */
+volatile uint64_t ullPortTaskHasFPUContext[configNUM_CORES] = {pdFALSE};
+
+/* Set to 1 to pend a context switch from an ISR. */
+uint64_t ullPortYieldRequired[configNUM_CORES] = { pdFALSE };
+
+/* Counts the interrupt nesting depth. A context switch is only performed if
+if the nesting depth is 0. */
+uint64_t ullPortInterruptNesting[configNUM_CORES] = { 0 };
+
+/* flag to control tick ISR handling, this is made true just before schedular start */
+volatile uint64_t ullPortSchedularRunning = pdFALSE;
+
+#define portPRIORITY_SHIFT 4
+__attribute__(( used )) const uint64_t ullMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
+
+/*
+ * See header file for description.
+ */
+StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
+{
+ /* Setup the initial stack of the task. The stack is set exactly as
+ expected by the portRESTORE_CONTEXT() macro. */
+
+ /* First all the general purpose registers. */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x0101010101010101ULL; /* R1 */
+ pxTopOfStack--;
+ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x0303030303030303ULL; /* R3 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x0202020202020202ULL; /* R2 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x0505050505050505ULL; /* R5 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x0404040404040404ULL; /* R4 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x0707070707070707ULL; /* R7 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x0606060606060606ULL; /* R6 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x0909090909090909ULL; /* R9 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x0808080808080808ULL; /* R8 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x1111111111111111ULL; /* R11 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x1010101010101010ULL; /* R10 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x1313131313131313ULL; /* R13 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x1212121212121212ULL; /* R12 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x1515151515151515ULL; /* R15 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x1414141414141414ULL; /* R14 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x1717171717171717ULL; /* R17 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x1616161616161616ULL; /* R16 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x1919191919191919ULL; /* R19 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x1818181818181818ULL; /* R18 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x2121212121212121ULL; /* R21 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x2020202020202020ULL; /* R20 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x2323232323232323ULL; /* R23 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x2222222222222222ULL; /* R22 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x2525252525252525ULL; /* R25 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x2424242424242424ULL; /* R24 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x2727272727272727ULL; /* R27 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x2626262626262626ULL; /* R26 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x2929292929292929ULL; /* R29 */
+ pxTopOfStack--;
+ *pxTopOfStack = 0x2828282828282828ULL; /* R28 */
+ pxTopOfStack--;
+ *pxTopOfStack = ( StackType_t ) 0x00; /* XZR - has no effect, used so there are an even number of registers. */
+ pxTopOfStack--;
+ *pxTopOfStack = ( StackType_t ) 0x00; /* R30 - procedure call link register. */
+ pxTopOfStack--;
+
+ *pxTopOfStack = portINITIAL_PSTATE;
+ pxTopOfStack--;
+
+ *pxTopOfStack = ( StackType_t ) pxCode; /* Exception return address. */
+ pxTopOfStack--;
+
+ /* The task will start with a critical nesting count of 0 as interrupts are
+ enabled. */
+ *pxTopOfStack = portNO_CRITICAL_NESTING;
+ pxTopOfStack--;
+
+ /* The task will start without a floating point context. A task that uses
+ the floating point hardware must call vPortTaskUsesFPU() before executing
+ any floating point instructions. */
+ *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
+
+ return pxTopOfStack;
+}
+
+BaseType_t xPortStartScheduler( void )
+{
+ uint32_t ulAPSR;
+
+ __asm volatile ( "MRS %0, CurrentEL" : "=r" ( ulAPSR ) );
+ ulAPSR &= portAPSR_MODE_BITS_MASK;
+
+ configASSERT( ulAPSR == portEL1 );
+ if( ulAPSR == portEL1 )
+ {
+ /* Interrupts are turned off in the CPU itself to ensure a tick does
+ not execute while the scheduler is being started. Interrupts are
+ automatically turned back on in the CPU when the first task starts
+ executing. */
+ portDISABLE_INTERRUPTS();
+
+ if (0 == portGET_CORE_ID())
+ {
+ ullPortSchedularRunning = pdTRUE;
+ }
+
+ /* Start the first task executing. */
+ vPortRestoreTaskContext();
+ }
+
+ return 0;
+}
+
+void vPortEndScheduler( void )
+{
+ /* Not implemented in ports where there is nothing to return to.
+ Artificially force an assert. */
+ configASSERT( 0 );
+}
+
+void vPortTimerTickHandler()
+{
+ if( ullPortSchedularRunning == pdTRUE )
+ {
+ /* Increment the RTOS tick. */
+ if( xTaskIncrementTick() != pdFALSE )
+ {
+ ullPortYieldRequired[portGET_CORE_ID()] = pdTRUE;
+ }
+ }
+}
+
+void vPortTaskUsesFPU( void )
+{
+ /* A task is registering the fact that it needs an FPU context. Set the
+ FPU flag (which is saved as part of the task context). */
+ ullPortTaskHasFPUContext[portGET_CORE_ID()] = pdTRUE;
+
+ /* Consider initialising the FPSR here - but probably not necessary in
+ AArch64. */
+}
+
+/* configCHECK_FOR_STACK_OVERFLOW is set to 1, so the application must provide an
+ * implementation of vApplicationStackOverflowHook()
+ */
+void vApplicationStackOverflowHook( TaskHandle_t xTask,
+ char * pcTaskName )
+{
+ DebugP_logError("[FreeRTOS] Stack overflow detected for task [%s]", pcTaskName);
+ DebugP_assertNoLog(0);
+}
+
+static StaticTask_t xIdleTaskTCB;
+static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
+/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an
+ * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
+ * used by the Idle task.
+ */
+void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
+ StackType_t **ppxIdleTaskStackBuffer,
+ uint32_t *pulIdleTaskStackSize )
+{
+ /* Pass out a pointer to the StaticTask_t structure in which the Idle task’s
+ * state will be stored.
+ */
+ *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
+
+ /* Pass out the array that will be used as the Idle task’s stack. */
+ *ppxIdleTaskStackBuffer = uxIdleTaskStack;
+
+ /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
+ * Note that, as the array is necessarily of type StackType_t,
+ * configMINIMAL_STACK_SIZE is specified in words, not bytes.
+ */
+ *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
+}
+
+static StaticTask_t xTimerTaskTCB;
+static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
+/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
+ * application must provide an implementation of vApplicationGetTimerTaskMemory()
+ * to provide the memory that is used by the Timer service task.
+ */
+void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
+ StackType_t **ppxTimerTaskStackBuffer,
+ uint32_t *pulTimerTaskStackSize )
+{
+ /* Pass out a pointer to the StaticTask_t structure in which the Timer
+ * task’s state will be stored.
+ */
+ *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
+
+ /* Pass out the array that will be used as the Timer task’s stack. */
+ *ppxTimerTaskStackBuffer = uxTimerTaskStack;
+
+ /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
+ * Note that, as the array is necessarily of type StackType_t,
+ * configTIMER_TASK_STACK_DEPTH is specified in words, not bytes.
+ */
+ *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
+}
+
+/* This function is called when configUSE_IDLE_HOOK is 1 in FreeRTOSConfig.h */
+void vApplicationIdleHook( void )
+{
+ void vApplicationLoadHook();
+
+ vApplicationLoadHook();
+
+ __asm__ volatile ("wfi");
+}
+
+/* This function is called when configUSE_MINIMAL_IDLE_HOOK is 1 in FreeRTOSConfig.h */
+void vApplicationMinimalIdleHook( void )
+{
+ void vApplicationLoadHook();
+
+ vApplicationLoadHook();
+
+ __asm__ volatile ("wfi");
+}
+
+/* initialize high resolution timer for CPU and task load calculation */
+void vPortConfigTimerForRunTimeStats()
+{
+ /* we assume clock is initialized before the schedular is started */
+}
+
+/* return current counter value of high speed counter in units of usecs */
+uint32_t uiPortGetRunTimeCounterValue()
+{
+ uint64_t timeInUsecs = ClockP_getTimeUsec();
+
+ /* note, there is no overflow protection for this 32b value in FreeRTOS
+ *
+ * This value will overflow in
+ * ((0xFFFFFFFF)/(1000000*60)) minutes ~ 71 minutes
+ *
+ * We call vApplicationLoadHook() in idle loop to accumlate the task load into a 64b value.
+ * The implementation of vApplicationLoadHook() is in source\kernel\freertos\dpl\common\TaskP_freertos.c
+ */
+ return (uint32_t)(timeInUsecs);
+}
+
+int32_t Signal_coreIntr( CSL_gic500_gicrRegs *pGic500GicrRegs, uint32_t coreId, uint32_t intrNum )
+{
+ if ( coreId < configNUM_CORES )
+ {
+ if ( intrNum < HWIP_GICD_SGI_PPI_INTR_ID_MAX )
+ {
+ uint32_t mask = 1 << intrNum;
+ pGic500GicrRegs->CORE[coreId].SGI_PPI.ISPENDR0 = mask;
+ }
+ }
+
+ __asm("dsb sy");
+
+ return SystemP_SUCCESS;
+}
+
+/* Read 64b value shared between cores */
+uint64_t Get_64(volatile uint64_t* x)
+{
+ __asm("dsb sy");
+ return *x;
+}
+
+/* Write 64b value shared between cores */
+void Set_64(volatile uint64_t* x, uint64_t value)
+{
+ *x = value;
+ __asm("dsb sy");
+}
+