diff options
author | anoop-rk97 <118251858+anoop-rk97@users.noreply.github.com> | 2022-11-21 16:57:58 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-21 16:57:58 +0300 |
commit | a21d142d3c615181cedc8f164b8d3aedb66d7894 (patch) | |
tree | 00ba874f4dfc7a38bf38bab91100c655b1f70d0d | |
parent | 3f9c99a682c5c796bb7eb89fd9c4385688fce27a (diff) |
Add ARM A53 SMP kernel port for TI-Sitara-AM64x device. (#7)
Signed-off-by: Anoop <anoop.rk@ti.com>
Signed-off-by: Anoop <anoop.rk@ti.com>
-rw-r--r-- | TI/CORTEX_A53_64-BIT_TI_AM64_SMP/port.c | 401 | ||||
-rw-r--r-- | TI/CORTEX_A53_64-BIT_TI_AM64_SMP/portASM.S | 602 | ||||
-rw-r--r-- | TI/CORTEX_A53_64-BIT_TI_AM64_SMP/portmacro.h | 294 |
3 files changed, 1297 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"); +} + diff --git a/TI/CORTEX_A53_64-BIT_TI_AM64_SMP/portASM.S b/TI/CORTEX_A53_64-BIT_TI_AM64_SMP/portASM.S new file mode 100644 index 0000000..266fd97 --- /dev/null +++ b/TI/CORTEX_A53_64-BIT_TI_AM64_SMP/portASM.S @@ -0,0 +1,602 @@ +/* + * 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. + */ + + .text + + /* Variables and functions. */ + .extern vTaskSwitchContext + .extern HwiP_intrHandler + .extern ullPortInterruptNesting + .extern ullPortTaskHasFPUContext + .extern ullPortYieldRequired + + .global HwiP_IRQ_Handler + .global HwiP_SVC_Handler + .global vPortRestoreTaskContext + .global HwiP_defaultExcHandler + .global HwiP_abortHandler + +.macro PUSH_ALL_CPU_REGS stackPtr + stp x0, x1, [\stackPtr, #-16]! + stp x2, x3, [\stackPtr, #-16]! + stp x4, x5, [\stackPtr, #-16]! + stp x6, x7, [\stackPtr, #-16]! + stp x8, x9, [\stackPtr, #-16]! + stp x10, x11, [\stackPtr, #-16]! + stp x12, x13, [\stackPtr, #-16]! + stp x14, x15, [\stackPtr, #-16]! + stp x16, x17, [\stackPtr, #-16]! + stp x18, x19, [\stackPtr, #-16]! + stp x20, x21, [\stackPtr, #-16]! + stp x22, x23, [\stackPtr, #-16]! + stp x24, x25, [\stackPtr, #-16]! + stp x26, x27, [\stackPtr, #-16]! + stp x28, x29, [\stackPtr, #-16]! + stp x30, xzr, [\stackPtr, #-16]! +.endm + +.macro POP_ALL_CPU_REGS stackPtr + LDP X30, XZR, [\stackPtr], #0x10 + LDP X28, X29, [\stackPtr], #0x10 + LDP X26, X27, [\stackPtr], #0x10 + LDP X24, X25, [\stackPtr], #0x10 + LDP X22, X23, [\stackPtr], #0x10 + LDP X20, X21, [\stackPtr], #0x10 + LDP X18, X19, [\stackPtr], #0x10 + LDP X16, X17, [\stackPtr], #0x10 + LDP X14, X15, [\stackPtr], #0x10 + LDP X12, X13, [\stackPtr], #0x10 + LDP X10, X11, [\stackPtr], #0x10 + LDP X8, X9, [\stackPtr], #0x10 + LDP X6, X7, [\stackPtr], #0x10 + LDP X4, X5, [\stackPtr], #0x10 + LDP X2, X3, [\stackPtr], #0x10 + LDP X0, X1, [\stackPtr], #0x10 +.endm + +.macro PUSH_CALLER_SAVE_CPU_REGS stackPtr + stp x0, x1, [\stackPtr, #-16]! + stp x2, x3, [\stackPtr, #-16]! + stp x4, x5, [\stackPtr, #-16]! + stp x6, x7, [\stackPtr, #-16]! + stp x8, x9, [\stackPtr, #-16]! + stp x10, x11, [\stackPtr, #-16]! + stp x12, x13, [\stackPtr, #-16]! + stp x14, x15, [\stackPtr, #-16]! + stp x16, x17, [\stackPtr, #-16]! + stp x18, x19, [\stackPtr, #-16]! + stp x29, x30, [\stackPtr, #-16]! +.endm + +.macro POP_CALLER_SAVE_CPU_REGS stackPtr + ldp x29, x30, [\stackPtr], #16 + ldp x18, x19, [\stackPtr], #16 + ldp x16, x17, [\stackPtr], #16 + ldp x14, x15, [\stackPtr], #16 + ldp x12, x13, [\stackPtr], #16 + ldp x10, x11, [\stackPtr], #16 + ldp x8, x9, [\stackPtr], #16 + ldp x6, x7, [\stackPtr], #16 + ldp x4, x5, [\stackPtr], #16 + ldp x2, x3, [\stackPtr], #16 + ldp x0, x1, [\stackPtr], #16 +.endm + +.macro PUSH_CALLER_SAVE_FPU_REGS stackPtr + stp q0, q1, [\stackPtr, #-32]! + stp q2, q3, [\stackPtr, #-32]! + stp q4, q5, [\stackPtr, #-32]! + stp q6, q7, [\stackPtr, #-32]! + stp q8, q9, [\stackPtr, #-32]! + stp q10, q11, [\stackPtr, #-32]! + stp q12, q13, [\stackPtr, #-32]! + stp q14, q15, [\stackPtr, #-32]! + stp q16, q17, [\stackPtr, #-32]! + stp q18, q19, [\stackPtr, #-32]! + stp q20, q21, [\stackPtr, #-32]! + stp q22, q23, [\stackPtr, #-32]! + stp q24, q25, [\stackPtr, #-32]! + stp q26, q27, [\stackPtr, #-32]! + stp q28, q29, [\stackPtr, #-32]! + stp q30, q31, [\stackPtr, #-32]! +.endm + +.macro POP_CALLER_SAVE_FPU_REGS stackPtr + ldp q30, q31, [\stackPtr], #32 + ldp q28, q29, [\stackPtr], #32 + ldp q26, q27, [\stackPtr], #32 + ldp q24, q25, [\stackPtr], #32 + ldp q22, q23, [\stackPtr], #32 + ldp q20, q21, [\stackPtr], #32 + ldp q18, q19, [\stackPtr], #32 + ldp q16, q17, [\stackPtr], #32 + ldp q14, q15, [\stackPtr], #32 + ldp q12, q13, [\stackPtr], #32 + ldp q10, q11, [\stackPtr], #32 + ldp q8, q9, [\stackPtr], #32 + ldp q6, q7, [\stackPtr], #32 + ldp q4, q5, [\stackPtr], #32 + ldp q2, q3, [\stackPtr], #32 + ldp q0, q1, [\stackPtr], #32 +.endm + + +.macro portSAVE_CONTEXT + + /* Switch to use the EL0 stack pointer. */ + MSR SPSEL, #0 + + /* Save the entire context. */ + PUSH_ALL_CPU_REGS SP + + /* Save the SPSR. */ + MRS X3, SPSR_EL1 + MRS X2, ELR_EL1 + + STP X2, X3, [SP, #-0x10]! + + /* Get coreId to X1 */ + MRS X1, MPIDR_EL1 + AND X1, X1, #0xff + LDR X0, ullPortTaskHasFPUContextConst + CMP X1, #0 + BEQ 3f + ADD X0, X0, #8 +3: + + /* Save the FPU context indicator. */ + LDR X2, [X0] + + /* Save the FPU context, if any (32 128-bit registers). */ + CMP X2, #0 + B.EQ 1f + PUSH_CALLER_SAVE_FPU_REGS SP + +1: + /* Store the FPU context indicator. */ + STR x2, [SP, #-0x10]! + + LDR X0, pxCurrentTCBConst + + /* Get coreId and choose the corresponding index for core in pxCurrentTCB */ + MRS X1, MPIDR_EL1 + AND X1, X1, #0xff + CMP X1, #0 + B.EQ 2f + ADD X0, X0, #8 + +2: + LDR X1, [X0] + MOV X0, SP /* Move SP into X0 for saving. */ + STR X0, [X1] + + /* Switch to use the ELx stack pointer. */ + MSR SPSEL, #1 + +.endm + +; /**********************************************************************/ + +.macro portRESTORE_CONTEXT + + /* Switch to use the EL0 stack pointer. */ + MSR SPSEL, #0 + + /* Set the SP to point to the stack of the task being restored. */ + LDR X0, pxCurrentTCBConst + + /* Get coreId and choose the corresponding index for core in pxCurrentTCB */ + MRS X1, MPIDR_EL1 + AND X1, X1, #0xff + CMP X1, #0 + B.EQ 2f + ADD X0, X0, #8 + +2: + LDR X1, [X0] + LDR X0, [X1] + MOV SP, X0 + + LDR X2, [SP], #0x10 /* FPU context. */ + + /* Set the PMR register to be correct for the current critical nesting + depth. */ + MOV X1, #255 /* X1 holds the unmask value. */ + + MSR s3_0_c4_c6_0, X1 /* Write the mask value to ICCPMR. s3_0_c4_c6_0 is ICC_PMR_EL1. */ + DSB SY /* _RB_Barriers probably not required here. */ + ISB SY + + /* Get coreId */ + MRS X1, MPIDR_EL1 + AND X1, X1, #0xff + LDR X0, ullPortTaskHasFPUContextConst + BEQ 3f + ADD X0, X0, #8 +3: + + /* Restore the FPU context indicator. */ + STR X2, [X0] + + /* Restore the FPU context, if any. */ + CMP X2, #0 + B.EQ 1f + POP_CALLER_SAVE_FPU_REGS SP +1: + LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */ + + /* Restore the SPSR. */ + MSR SPSR_EL1, X3 + /* Restore the ELR. */ + MSR ELR_EL1, X2 + + POP_ALL_CPU_REGS SP + + /* Switch to use the ELx stack pointer. _RB_ Might not be required. */ + MSR SPSEL, #1 + + ERET + +.endm + +.macro VECTOR_ENTRY name + .align 7 +\name: +.endm + + .global HwiP_gicv3Vectors + .section .vecs, "ax" + .align 11 +HwiP_gicv3Vectors: + +/* + ************************************************************************* + * Exception from currentEL, using SP0 + ************************************************************************* + */ +VECTOR_ENTRY el1SyncSP0 + B HwiP_SVC_Handler + +VECTOR_ENTRY el1IrqSP0 + B HwiP_IRQ_Handler + +VECTOR_ENTRY el1FiqSP0 + b el1FiqSP0 + +VECTOR_ENTRY el1SErrorSP0 + PUSH_ALL_CPU_REGS sp /* save all CPU regs */ + mrs x0, sp_el0 + mrs x1, elr_el1 + mrs x2, spsr_el1 + mrs x3, esr_el1 + stp x0, x1, [sp, #-16]! /* save sp & elr */ + stp x2, x3, [sp, #-16]! /* save spsr and esr */ + mov x0, sp + mov x1, #1 + ldr x2, =HwiP_defaultExcHandler + br x2 + +/* + ************************************************************************* + * Exception from currentEL, using SPx + ************************************************************************* + */ +VECTOR_ENTRY el1SyncSPx + B HwiP_SVC_Handler + +VECTOR_ENTRY el1IrqSPx + B HwiP_IRQ_Handler + +VECTOR_ENTRY el1FiqSPx + b el1FiqSPx + +VECTOR_ENTRY el1SErrorSPx + PUSH_ALL_CPU_REGS sp /* save all CPU regs */ + add x0, sp, #256 /* compute original SP */ + mrs x1, elr_el1 + mrs x2, spsr_el1 + mrs x3, esr_el1 + stp x0, x1, [sp, #-16]! /* save sp & elr */ + stp x2, x3, [sp, #-16]! /* save spsr and esr */ + mov x0, sp + mov x1, #1 + ldr x2, =HwiP_defaultExcHandler + br x2 + +/* + ************************************************************************* + * Exception from lowerEL, all lowerEL using Aarch64 + ************************************************************************* + */ +VECTOR_ENTRY el0SyncAarch64 + b el0SyncAarch64 + +VECTOR_ENTRY el0IrqAarch64 + b el0IrqAarch64 + +VECTOR_ENTRY el0FiqAarch64 + b el0FiqAarch64 + +VECTOR_ENTRY el0SErrorAarch64 + b el0SErrorAarch64 + +/* + ************************************************************************* + * Exception from lowerEL, all lowerEL using Aarch32 + ************************************************************************* + */ +VECTOR_ENTRY el0SyncAarch32 + b el0SyncAarch32 + +VECTOR_ENTRY el0IrqAarch32 + b el0IrqAarch32 + +VECTOR_ENTRY el0FiqAarch32 + b el0FiqAarch32 + +VECTOR_ENTRY el0SErrorAarch32 + b el0SErrorAarch32 + + +/****************************************************************************** + * vPortRestoreTaskContext is used to start the scheduler. + *****************************************************************************/ +.align 8 +.type vPortRestoreTaskContext, %function +vPortRestoreTaskContext: + DSB SY + ISB SY + /* Start the first task. */ + portRESTORE_CONTEXT + +/****************************************************************************** + * handles SVC entry and exit. + *****************************************************************************/ +.align 8 +.type HwiP_SVC_Handler, %function +HwiP_SVC_Handler: + /* Save the context of the current task and select a new task to run. */ + portSAVE_CONTEXT + MRS X0, ESR_EL1 + MRS X2, ELR_EL1 + LSR X1, X0, #26 + CMP X1, #0x15 /* 0x15 = SVC instruction. */ + B.NE HwiP_SVC_Abort + MRS x0, mpidr_el1 /* Get CoreID */ + and x0, x0, #0xff + BL vTaskSwitchContext + portRESTORE_CONTEXT +HwiP_SVC_Abort: + /* Full ESR is in X0, exception class code is in X1. */ + B . + +/****************************************************************************** + * handles IRQ entry and exit. + *****************************************************************************/ +.align 8 +.type HwiP_IRQ_Handler, %function +HwiP_IRQ_Handler: + /* save cpu scratch regs */ + PUSH_CALLER_SAVE_CPU_REGS SP + + /* Save the SPSR and ELR. */ + MRS X3, SPSR_EL1 + MRS X2, ELR_EL1 + STP X2, X3, [SP, #-0x10]! + + /* Increment the interrupt nesting counter. */ + LDR X5, ullPortInterruptNestingConst + + /* Get coreId and choose the corresponding index for core in ullPortInterruptNesting */ + MRS X1, MPIDR_EL1 + AND X1, X1, #0xff + CMP X1, #0 + B.EQ 2f + ADD X5, X5, #8 +2: + LDR X1, [X5] /* Old nesting count in X1. */ + ADD X6, X1, #1 + STR X6, [X5] /* Address of nesting count variable in X5. */ + + /* Maintain the interrupt nesting information across the function call. */ + STP X1, X5, [SP, #-0x10]! + + /* Call the C handler. */ + BL HwiP_intrHandler + + /* Disable interrupts. */ + MSR DAIFSET, #2 + DSB SY + ISB SY + + /* Restore the critical nesting count. */ + LDP X1, X5, [SP], #0x10 + STR X1, [X5] + + /* Has interrupt nesting unwound? */ + CMP X1, #0 + B.NE Exit_IRQ_No_Context_Switch + + /* Is a context switch required? */ + LDR X0, ullPortYieldRequiredConst + + /* Get coreId and choose the corresponding index for core in ullPortYieldRequired */ + MRS X1, MPIDR_EL1 + AND X1, X1, #0xff + CMP X1, #0 + B.EQ 2f + ADD X0, X0, #8 +2: + LDR X1, [X0] + CMP X1, #0 + B.EQ Exit_IRQ_No_Context_Switch + + /* Reset ullPortYieldRequired to 0. */ + MOV X2, #0 + STR X2, [X0] + + /* Restore volatile registers. */ + LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */ + MSR SPSR_EL1, X5 + MSR ELR_EL1, X4 + DSB SY + ISB SY + + POP_CALLER_SAVE_CPU_REGS SP + + /* Save the context of the current task and select a new task to run. */ + portSAVE_CONTEXT + MRS x0, mpidr_el1 /* Get CoreID */ + and x0, x0, #0xff + BL vTaskSwitchContext + portRESTORE_CONTEXT + +Exit_IRQ_No_Context_Switch: + /* Restore volatile registers. */ + LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */ + MSR SPSR_EL1, X5 + MSR ELR_EL1, X4 + DSB SY + ISB SY + + POP_CALLER_SAVE_CPU_REGS SP + + ERET + +/* + * Void HwiP_defaultExcHandler(uint32_t usingEL0Stack); + */ + .section .text.HwiP_defaultExcHandler, "ax" + .func HwiP_defaultExcHandler +HwiP_defaultExcHandler: + + mov x19, x0 /* copy 'usingEL0Stack' argument */ + mrs x0, spsr_el1 + mrs x1, elr_el1 + stp x0, x1, [sp, #-16]! /* save spsr_el1 and elr_el1 */ +#if defined(__ARM_FP) + mrs x0, fpcr + mrs x1, fpsr + stp x0, x1, [sp, #-16]! /* save fpcr and fpsr */ +#endif + + /* call dispatch default handler */ + mrs x0, elr_el1 /* pass IRP to dispatchIRQC() */ + ldr x1, =HwiP_defaultHandler + blr x1 + + /* returns with interrupts disabled */ +#if defined(__ARM_FP) + ldp x0, x1, [sp], #16 + msr fpcr, x0 + msr fpsr, x1 +#endif + ldp x0, x1, [sp], #16 + msr spsr_el1, x0 + msr elr_el1, x1 +#if defined(__ARM_FP) + POP_CALLER_SAVE_FPU_REGS sp /* restore vfp scratch regs */ +#endif + POP_CALLER_SAVE_CPU_REGS sp /* restore cpu scratch regs */ + eret + +.align 8 + +/* + * int32_t GateSmp_tryLock(uintptr_t gateWord); + */ + .global GateSmp_tryLock + .type GateSmp_tryLock , %function +GateSmp_tryLock: + ldxr w1, [x0] + cmp w1, #1 /* is locked already? */ + beq 1f /* if so, leave with fail */ + + mov w2, #1 /* locked = 1 */ + stxr w1, w2, [x0] /* if so attempt to grab it */ + cmp w1, #0 /* did we get it? zero is yes */ + /* if not, loop while in contention */ + bne GateSmp_tryLock +1: + mov w0, w1 + dmb sy + ret + +/* + * void GateSmp_unlock(uintptr_t gateWord); + */ + .global GateSmp_unlock + .type GateSmp_unlock , %function + +GateSmp_unlock: + dmb sy + + mov w1, #0 + str w1, [x0] + + dsb sy + sev /* let everyone know */ + ret + +pxCurrentTCBConst: .dword pxCurrentTCBs +ullPortTaskHasFPUContextConst: .dword ullPortTaskHasFPUContext +ullPortInterruptNestingConst: .dword ullPortInterruptNesting +ullPortYieldRequiredConst: .dword ullPortYieldRequired + +.end diff --git a/TI/CORTEX_A53_64-BIT_TI_AM64_SMP/portmacro.h b/TI/CORTEX_A53_64-BIT_TI_AM64_SMP/portmacro.h new file mode 100644 index 0000000..126b9ff --- /dev/null +++ b/TI/CORTEX_A53_64-BIT_TI_AM64_SMP/portmacro.h @@ -0,0 +1,294 @@ +/* + * FreeRTOS Kernel V10.4.3 + * Copyright (C) 2020 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. + * + * 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) 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. + */ + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include <kernel/dpl/HwiP.h> +#include <kernel/a53/HwiP_armv8_gic.h> +#include <kernel/a53/common_armv8.h> + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the given hardware + * and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE size_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef portBASE_TYPE BaseType_t; +typedef uint64_t UBaseType_t; + +typedef uint32_t TickType_t; +#define portMAX_DELAY ( ( TickType_t ) 0xffffffff ) + +/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do +not need to be guarded with a critical section. */ +#define portTICK_TYPE_IS_ATOMIC 1 + +/* Hardware specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 16 +#define portPOINTER_SIZE_TYPE uint64_t +#define portCRITICAL_NESTING_IN_TCB 1 + +/* Task utilities. */ + +extern uint64_t ullPortYieldRequired[]; +/* Called at the end of an ISR that can cause a context switch. */ +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ +{ \ + \ + if( xSwitchRequired != pdFALSE ) \ + { \ + ullPortYieldRequired[portGET_CORE_ID()] = pdTRUE; \ + } \ +} + +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() __asm volatile ( "SVC 0" ::: "memory" ) + +/*----------------------------------------------------------- + * Critical section control + *----------------------------------------------------------*/ + +extern void vTaskEnterCritical( void ); +extern void vTaskExitCritical( void ); + +#define portDISABLE_INTERRUPTS() HwiP_disable() +#define portENABLE_INTERRUPTS() HwiP_enable() +#define portENTER_CRITICAL() vTaskEnterCritical(); +#define portEXIT_CRITICAL() vTaskExitCritical(); +#define portSET_INTERRUPT_MASK_FROM_ISR() ({ \ + uint64_t x = HwiP_disable(); \ + vTaskEnterCritical(); \ + x; \ + }) + +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) ({ \ + vTaskExitCritical(); \ + HwiP_restore(x); \ + }) + +/* Task function macros as described on the FreeRTOS.org WEB site. These are +not required for this port but included in case common demo code that uses these +macros is used. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) + +/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU() +before any floating point instructions are executed. */ +void vPortTaskUsesFPU( void ); +#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU() + +/* Architecture specific optimisations. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + + /* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +#define portNOP() __asm volatile( "NOP" ) +#define portINLINE __inline +#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) + +/* port for SMP */ +#define portGET_CORE_ID() Armv8_getCoreId() +#define portRESTORE_INTERRUPTS( ulState ) HwiP_restore ( ulState ) +#define portCHECK_IF_IN_ISR() HwiP_inISR() + +/*----------------------------------------------------------- + * Critical section locks + *----------------------------------------------------------*/ + +#define ISR_LOCK (0u) +#define TASK_LOCK (1u) + +#define portRTOS_LOCK_COUNT 2 +#define portMAX_CORE_COUNT 2 + +#define portRELEASE_ISR_LOCK() vPortRecursiveLock(ISR_LOCK, pdFALSE) +#define portGET_ISR_LOCK() vPortRecursiveLock(ISR_LOCK, pdTRUE) + +#define portRELEASE_TASK_LOCK() vPortRecursiveLock(TASK_LOCK, pdFALSE) +#define portGET_TASK_LOCK() vPortRecursiveLock(TASK_LOCK, pdTRUE) + +/* Interrupt number to interrupt a core for task yield */ +#define YIELD_CORE_INTERRUPT_NO (0U) + +extern int32_t Signal_coreIntr( CSL_gic500_gicrRegs *pGic500GicrRegs, uint32_t coreId, uint32_t intrNum ); + +#define portYIELD_CORE( xCoreID ) do { \ + Signal_coreIntr((CSL_gic500_gicrRegs *) ( HWIP_GIC_BASE_ADDR + \ + CSL_GIC500_GICR_CORE_CONTROL_CTLR(0U)), xCoreID, YIELD_CORE_INTERRUPT_NO); \ + }while(0); + + +uint64_t Get_64(volatile uint64_t* x); +void Set_64(volatile uint64_t* x, uint64_t value); + +/* Which core owns the lock */ +volatile uint64_t ucOwnedByCore[ portMAX_CORE_COUNT ]; +/* Lock count a core owns */ +volatile uint64_t ucRecursionCountByLock[ portRTOS_LOCK_COUNT ]; + +/* Index 0 is used for ISR lock and Index 1 is used for task lock */ +uint32_t GateWord[ portRTOS_LOCK_COUNT ]; + +int32_t GateSmp_tryLock(uint32_t* gateWord); +void GateSmp_unlock(uint32_t* gateWord); + +static inline void vPortRecursiveLock(uint32_t ulLockNum, BaseType_t uxAcquire) +{ + uint32_t ulCoreNum = portGET_CORE_ID(); + uint32_t ulLockBit = 1u << ulLockNum; + + /* Lock acquire */ + if (uxAcquire) + { + + /* Check if spinlock is available */ + /* If spinlock is not available check if the core owns the lock */ + /* If the core owns the lock wait increment the lock count by the core */ + /* If core does not own the lock wait for the spinlock */ + if( GateSmp_tryLock( &GateWord[ulLockNum] ) != 0) + { + /* Check if the core owns the spinlock */ + if( Get_64(&ucOwnedByCore[ulCoreNum]) & ulLockBit ) + { + configASSERT( Get_64(&ucRecursionCountByLock[ulLockNum]) != 255u); + Set_64(&ucRecursionCountByLock[ulLockNum], (Get_64(&ucRecursionCountByLock[ulLockNum])+1)); + return; + } + + /* Preload the gate word into the cache */ + uint32_t dummy = GateWord[ulLockNum]; + dummy++; + + /* Wait for spinlock */ + while( GateSmp_tryLock(&GateWord[ulLockNum]) != 0); + } + + /* Add barrier to ensure lock is taken before we proceed */ + __asm__ __volatile__ ( + "dmb sy" + ::: "memory" + ); + + /* Assert the lock count is 0 when the spinlock is free and is acquired */ + configASSERT(Get_64(&ucRecursionCountByLock[ulLockNum]) == 0); + + /* Set lock count as 1 */ + Set_64(&ucRecursionCountByLock[ulLockNum], 1); + /* Set ucOwnedByCore */ + Set_64(&ucOwnedByCore[ulCoreNum], (Get_64(&ucOwnedByCore[ulCoreNum]) | ulLockBit)); + } + /* Lock release */ + else + { + /* Assert the lock is not free already */ + configASSERT( (Get_64(&ucOwnedByCore[ulCoreNum]) & ulLockBit) != 0 ); + configASSERT( Get_64(&ucRecursionCountByLock[ulLockNum]) != 0 ); + + /* Reduce ucRecursionCountByLock by 1 */ + Set_64(&ucRecursionCountByLock[ulLockNum], (Get_64(&ucRecursionCountByLock[ulLockNum]) - 1) ); + + if( !Get_64(&ucRecursionCountByLock[ulLockNum]) ) + { + Set_64(&ucOwnedByCore[ulCoreNum], (Get_64(&ucOwnedByCore[ulCoreNum]) & ~ulLockBit)); + GateSmp_unlock(&GateWord[ulLockNum]); + /* Add barrier to ensure lock is taken before we proceed */ + __asm__ __volatile__ ( + "dmb sy" + ::: "memory" + ); + } + } +} + +#ifdef __cplusplus + } /* extern C */ +#endif + +#endif /* PORTMACRO_H */ + |