Moved proj up
This commit is contained in:
+13
@@ -0,0 +1,13 @@
|
||||
OVERVIEW
|
||||
|
||||
This directory contains FreeRTOS port for Renesas RH850 F1KM-S4
|
||||
|
||||
The standard demo project to test this port is added at following location:
|
||||
FreeRTOS-Community-Supported-Demos\RH850_F1KM_S4_CCRH
|
||||
|
||||
This port is distributed under MIT open source license.
|
||||
|
||||
TOOL CHAIN SUPPORT:
|
||||
IDE and Coding Tool: e² studio version 07-2023
|
||||
C Compiler Package for RH850 Family [CC-RH] version 2.06.00 for e2 studio.
|
||||
FreeRTOS Kernel V11.0.1
|
||||
+292
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.1
|
||||
* Copyright (C) 2023 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
|
||||
*
|
||||
*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "bsp_common.h"
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Constants required to set up the initial stack. */
|
||||
|
||||
/* Task should start with interrupts enabled and in Supervisor mode, therefore
|
||||
* PSW is set with ID clear. */
|
||||
#define portINITIAL_PSW ((StackType_t) 0x00000000) /* PSW.ID bit */
|
||||
|
||||
#define portSTACK_INITIAL_VALUE_R1 ((StackType_t) 0x01010101UL)
|
||||
#define portSTACK_INITIAL_VALUE_R2 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x02UL)
|
||||
#define portSTACK_INITIAL_VALUE_R3 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x03UL)
|
||||
#define portSTACK_INITIAL_VALUE_R4 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x04UL)
|
||||
#define portSTACK_INITIAL_VALUE_R5 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x05UL)
|
||||
#define portSTACK_INITIAL_VALUE_R6 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x06UL)
|
||||
#define portSTACK_INITIAL_VALUE_R7 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x07UL)
|
||||
#define portSTACK_INITIAL_VALUE_R8 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x08UL)
|
||||
#define portSTACK_INITIAL_VALUE_R9 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x09UL)
|
||||
#define portSTACK_INITIAL_VALUE_R10 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x10UL)
|
||||
#define portSTACK_INITIAL_VALUE_R11 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x11UL)
|
||||
#define portSTACK_INITIAL_VALUE_R12 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x12UL)
|
||||
#define portSTACK_INITIAL_VALUE_R13 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x13UL)
|
||||
#define portSTACK_INITIAL_VALUE_R14 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x14UL)
|
||||
#define portSTACK_INITIAL_VALUE_R15 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x15UL)
|
||||
#define portSTACK_INITIAL_VALUE_R16 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x16UL)
|
||||
#define portSTACK_INITIAL_VALUE_R17 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x17UL)
|
||||
#define portSTACK_INITIAL_VALUE_R18 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x18UL)
|
||||
#define portSTACK_INITIAL_VALUE_R19 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x19UL)
|
||||
#define portSTACK_INITIAL_VALUE_R20 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x20UL)
|
||||
#define portSTACK_INITIAL_VALUE_R21 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x21UL)
|
||||
#define portSTACK_INITIAL_VALUE_R22 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x22UL)
|
||||
#define portSTACK_INITIAL_VALUE_R23 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x23UL)
|
||||
#define portSTACK_INITIAL_VALUE_R24 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x24UL)
|
||||
#define portSTACK_INITIAL_VALUE_R25 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x25UL)
|
||||
#define portSTACK_INITIAL_VALUE_R26 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x26UL)
|
||||
#define portSTACK_INITIAL_VALUE_R27 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x27UL)
|
||||
#define portSTACK_INITIAL_VALUE_R28 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x28UL)
|
||||
#define portSTACK_INITIAL_VALUE_R29 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x29UL)
|
||||
#define portSTACK_INITIAL_VALUE_R30 ((StackType_t) portSTACK_INITIAL_VALUE_R1 * 0x30UL)
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Constants required to set up OSTM0 timer. */
|
||||
|
||||
/* OSTM Count Start Trigger Register (OSTMnTS) */
|
||||
#define portOSTM_COUNTER_START (0x01U) /* Starts the counter */
|
||||
|
||||
/* OSTM Count Stop Trigger Register (OSTMnTT) */
|
||||
#define portOSTM_COUNTER_STOP (0x01U) /* Stops the counter */
|
||||
|
||||
/* OSTM Control Register (OSTMnCTL) */
|
||||
#define portOSTM_MODE_INTERVAL_TIMER (0x00U) /* Interval timer mode */
|
||||
#define portOSTM_MODE_FREE_RUNNING (0x02U) /* Free-running comparison mode */
|
||||
#define portOSTM_START_INTERRUPT_DISABLE (0x00U) /* Disables the interrupts when counting starts */
|
||||
#define portOSTM_START_INTERRUPT_ENABLE (0x01U) /* Enables the interrupts when counting starts */
|
||||
|
||||
/* Interrupt request flag (RFxxx) */
|
||||
#define portINT_REQUEST_NOT_OCCUR (0x0U) /* No interrupt request is made */
|
||||
|
||||
/* Interrupt mask (MKxxx) */
|
||||
#define portINT_PROCESSING_ENABLED (0x0U) /* Enables interrupt processing */
|
||||
#define portINT_PROCESSING_DISABLED (0x1U) /* Disables interrupt processing */
|
||||
|
||||
/* Interrupt vector method select (TBxxx) */
|
||||
#define portINT_DIRECT_VECTOR (0x0U) /* Direct jumping to an address by the level of priority */
|
||||
#define portINT_TABLE_VECTOR (0x1U) /* Table reference */
|
||||
|
||||
/* Specify 16 interrupt priority levels */
|
||||
#define portINT_PRIORITY_HIGHEST (0x00C0U) /* Level 0 (highest) */
|
||||
#define portINT_PRIORITY_LEVEL1 (0x00C1U) /* Level 1 */
|
||||
#define portINT_PRIORITY_LEVEL2 (0x00C2U) /* Level 2 */
|
||||
#define portINT_PRIORITY_LEVEL3 (0x00C3U) /* Level 3 */
|
||||
#define portINT_PRIORITY_LEVEL4 (0x00C4U) /* Level 4 */
|
||||
#define portINT_PRIORITY_LEVEL5 (0x00C5U) /* Level 5 */
|
||||
#define portINT_PRIORITY_LEVEL6 (0x00C6U) /* Level 6 */
|
||||
#define portINT_PRIORITY_LEVEL7 (0x00C7U) /* Level 7 */
|
||||
#define portINT_PRIORITY_LEVEL8 (0x00C8U) /* Level 8 */
|
||||
#define portINT_PRIORITY_LEVEL9 (0x00C9U) /* Level 9 */
|
||||
#define portINT_PRIORITY_LEVEL10 (0x00CAU) /* Level 10 */
|
||||
#define portINT_PRIORITY_LEVEL11 (0x00CBU) /* Level 11 */
|
||||
#define portINT_PRIORITY_LEVEL12 (0x00CCU) /* Level 12 */
|
||||
#define portINT_PRIORITY_LEVEL13 (0x00CDU) /* Level 13 */
|
||||
#define portINT_PRIORITY_LEVEL14 (0x00CEU) /* Level 14 */
|
||||
#define portINT_PRIORITY_LOWEST (0x00CFU) /* Level 15 (lowest) */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Counts the interrupt nesting depth. A context switch is only performed
|
||||
* if the nesting depth is 0. */
|
||||
volatile BaseType_t xInterruptNesting = 0;
|
||||
|
||||
/* Set to 1 to pend a context switch from an ISR. */
|
||||
volatile BaseType_t xPortSwitchRequired = pdFALSE;
|
||||
|
||||
/* Function to start the first task executing */
|
||||
extern void vPortStartFirstTask(void);
|
||||
|
||||
/*
|
||||
* Sets up the periodic ISR used for the RTOS tick using the OSTM.
|
||||
* The application writer can define configSETUP_TICK_INTERRUPT() (in
|
||||
* FreeRTOSConfig.h) such that their own tick interrupt configuration is used
|
||||
* in place of prvSetupTimerInterrupt().
|
||||
*/
|
||||
static void prvSetupTimerInterrupt(void);
|
||||
|
||||
#ifndef configSETUP_TICK_INTERRUPT
|
||||
|
||||
/* The user has not provided their own tick interrupt configuration so use
|
||||
* the definition in this file (which uses the interval timer). */
|
||||
#define configSETUP_TICK_INTERRUPT() prvSetupTimerInterrupt()
|
||||
#endif /* configSETUP_TICK_INTERRUPT */
|
||||
|
||||
/******************************************************************************
|
||||
* Setup the stack of a new task so it is ready to be placed under the
|
||||
* scheduler control. The registers have to be placed on the stack in the
|
||||
* order that the port expects to find them.
|
||||
*
|
||||
* @param[in] pxTopOfStack Pointer to top of this task's stack
|
||||
* @param[in] pxCode Task function, stored as initial PC for the task
|
||||
* @param[in] pvParameters Parameters for task
|
||||
******************************************************************************/
|
||||
StackType_t * pxPortInitialiseStack (StackType_t * pxTopOfStack, TaskFunction_t pxCode, void * pvParameters)
|
||||
{
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
* interrupt. */
|
||||
*pxTopOfStack = (StackType_t) vPortEndScheduler; /* R31 (LP) */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R5; /* R5 (TP) */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) pvParameters; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R7; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R8; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R9; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R10; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R11; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R12; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R13; /* R13 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R14; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R15; /* R15 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R16; /* R16 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R17; /* R17 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R18; /* R18 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R19; /* R19 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R20; /* R20 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R21; /* R21 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R22; /* R22 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R23; /* R23 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R24; /* R24 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R25; /* R25 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R26; /* R26 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R27; /* R27 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R28; /* R28 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R29; /* R29 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R30; /* R30 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R1; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portSTACK_INITIAL_VALUE_R2; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) portINITIAL_PSW; /* EIPSW */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = (StackType_t) pxCode; /* EIPC */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Configures the tick frequency and starts the first task.
|
||||
*****************************************************************************/
|
||||
portBASE_TYPE xPortStartScheduler (void)
|
||||
{
|
||||
/* Setup the hardware to generate the tick. Interrupts are disabled when
|
||||
* this function is called. */
|
||||
configSETUP_TICK_INTERRUPT();
|
||||
|
||||
/* Restore the context of the first task that is going to run. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Execution should not reach here as the tasks are now running! */
|
||||
return pdTRUE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Execution should never get here.
|
||||
*****************************************************************************/
|
||||
void vPortEndScheduler (void)
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
* Artificially force an assert. */
|
||||
configASSERT(pdFALSE);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Port Tick ISR. This is installed as the OSTM timer interrupt handler.
|
||||
*****************************************************************************/
|
||||
void vPortTickISR (void)
|
||||
{
|
||||
BaseType_t xSavedInterruptStatus;
|
||||
|
||||
xSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if (xTaskIncrementTick() != pdFALSE)
|
||||
{
|
||||
xPortSwitchRequired = pdTRUE;
|
||||
}
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR(xSavedInterruptStatus);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Enables the OS timer to generate the tick interrupts.
|
||||
*****************************************************************************/
|
||||
static void prvSetupTimerInterrupt (void)
|
||||
{
|
||||
/* Disable OSTM0 operation */
|
||||
OSTM0.TT = portOSTM_COUNTER_STOP;
|
||||
|
||||
/* Clear interrupt flag */
|
||||
INTC2.ICOSTM0.BIT.RFOSTM0 = portINT_REQUEST_NOT_OCCUR;
|
||||
|
||||
/* Enables interrupt processing */
|
||||
INTC2.ICOSTM0.BIT.MKOSTM0 = portINT_PROCESSING_ENABLED;
|
||||
|
||||
/* Table method */
|
||||
INTC2.ICOSTM0.BIT.TBOSTM0 = portINT_TABLE_VECTOR;
|
||||
|
||||
/* interrupt priority lowest */
|
||||
INTC2.ICOSTM0.UINT16 &= portINT_PRIORITY_LOWEST;
|
||||
|
||||
/* Set OSTM0 control setting */
|
||||
OSTM0.CTL = portOSTM_MODE_INTERVAL_TIMER | portOSTM_START_INTERRUPT_DISABLE;
|
||||
OSTM0.CMP = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ) - 1;
|
||||
|
||||
/* Enable OSTM0 operation */
|
||||
OSTM0.TS = portOSTM_COUNTER_START;
|
||||
}
|
||||
+215
@@ -0,0 +1,215 @@
|
||||
;/*
|
||||
;* FreeRTOS Kernel V11.0.1
|
||||
;* Copyright (C) 2023 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
|
||||
;*
|
||||
;*/
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; Extern symbols
|
||||
;------------------------------------------------------------------------------
|
||||
.extern _vTaskSwitchContext
|
||||
.extern _pxCurrentTCB
|
||||
.extern _xInterruptNesting
|
||||
.extern _xPortSwitchRequired
|
||||
.extern _bsp_common_interrupt_handler
|
||||
|
||||
.public _vPortYield
|
||||
.public _TRAP0_Handler
|
||||
.public _Irq_Handler
|
||||
.public _vPortStartFirstTask
|
||||
|
||||
.section ".text", text
|
||||
;------------------------------------------------------------------------------
|
||||
; Macro definitions
|
||||
;------------------------------------------------------------------------------
|
||||
EIPC .set 0
|
||||
EIPSW .set 1
|
||||
EIIC .set 13
|
||||
EIIC_MSK .set 0x00000FFF
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; Context saving
|
||||
;------------------------------------------------------------------------------
|
||||
portSAVE_CONTEXT .macro
|
||||
prepare lp, 0
|
||||
|
||||
;Save general-purpose registers and EIPSW, EIPC, EIIC into stack.
|
||||
pushsp r5, r30
|
||||
$nowarning
|
||||
pushsp r1, r2
|
||||
$warning
|
||||
|
||||
stsr EIPSW, r17
|
||||
stsr EIPC, r18
|
||||
pushsp r17, r18
|
||||
|
||||
;Save the stack pointer in the TCB
|
||||
mov #_pxCurrentTCB, r2
|
||||
ld.w 0[r2], r2
|
||||
st.w sp, 0[r2]
|
||||
.endm
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; Context restoring
|
||||
;------------------------------------------------------------------------------
|
||||
portRESTORE_CONTEXT .macro
|
||||
;Set the SP to point to the stack of the task being restored.
|
||||
mov #_pxCurrentTCB, r2
|
||||
ld.w 0[r2], r2
|
||||
ld.w 0[r2], sp
|
||||
|
||||
;Restore general-purpose registers and EIPSW, EIPC, EIIC.
|
||||
popsp r17, r18
|
||||
ldsr r18, EIPC
|
||||
ldsr r17, EIPSW
|
||||
|
||||
$nowarning
|
||||
popsp r1, r2
|
||||
$warning
|
||||
popsp r5, r30
|
||||
|
||||
dispose 0, lp
|
||||
.endm
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; Start the first task.
|
||||
;------------------------------------------------------------------------------
|
||||
_vPortStartFirstTask:
|
||||
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
eiret
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; _vPortYield
|
||||
;------------------------------------------------------------------------------
|
||||
_vPortYield:
|
||||
trap 0
|
||||
jmp [lp]
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; _TRAP0_Handler
|
||||
; FreeRTOS yield handler. This is installed as the TRAP exception handler.
|
||||
;------------------------------------------------------------------------------
|
||||
_TRAP0_Handler:
|
||||
;Save the context of the current task.
|
||||
portSAVE_CONTEXT
|
||||
|
||||
;Call the scheduler to select the next task.
|
||||
jarl _vTaskSwitchContext, lp
|
||||
|
||||
;Restore the context of the next task to run.
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
eiret
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; Interrupt start processing.
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
_Irq_Handler:
|
||||
;Save used registers.
|
||||
pushsp r5, r19
|
||||
$nowarning
|
||||
pushsp r1, r2
|
||||
$warning
|
||||
|
||||
stsr EIPSW, r19
|
||||
stsr EIPC, r18
|
||||
stsr EIIC, r17
|
||||
mov lp, r16
|
||||
mov ep, r15
|
||||
|
||||
pushsp r15, r19
|
||||
|
||||
;Increment nesting count.
|
||||
mov #_xInterruptNesting, r19
|
||||
ld.w 0[r19], r18
|
||||
addi 0x1, r18, r17
|
||||
st.w r17, 0[r19]
|
||||
|
||||
pushsp r18, r19
|
||||
|
||||
;Call the interrupt handler.
|
||||
stsr EIIC, r6
|
||||
andi EIIC_MSK, r6, r6
|
||||
jarl _bsp_common_interrupt_handler, lp
|
||||
synce
|
||||
popsp r18, r19
|
||||
|
||||
;Restore the old nesting count.
|
||||
st.w r18, 0[r19]
|
||||
|
||||
;A context switch if no nesting interrupt.
|
||||
cmp 0x0, r18
|
||||
bne exit_without_switch
|
||||
|
||||
;Check if context switch is requested.
|
||||
mov #_xPortSwitchRequired, r19
|
||||
ld.w 0[r19], r18
|
||||
cmp 0x0, r18
|
||||
bne switch_before_exit
|
||||
|
||||
exit_without_switch:
|
||||
;No context switch. Restore used registers
|
||||
popsp r15, r19
|
||||
|
||||
mov r15, ep
|
||||
mov r16, lp
|
||||
ldsr r17, EIIC
|
||||
ldsr r18, EIPC
|
||||
ldsr r19, EIPSW
|
||||
|
||||
$nowarning
|
||||
popsp r1, r2
|
||||
$warning
|
||||
popsp r5, r19
|
||||
|
||||
eiret
|
||||
|
||||
switch_before_exit:
|
||||
;Clear the context switch pending flag.
|
||||
st.w r0, 0[r19]
|
||||
|
||||
;Restore used registers before saving the context to the task stack.
|
||||
popsp r15, r19
|
||||
|
||||
mov r15, ep
|
||||
mov r16, lp
|
||||
ldsr r17, EIIC
|
||||
ldsr r18, EIPC
|
||||
ldsr r19, EIPSW
|
||||
|
||||
$nowarning
|
||||
popsp r1, r2
|
||||
$warning
|
||||
popsp r5, r19
|
||||
|
||||
portSAVE_CONTEXT
|
||||
jarl _vTaskSwitchContext, lp
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
eiret
|
||||
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V11.0.1
|
||||
* Copyright (C) 2023 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#if __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* 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 - These are a bit legacy and not really used now, other
|
||||
* than portSTACK_TYPE and portBASE_TYPE. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
/* Defines the maximum time when using a wait command in a task */
|
||||
#if (configUSE_16_BIT_TICKS == 1)
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY (TickType_t) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY (TickType_t) 0xffffffffUL
|
||||
|
||||
/* 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)
|
||||
#endif
|
||||
|
||||
/* Structure passed to pvParameters when task creation code is generated. */
|
||||
typedef struct st_rm_freertos_port_parameters
|
||||
{
|
||||
void * p_context; // Pointer to user data
|
||||
} rm_freertos_port_parameters_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics */
|
||||
|
||||
/* Determine the descending of the stack from high address to address */
|
||||
#define portSTACK_GROWTH (-1)
|
||||
|
||||
/* Determine the time (in milliseconds) corresponding to each tick */
|
||||
#define portTICK_PERIOD_MS ((TickType_t) 1000 / configTICK_RATE_HZ)
|
||||
|
||||
/* It is a multiple of 4 (the two lower-order bits of the address = 0),
|
||||
* otherwise it will cause MAE (Misaligned Exception) according to the manual */
|
||||
#define portBYTE_ALIGNMENT (8)
|
||||
|
||||
/* Interrupt control macros. */
|
||||
|
||||
#define portENABLE_INTERRUPTS() __EI() /* Macro to enable all maskable interrupts. */
|
||||
#define portDISABLE_INTERRUPTS() __DI() /* Macro to disable all maskable interrupts. */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler utilities */
|
||||
|
||||
/* Use to transfer control from one task to perform other tasks of higher priority */
|
||||
extern void vPortYield(void);
|
||||
|
||||
/* Called at the end of an ISR that can cause a context switch */
|
||||
|
||||
#define portEND_SWITCHING_ISR(xSwitchRequired) \
|
||||
{ \
|
||||
extern volatile BaseType_t xPortSwitchRequired; \
|
||||
\
|
||||
if (xSwitchRequired != pdFALSE) \
|
||||
{ \
|
||||
xPortSwitchRequired = pdTRUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define portYIELD_FROM_ISR(x) portEND_SWITCHING_ISR(x)
|
||||
#define portYIELD() vPortYield()
|
||||
|
||||
/* Critical section management. */
|
||||
|
||||
/* Critical nesting counts are stored in the TCB. */
|
||||
|
||||
#define portCRITICAL_NESTING_IN_TCB (1)
|
||||
|
||||
/* The critical nesting functions defined within tasks.c */
|
||||
|
||||
extern void vTaskEnterCritical(void);
|
||||
extern void vTaskExitCritical(void);
|
||||
|
||||
/* Macro to mark the start of a critical code region */
|
||||
#define portENTER_CRITICAL() vTaskEnterCritical()
|
||||
|
||||
/* Macro to mark the end of a critical code region */
|
||||
#define portEXIT_CRITICAL() vTaskExitCritical()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* As this port allows interrupt nesting... */
|
||||
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() __stsr_rh(5, 0); __DI() /* Stores the contents of the system register,
|
||||
* and disable all maskable interrupts */
|
||||
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) __ldsr_rh(5, 0, x) /* Load the contents into the system register */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
|
||||
#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void * pvParameters)
|
||||
#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void * pvParameters)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
|
||||
OVERVIEW
|
||||
|
||||
This directory contains FreeRTOS port for Texas Instruments C28x based microcontrollers.
|
||||
|
||||
The standard demo project to test this port is added at following location:
|
||||
FreeRTOS-Community-Supported-Demos\C2000_F2838x_C28x_CCS\freertos_ex1_c28x_port_val
|
||||
|
||||
This port is distributed under MIT open source license.
|
||||
|
||||
TOOL CHAIN SUPPORT:
|
||||
Code Composer Studio™ IDE (CCS) v11.1.0 or newer
|
||||
C2000 Compiler v20.2.1.LTS or newer
|
||||
C2000Ware_3_01_00_00 or newer
|
||||
FreeRTOSv202112.00
|
||||
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Author: Ivan Zaitsev, ivan.zaitsev@gmail.com
|
||||
//
|
||||
// This file follows the FreeRTOS distribution license.
|
||||
//
|
||||
// FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License (version 2) as published by the
|
||||
// Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
//
|
||||
// ***************************************************************************
|
||||
// >>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
// >>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
// >>! obliged to provide the source code for proprietary components !<<
|
||||
// >>! outside of the FreeRTOS kernel. !<<
|
||||
// ***************************************************************************
|
||||
//
|
||||
// FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
// link: http://www.freertos.org/a00114.html
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Scheduler includes.
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Implementation of functions defined in portable.h for the C28x port.
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
// Constants required for hardware setup.
|
||||
#define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 )
|
||||
#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x08 )
|
||||
#if defined(__TMS320C28XX_FPU64__)
|
||||
# define AUX_REGISTERS_TO_SAVE 27 // XAR + FPU registers
|
||||
# define XAR4_REGISTER_POSITION 6 // XAR4 position in AUX registers array
|
||||
# define STF_REGISTER_POSITION 10 // STF position in AUX registers array
|
||||
#elif defined(__TMS320C28XX_FPU32__)
|
||||
# define AUX_REGISTERS_TO_SAVE 19 // XAR + FPU registers
|
||||
# define XAR4_REGISTER_POSITION 6 // XAR4 position in AUX registers array
|
||||
# define STF_REGISTER_POSITION 10 // STF position in AUX registers array
|
||||
#else
|
||||
# define AUX_REGISTERS_TO_SAVE 9 // XAR registers only
|
||||
# define XAR4_REGISTER_POSITION 5 // XAR4 position in AUX registers array
|
||||
#endif
|
||||
|
||||
extern uint32_t getSTF( void );
|
||||
extern void vApplicationSetupTimerInterrupt( void );
|
||||
|
||||
// Each task maintains a count of the critical section nesting depth. Each
|
||||
// time a critical section is entered the count is incremented. Each time a
|
||||
// critical section is exited the count is decremented - with interrupts only
|
||||
// being re-enabled if the count is zero.
|
||||
//
|
||||
// ulCriticalNesting will get set to zero when the scheduler starts, but must
|
||||
// not be initialised to zero as this will cause problems during the startup
|
||||
// sequence.
|
||||
// ulCriticalNesting should be 32 bit value to keep stack alignment unchanged.
|
||||
volatile uint32_t ulCriticalNesting = portINITIAL_CRITICAL_NESTING;
|
||||
volatile uint16_t bYield = 0;
|
||||
volatile uint16_t bPreemptive = 0;
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Initialise the stack of a task to look exactly as if
|
||||
// timer interrupt was executed.
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
uint16_t i;
|
||||
uint16_t base = 0;
|
||||
|
||||
pxTopOfStack[base++] = 0x0080; // ST0. PSM = 0(No shift)
|
||||
pxTopOfStack[base++] = 0x0000; // T
|
||||
pxTopOfStack[base++] = 0x0000; // AL
|
||||
pxTopOfStack[base++] = 0x0000; // AH
|
||||
pxTopOfStack[base++] = 0xFFFF; // PL
|
||||
pxTopOfStack[base++] = 0xFFFF; // PH
|
||||
pxTopOfStack[base++] = 0xFFFF; // AR0
|
||||
pxTopOfStack[base++] = 0xFFFF; // AR1
|
||||
pxTopOfStack[base++] = 0x8A08; // ST1
|
||||
pxTopOfStack[base++] = 0x0000; // DP
|
||||
pxTopOfStack[base++] = 0x0000; // IER
|
||||
pxTopOfStack[base++] = 0x0000; // DBGSTAT
|
||||
pxTopOfStack[base++] = ((uint32_t)pxCode) & 0xFFFFU; // PCL
|
||||
pxTopOfStack[base++] = ((uint32_t)pxCode >> 16) & 0x00FFU; // PCH
|
||||
pxTopOfStack[base++] = 0xAAAA; // Alignment
|
||||
pxTopOfStack[base++] = 0xBBBB; // Alignment
|
||||
|
||||
// Fill the rest of the registers with dummy values.
|
||||
for(i = 0; i < (2 * AUX_REGISTERS_TO_SAVE); i++)
|
||||
{
|
||||
uint16_t low = 0x0000;
|
||||
uint16_t high = 0x0000;
|
||||
|
||||
if(i == (2 * XAR4_REGISTER_POSITION))
|
||||
{
|
||||
low = ((uint32_t)pvParameters) & 0xFFFFU;
|
||||
high = ((uint32_t)pvParameters >> 16) & 0xFFFFU;
|
||||
}
|
||||
|
||||
#if defined(__TMS320C28XX_FPU32__)
|
||||
if(i == (2 * STF_REGISTER_POSITION))
|
||||
{
|
||||
uint32_t stf = getSTF();
|
||||
|
||||
low = stf & 0xFFFFU;
|
||||
high = (stf >> 16) & 0xFFFFU;
|
||||
}
|
||||
#endif
|
||||
|
||||
pxTopOfStack[base + i] = low;
|
||||
i++;
|
||||
pxTopOfStack[base + i] = high;
|
||||
}
|
||||
|
||||
base += i;
|
||||
|
||||
// Reserve place for ST1 which will be used in context switch
|
||||
// to set correct SPA bit ASAP.
|
||||
pxTopOfStack[base++] = 0x8A18; // ST1 with SPA bit set
|
||||
pxTopOfStack[base++] = 0x0000; // DP
|
||||
pxTopOfStack[base++] = 0x0000; // placeholder for 32 bit ulCriticalNesting
|
||||
pxTopOfStack[base++] = 0x0000;
|
||||
|
||||
// Return a pointer to the top of the stack we have generated so this can
|
||||
// be stored in the task control block for the task.
|
||||
return pxTopOfStack + base;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
// It is unlikely that the TMS320 port will get stopped.
|
||||
// If required simply disable the tick interrupt here.
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// See header file for description.
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
BaseType_t xPortStartScheduler(void)
|
||||
{
|
||||
vApplicationSetupTimerInterrupt();
|
||||
|
||||
ulCriticalNesting = 0;
|
||||
|
||||
#if(configUSE_PREEMPTION == 1)
|
||||
bPreemptive = 1;
|
||||
#else
|
||||
bPreemptive = 0;
|
||||
#endif
|
||||
|
||||
portENABLE_INTERRUPTS();
|
||||
portRESTORE_FIRST_CONTEXT();
|
||||
|
||||
// Should not get here!
|
||||
return pdFAIL;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
ulCriticalNesting--;
|
||||
if( ulCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
+385
@@ -0,0 +1,385 @@
|
||||
;-------------------------------------------------------------------------------------------------
|
||||
; Author: Ivan Zaitsev, ivan.zaitsev@gmail.com
|
||||
;
|
||||
; This file follows the FreeRTOS distribution license.
|
||||
;
|
||||
; FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
; the terms of the GNU General Public License (version 2) as published by the
|
||||
; Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
;
|
||||
; ***************************************************************************
|
||||
; >>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
; >>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
; >>! obliged to provide the source code for proprietary components !<<
|
||||
; >>! outside of the FreeRTOS kernel. !<<
|
||||
; ***************************************************************************
|
||||
;
|
||||
; FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
; WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
; FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
; link: http://www.freertos.org/a00114.html
|
||||
;-------------------------------------------------------------------------------------------------
|
||||
|
||||
.if __TI_EABI__
|
||||
.asg pxCurrentTCB, _pxCurrentTCB
|
||||
.asg bYield, _bYield
|
||||
.asg bPreemptive, _bPreemptive
|
||||
.asg ulCriticalNesting, _ulCriticalNesting
|
||||
.asg xTaskIncrementTick, _xTaskIncrementTick
|
||||
.asg vTaskSwitchContext, _vTaskSwitchContext
|
||||
.asg portTICK_ISR, _portTICK_ISR
|
||||
.asg portRESTORE_FIRST_CONTEXT, _portRESTORE_FIRST_CONTEXT
|
||||
.asg getSTF, _getSTF
|
||||
.endif
|
||||
|
||||
.ref _pxCurrentTCB
|
||||
.ref _bYield
|
||||
.ref _bPreemptive
|
||||
.ref _ulCriticalNesting
|
||||
.ref _xTaskIncrementTick
|
||||
.ref _vTaskSwitchContext
|
||||
|
||||
.def _portTICK_ISR
|
||||
.def _portRESTORE_FIRST_CONTEXT
|
||||
|
||||
.if .TMS320C2800_FPU32 = 1
|
||||
|
||||
.def _getSTF
|
||||
|
||||
_getSTF:
|
||||
MOV32 *SP++, STF
|
||||
POP ACC
|
||||
LRETR
|
||||
|
||||
_portRESTORE_FIRST_CONTEXT:
|
||||
; Restore stack pointer from new task control block.
|
||||
MOVL XAR0, #_pxCurrentTCB
|
||||
MOVL XAR0, *XAR0
|
||||
MOVL XAR0, *XAR0
|
||||
MOV @SP, AR0
|
||||
|
||||
; Restore XAR4 and RPC from saved task stack.
|
||||
; and return to main task function.
|
||||
; SP should be set to stack start plus 2 before LRETR.
|
||||
.if .TMS320C2800_FPU64 = 1
|
||||
SUBB SP, #44
|
||||
.else
|
||||
SUBB SP, #28
|
||||
.endif
|
||||
POP XAR4
|
||||
SUBB SP, #14
|
||||
POP RPC
|
||||
SUBB SP, #10
|
||||
LRETR
|
||||
|
||||
_portTICK_ISR:
|
||||
; Save context
|
||||
ASP
|
||||
PUSH RB
|
||||
PUSH AR1H:AR0H
|
||||
PUSH RPC
|
||||
MOVL *SP++, XT
|
||||
MOVL *SP++, XAR2
|
||||
MOVL *SP++, XAR3
|
||||
MOVL *SP++, XAR4
|
||||
MOVL *SP++, XAR5
|
||||
MOVL *SP++, XAR6
|
||||
MOVL *SP++, XAR7
|
||||
MOV32 *SP++, STF
|
||||
|
||||
.if .TMS320C2800_FPU64 = 1
|
||||
MOV32 *SP++, R0L
|
||||
MOV32 *SP++, R0H
|
||||
MOV32 *SP++, R1L
|
||||
MOV32 *SP++, R1H
|
||||
MOV32 *SP++, R2L
|
||||
MOV32 *SP++, R2H
|
||||
MOV32 *SP++, R3L
|
||||
MOV32 *SP++, R3H
|
||||
MOV32 *SP++, R4L
|
||||
MOV32 *SP++, R4H
|
||||
MOV32 *SP++, R5L
|
||||
MOV32 *SP++, R5H
|
||||
MOV32 *SP++, R6L
|
||||
MOV32 *SP++, R6H
|
||||
MOV32 *SP++, R7L
|
||||
MOV32 *SP++, R7H
|
||||
.else
|
||||
MOV32 *SP++, R0H
|
||||
MOV32 *SP++, R1H
|
||||
MOV32 *SP++, R2H
|
||||
MOV32 *SP++, R3H
|
||||
MOV32 *SP++, R4H
|
||||
MOV32 *SP++, R5H
|
||||
MOV32 *SP++, R6H
|
||||
MOV32 *SP++, R7H
|
||||
.endif
|
||||
|
||||
PUSH DP:ST1
|
||||
|
||||
; Save critical section nesting counter
|
||||
MOVL XAR0, #_ulCriticalNesting
|
||||
MOVL ACC, *XAR0
|
||||
PUSH ACC
|
||||
|
||||
; Save stack pointer in the task control block.
|
||||
MOVL XAR0, #_pxCurrentTCB
|
||||
MOVL XAR0, *XAR0
|
||||
MOVL XAR6, #0 ;set to 0 XAR6 before move the new value of pxTopOfStack
|
||||
MOV AR6, @SP
|
||||
MOVL *XAR0, XAR6
|
||||
|
||||
; Save IER on stack to avoid corruption.
|
||||
; Depending on stack alignment bit IER can be found in two locations.
|
||||
PUSH ST1
|
||||
POP AL
|
||||
TBIT AL, #4
|
||||
SB SPA_BIT_SET, TC
|
||||
.if .TMS320C2800_FPU64 = 1
|
||||
MOVZ AR7, @SP ;load lower half of XAR7 with contents of SP, clear upper half of XAR7
|
||||
SUBB XAR7, #62
|
||||
MOVZ AR7, *XAR7
|
||||
.else
|
||||
MOV AR7, *-SP[46]
|
||||
.endif
|
||||
SB SAVE_IER, UNC
|
||||
SPA_BIT_SET:
|
||||
.if .TMS320C2800_FPU64 = 1
|
||||
MOVZ AR7, @SP ;load lower half of XAR7 with contents of SP, clear upper half of XAR7
|
||||
SUBB XAR7, #64
|
||||
MOV AR7, *XAR7
|
||||
.else
|
||||
MOV AR7, *-SP[48]
|
||||
.endif
|
||||
SAVE_IER:
|
||||
MOVL *SP++, XAR7
|
||||
|
||||
; Increment tick counter if timer tick is executed.
|
||||
; Don't increment if explicitly yielded.
|
||||
MOVL XAR0, #_bYield
|
||||
MOV ACC, *XAR0
|
||||
SB RESET_YIELD_FLAG, NEQ
|
||||
LCR _xTaskIncrementTick
|
||||
|
||||
RESET_YIELD_FLAG:
|
||||
; Save bYield in AR1 and clear it in memory.
|
||||
MOV AR1, ACC
|
||||
MOV ACC, #0
|
||||
MOV *XAR0, ACC
|
||||
|
||||
; Do context switch if bYield=1 or bPreemptive=1
|
||||
MOVL XAR0, #_bPreemptive
|
||||
MOV ACC, *XAR0
|
||||
CMPB AL, #0x1
|
||||
SB CONTEXT_SWITCH, EQ
|
||||
MOV ACC, AR1
|
||||
CMPB AL, #0x1
|
||||
SB SKIP_CONTEXT_SWITCH, NEQ
|
||||
|
||||
CONTEXT_SWITCH:
|
||||
LCR _vTaskSwitchContext
|
||||
|
||||
SKIP_CONTEXT_SWITCH:
|
||||
; Restore IER value from stack.
|
||||
MOVL XAR7, *--SP
|
||||
|
||||
; Restore stack pointer from new task control block.
|
||||
MOVL XAR0, #_pxCurrentTCB
|
||||
MOVL XAR0, *XAR0
|
||||
MOVL XAR0, *XAR0
|
||||
MOV @SP, AR0
|
||||
|
||||
; Restore critical section nesting counter
|
||||
MOVL XAR0, #_ulCriticalNesting
|
||||
POP ACC
|
||||
MOVL *XAR0, ACC
|
||||
|
||||
; Update IER value in target context.
|
||||
; Depending on stack alignment bit IER can be found in two locations.
|
||||
POP DP:ST1
|
||||
PUSH ST1
|
||||
POP AL
|
||||
TBIT AL, #4
|
||||
SB SPA_BIT_SET_RESTORE, TC
|
||||
.if .TMS320C2800_FPU64 = 1
|
||||
MOVZ AR6, @SP ;load lower half of XAR6 with contents of SP, clear upper half of XAR6
|
||||
SUBB XAR6, #58
|
||||
MOV *XAR6, AR7
|
||||
.else
|
||||
MOV *-SP[42], AR7
|
||||
.endif
|
||||
SB RESTORE_CONTEXT, UNC
|
||||
SPA_BIT_SET_RESTORE:
|
||||
.if .TMS320C2800_FPU64 = 1
|
||||
MOVZ AR6, @SP ;load lower half of XAR6 with contents of SP, clear upper half of XAR6
|
||||
SUBB XAR6, #60
|
||||
MOV *XAR6, AR7
|
||||
.else
|
||||
MOV *-SP[44], AR7
|
||||
.endif
|
||||
|
||||
RESTORE_CONTEXT:
|
||||
.if .TMS320C2800_FPU64 = 1
|
||||
MOV32 R7H, *--SP
|
||||
MOV32 R7L, *--SP
|
||||
MOV32 R6H, *--SP
|
||||
MOV32 R6L, *--SP
|
||||
MOV32 R5H, *--SP
|
||||
MOV32 R5L, *--SP
|
||||
MOV32 R4H, *--SP
|
||||
MOV32 R4L, *--SP
|
||||
MOV32 R3H, *--SP
|
||||
MOV32 R3L, *--SP
|
||||
MOV32 R2H, *--SP
|
||||
MOV32 R2L, *--SP
|
||||
MOV32 R1H, *--SP
|
||||
MOV32 R1L, *--SP
|
||||
MOV32 R0H, *--SP
|
||||
MOV32 R0L, *--SP
|
||||
.else
|
||||
MOV32 R7H, *--SP
|
||||
MOV32 R6H, *--SP
|
||||
MOV32 R5H, *--SP
|
||||
MOV32 R4H, *--SP
|
||||
MOV32 R3H, *--SP
|
||||
MOV32 R2H, *--SP
|
||||
MOV32 R1H, *--SP
|
||||
MOV32 R0H, *--SP
|
||||
.endif
|
||||
MOV32 STF, *--SP
|
||||
MOVL XAR7, *--SP
|
||||
MOVL XAR6, *--SP
|
||||
MOVL XAR5, *--SP
|
||||
MOVL XAR4, *--SP
|
||||
MOVL XAR3, *--SP
|
||||
MOVL XAR2, *--SP
|
||||
MOVL XT, *--SP
|
||||
POP RPC
|
||||
POP AR1H:AR0H
|
||||
POP RB
|
||||
NASP
|
||||
IRET
|
||||
|
||||
.else
|
||||
|
||||
_portRESTORE_FIRST_CONTEXT:
|
||||
; Restore stack pointer from new task control block.
|
||||
MOVL XAR0, #_pxCurrentTCB
|
||||
MOVL XAR0, *XAR0
|
||||
MOVL XAR0, *XAR0
|
||||
MOV @SP, AR0
|
||||
|
||||
; Restore XAR4 and RPC from saved task stack.
|
||||
; and return to main task function.
|
||||
; SP should be set to stack start plus 2 before LRETR.
|
||||
SUBB SP, #10
|
||||
POP XAR4
|
||||
SUBB SP, #12
|
||||
POP RPC
|
||||
SUBB SP, #10
|
||||
LRETR
|
||||
|
||||
_portTICK_ISR:
|
||||
; Save context
|
||||
ASP
|
||||
PUSH AR1H:AR0H
|
||||
PUSH RPC
|
||||
MOVL *SP++, XT
|
||||
MOVL *SP++, XAR2
|
||||
MOVL *SP++, XAR3
|
||||
MOVL *SP++, XAR4
|
||||
MOVL *SP++, XAR5
|
||||
MOVL *SP++, XAR6
|
||||
MOVL *SP++, XAR7
|
||||
PUSH DP:ST1
|
||||
|
||||
; Save critical section nesting counter
|
||||
MOVL XAR0, #_ulCriticalNesting
|
||||
MOVL ACC, *XAR0
|
||||
PUSH ACC
|
||||
|
||||
; Save stack pointer in the task control block.
|
||||
MOVL XAR0, #_pxCurrentTCB
|
||||
MOVL XAR0, *XAR0
|
||||
MOVL XAR6, #0 ;set to 0 XAR6 before move the new value of pxTopOfStack
|
||||
MOV AR6, @SP
|
||||
MOVL *XAR0, XAR6
|
||||
|
||||
; Save IER on stack to avoid corruption.
|
||||
PUSH ST1
|
||||
POP AL
|
||||
TBIT AL, #4
|
||||
SB SPA_BIT_SET, TC
|
||||
MOV AR7, *-SP[26]
|
||||
SB SAVE_IER, UNC
|
||||
SPA_BIT_SET:
|
||||
MOV AR7, *-SP[28]
|
||||
SAVE_IER:
|
||||
MOVL *SP++, XAR7
|
||||
|
||||
; Increment tick counter if timer tick is executed.
|
||||
; Don't increment if explicitly yielded.
|
||||
MOVL XAR0, #_bYield
|
||||
MOV ACC, *XAR0
|
||||
SB RESET_YIELD_FLAG, NEQ
|
||||
LCR _xTaskIncrementTick
|
||||
|
||||
RESET_YIELD_FLAG:
|
||||
; Save bYield in AR1 and clear it in memory.
|
||||
MOV AR1, ACC
|
||||
MOV ACC, #0
|
||||
MOV *XAR0, ACC
|
||||
|
||||
; Do context switch if bYield=1 or bPreemptive=1
|
||||
MOVL XAR0, #_bPreemptive
|
||||
MOV ACC, *XAR0
|
||||
CMPB AL, #0x1
|
||||
SB CONTEXT_SWITCH, EQ
|
||||
MOV ACC, AR1
|
||||
CMPB AL, #0x1
|
||||
SB SKIP_CONTEXT_SWITCH, NEQ
|
||||
|
||||
CONTEXT_SWITCH:
|
||||
LCR _vTaskSwitchContext
|
||||
|
||||
SKIP_CONTEXT_SWITCH:
|
||||
; Restore IER value from stack.
|
||||
MOVL XAR7, *--SP
|
||||
|
||||
; Restore stack pointer from new task control block.
|
||||
MOVL XAR0, #_pxCurrentTCB
|
||||
MOVL XAR0, *XAR0
|
||||
MOVL XAR0, *XAR0
|
||||
MOV @SP, AR0
|
||||
|
||||
; Restore critical section nesting counter
|
||||
MOVL XAR0, #_ulCriticalNesting
|
||||
POP ACC
|
||||
MOVL *XAR0, ACC
|
||||
|
||||
; Update IER value in target context.
|
||||
POP DP:ST1
|
||||
PUSH ST1
|
||||
POP AL
|
||||
TBIT AL, #4
|
||||
SB SPA_BIT_SET_RESTORE, TC
|
||||
MOV *-SP[22], AR7
|
||||
SB RESTORE_CONTEXT, UNC
|
||||
SPA_BIT_SET_RESTORE:
|
||||
MOV *-SP[24], AR7
|
||||
|
||||
RESTORE_CONTEXT:
|
||||
MOVL XAR7, *--SP
|
||||
MOVL XAR6, *--SP
|
||||
MOVL XAR5, *--SP
|
||||
MOVL XAR4, *--SP
|
||||
MOVL XAR3, *--SP
|
||||
MOVL XAR2, *--SP
|
||||
MOVL XT, *--SP
|
||||
POP RPC
|
||||
POP AR1H:AR0H
|
||||
NASP
|
||||
IRET
|
||||
|
||||
.endif
|
||||
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Author: Ivan Zaitsev, ivan.zaitsev@gmail.com
|
||||
//
|
||||
// This file follows the FreeRTOS distribution license.
|
||||
//
|
||||
// FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License (version 2) as published by the
|
||||
// Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
//
|
||||
// ***************************************************************************
|
||||
// >>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
// >>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
// >>! obliged to provide the source code for proprietary components !<<
|
||||
// >>! outside of the FreeRTOS kernel. !<<
|
||||
// ***************************************************************************
|
||||
//
|
||||
// FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
// FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
// link: http://www.freertos.org/a00114.html
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Port specific definitions.
|
||||
//
|
||||
// The settings in this file configure FreeRTOS correctly for the
|
||||
// given hardware and compiler.
|
||||
//
|
||||
// These settings should not be altered.
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Hardware includes
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Type definitions.
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
#define portCHAR uint16_t
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG uint32_t
|
||||
#define portSHORT uint16_t
|
||||
#define portBASE_TYPE uint16_t
|
||||
#define uint8_t uint16_t
|
||||
#define int8_t int16_t
|
||||
#define portSTACK_TYPE uint16_t
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef int16_t BaseType_t;
|
||||
typedef uint16_t UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Interrupt control macros.
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
#define portDISABLE_INTERRUPTS() __asm(" setc INTM")
|
||||
#define portENABLE_INTERRUPTS() __asm(" clrc INTM")
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Critical section control macros.
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Task utilities.
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
#define portYIELD() do{bYield = 1; __asm(" INTR INT14");}while(0)
|
||||
#define portYIELD_FROM_ISR( x ) do{if(x == pdTRUE){bYield = 1; __asm(" OR IFR, #0x2000");}}while(0)
|
||||
|
||||
extern void portTICK_ISR( void );
|
||||
extern void portRESTORE_FIRST_CONTEXT( void );
|
||||
extern void vTaskSwitchContext( void );
|
||||
extern volatile uint16_t bYield;
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Hardware specifics.
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
#define portBYTE_ALIGNMENT 2
|
||||
#define portSTACK_GROWTH ( 1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portNOP() __asm(" NOP")
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Task function macros as described on the FreeRTOS.org WEB site.
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
+1
@@ -0,0 +1 @@
|
||||
The bsp_patches contains the xlinx bsp modifications needed to port FreeRTOS-SMP to the ZynqMPOSC(A53*4) platform, see details bsp_patches/ReadMe.txt
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
boot.S:
|
||||
Added CPU ID determination and stack initialization code after multicore startup.
|
||||
xil-crt0.S:
|
||||
Initialize the C runtime environment only on the primary core
|
||||
Start the secondary cores
|
||||
cpu.c / cpu.h:
|
||||
APIs of secondary cores power up and reset
|
||||
|
||||
xscugic.c:
|
||||
Added CPU interface initialization of the GIC for secondary cores
|
||||
|
||||
scugic_v4_2_diff.png:
|
||||
standalone_v7_2_diff.png:
|
||||
Xlinx bsp libaray modification details
|
||||
+501
@@ -0,0 +1,501 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2014 - 2020 Xilinx, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
******************************************************************************/
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file boot.S
|
||||
*
|
||||
* @addtogroup a53_64_boot_code Cortex A53 64bit Processor Boot Code
|
||||
* @{
|
||||
* <h2> boot.S </h2>
|
||||
*
|
||||
* The boot code performs minimum configuration which is required for an
|
||||
* application. Cortex-A53 starts by checking current exception level. If the
|
||||
* current exception level is EL3 and BSP is built for EL3, it will do
|
||||
* initialization required for application execution at EL3. Below is a
|
||||
* sequence illustrating what all configuration is performed before control
|
||||
* reaches to main function for EL3 execution.
|
||||
*
|
||||
* 1. Program vector table base for exception handling
|
||||
* 2. Set reset vector table base address
|
||||
* 3. Program stack pointer for EL3
|
||||
* 4. Routing of interrupts to EL3
|
||||
* 5. Enable ECC protection
|
||||
* 6. Program generic counter frequency
|
||||
* 7. Invalidate instruction cache, data cache and TLBs
|
||||
* 8. Configure MMU registers and program base address of translation table
|
||||
* 9. Transfer control to _start which clears BSS sections and runs global
|
||||
* constructor before jumping to main application
|
||||
*
|
||||
* If the current exception level is EL1 and BSP is also built for EL1_NONSECURE
|
||||
* it will perform initialization required for application execution at EL1
|
||||
* non-secure. For all other combination, the execution will go into infinite
|
||||
* loop. Below is a sequence illustrating what all configuration is performed
|
||||
* before control reaches to main function for EL1 execution.
|
||||
*
|
||||
* 1. Program vector table base for exception handling
|
||||
* 2. Program stack pointer for EL1
|
||||
* 3. Invalidate instruction cache, data cache and TLBs
|
||||
* 4. Configure MMU registers and program base address of translation table
|
||||
* 5. Transfer control to _start which clears BSS sections and runs global
|
||||
* constructor before jumping to main application
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ------- -------- ---------------------------------------------------
|
||||
* 5.00 pkp 05/21/14 Initial version
|
||||
* 6.00 pkp 07/25/16 Program the counter frequency
|
||||
* 6.02 pkp 01/22/17 Added support for EL1 non-secure
|
||||
* 6.02 pkp 01/24/17 Clearing status of FPUStatus variable to ensure it
|
||||
* holds correct value.
|
||||
* 6.3 mus 04/20/17 CPU Cache protection bit in the L2CTLR_EL1 will be in
|
||||
* set state on reset. So, setting that bit through boot
|
||||
* code is redundant, hence removed the code which sets
|
||||
* CPU cache protection bit.
|
||||
* 6.4 mus 08/11/17 Implemented ARM erratum 855873.It fixes
|
||||
* CR#982209.
|
||||
* 6.6 mus 01/19/18 Added isb after writing to the cpacr_el1/cptr_el3,
|
||||
* to ensure floating-point unit is disabled, before
|
||||
* any subsequent instruction.
|
||||
* 7.0 mus 03/26/18 Updated TCR_EL3/TCR_EL1 as per versal address map
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "xparameters.h"
|
||||
#include "bspconfig.h"
|
||||
#include "xil_errata.h"
|
||||
|
||||
#define FREERTOS_SMP
|
||||
|
||||
.globl MMUTableL0
|
||||
.globl MMUTableL1
|
||||
.globl MMUTableL2
|
||||
.global _prestart
|
||||
.global _boot
|
||||
|
||||
.global __el3_stack
|
||||
.global __el2_stack
|
||||
.global __el1_stack
|
||||
.global __el0_stack
|
||||
.global _vector_table
|
||||
|
||||
.set EL3_stack, __el3_stack
|
||||
.set EL2_stack, __el2_stack
|
||||
.set EL1_stack, __el1_stack
|
||||
.set EL0_stack, __el0_stack
|
||||
|
||||
.set EL3_stack_end, _el3_stack_end
|
||||
.set EL2_stack_end, _el2_stack_end
|
||||
.set EL1_stack_end, _el1_stack_end
|
||||
.set EL0_stack_end, _el0_stack_end
|
||||
|
||||
.set N_CPUS_SHIFT, 0x2
|
||||
|
||||
.set TT_S1_FAULT, 0x0
|
||||
.set TT_S1_TABLE, 0x3
|
||||
|
||||
.set L0Table, MMUTableL0
|
||||
.set L1Table, MMUTableL1
|
||||
.set L2Table, MMUTableL2
|
||||
.set vector_base, _vector_table
|
||||
.set rvbar_base, 0xFD5C0040
|
||||
|
||||
#if defined (versal)
|
||||
.set counterfreq, XPAR_CPU_CORTEXA72_0_TIMESTAMP_CLK_FREQ
|
||||
#else
|
||||
.set counterfreq, XPAR_CPU_CORTEXA53_0_TIMESTAMP_CLK_FREQ
|
||||
#endif
|
||||
|
||||
.set MODE_EL1, 0x5
|
||||
.set DAIF_BIT, 0x1C0
|
||||
|
||||
.section .boot,"ax"
|
||||
|
||||
|
||||
/* this initializes the various processor modes */
|
||||
|
||||
_prestart:
|
||||
_boot:
|
||||
mov x0, #0
|
||||
mov x1, #0
|
||||
mov x2, #0
|
||||
mov x3, #0
|
||||
mov x4, #0
|
||||
mov x5, #0
|
||||
mov x6, #0
|
||||
mov x7, #0
|
||||
mov x8, #0
|
||||
mov x9, #0
|
||||
mov x10, #0
|
||||
mov x11, #0
|
||||
mov x12, #0
|
||||
mov x13, #0
|
||||
mov x14, #0
|
||||
mov x15, #0
|
||||
mov x16, #0
|
||||
mov x17, #0
|
||||
mov x18, #0
|
||||
mov x19, #0
|
||||
mov x20, #0
|
||||
mov x21, #0
|
||||
mov x22, #0
|
||||
mov x23, #0
|
||||
mov x24, #0
|
||||
mov x25, #0
|
||||
mov x26, #0
|
||||
mov x27, #0
|
||||
mov x28, #0
|
||||
mov x29, #0
|
||||
mov x30, #0
|
||||
#if 0 //don't put other a53 cpus in wfi
|
||||
//Which core am I
|
||||
// ----------------
|
||||
mrs x0, MPIDR_EL1
|
||||
and x0, x0, #0xFF //Mask off to leave Aff0
|
||||
cbz x0, OKToRun //If core 0, run the primary init code
|
||||
EndlessLoop0:
|
||||
wfi
|
||||
b EndlessLoop0
|
||||
#endif
|
||||
OKToRun:
|
||||
|
||||
mrs x0, currentEL
|
||||
cmp x0, #0xC
|
||||
beq InitEL3
|
||||
|
||||
cmp x0, #0x4
|
||||
beq InitEL1
|
||||
|
||||
b error // go to error if current exception level is neither EL3 nor EL1
|
||||
InitEL3:
|
||||
.if (EL3 == 1)
|
||||
/*Set vector table base address*/
|
||||
ldr x1, =vector_base
|
||||
msr VBAR_EL3,x1
|
||||
|
||||
/* Set reset vector address */
|
||||
/* Get the cpu ID */
|
||||
mrs x0, MPIDR_EL1
|
||||
and x0, x0, #0xFF
|
||||
/* Save cpu ID for future use */
|
||||
mov x4, x0
|
||||
mov w0, w0
|
||||
ldr w2, =rvbar_base
|
||||
/* calculate the rvbar base address for particular CPU core */
|
||||
mov w3, #0x8
|
||||
mul w0, w0, w3
|
||||
add w2, w2, w0
|
||||
/* store vector base address to RVBAR */
|
||||
str x1, [x2]
|
||||
|
||||
/*Define stack pointer for current exception level*/
|
||||
#ifdef FREERTOS_SMP
|
||||
|
||||
/*EL3_stack_end */
|
||||
/*------------*/
|
||||
/* CPU0 stack */
|
||||
/*------------*/
|
||||
/* CPU1 stack */
|
||||
/*------------*/
|
||||
/* CPU2 stack */
|
||||
/*------------*/
|
||||
/* CPU3 stack */
|
||||
/*------------*/
|
||||
/* EL3_stack */
|
||||
mov x0, N_CPUS_SHIFT
|
||||
ldr x1, =EL3_stack_end
|
||||
ldr x2, =EL3_stack
|
||||
subs x1, x2, x1
|
||||
lsr x1, x1, x0
|
||||
mul x0, x1, x4
|
||||
add x2, x2, x0
|
||||
mov sp, x2
|
||||
#else
|
||||
ldr x2, =EL3_stack
|
||||
mov sp, x2
|
||||
#endif
|
||||
/* Enable Trapping of SIMD/FPU register for standalone BSP */
|
||||
mov x0, #0
|
||||
#ifndef FREERTOS_BSP
|
||||
orr x0, x0, #(0x1 << 10)
|
||||
#endif
|
||||
msr CPTR_EL3, x0
|
||||
isb
|
||||
|
||||
/*
|
||||
* Clear FPUStatus variable to make sure that it contains current
|
||||
* status of FPU i.e. disabled. In case of a warm restart execution
|
||||
* when bss sections are not cleared, it may contain previously updated
|
||||
* value which does not hold true now.
|
||||
*/
|
||||
#ifndef FREERTOS_BSP
|
||||
ldr x0,=FPUStatus
|
||||
str xzr, [x0]
|
||||
#endif
|
||||
/* Configure SCR_EL3 */
|
||||
mov w1, #0 //; Initial value of register is unknown
|
||||
orr w1, w1, #(1 << 11) //; Set ST bit (Secure EL1 can access CNTPS_TVAL_EL1, CNTPS_CTL_EL1 & CNTPS_CVAL_EL1)
|
||||
orr w1, w1, #(1 << 10) //; Set RW bit (EL1 is AArch64, as this is the Secure world)
|
||||
orr w1, w1, #(1 << 3) //; Set EA bit (SError routed to EL3)
|
||||
orr w1, w1, #(1 << 2) //; Set FIQ bit (FIQs routed to EL3)
|
||||
orr w1, w1, #(1 << 1) //; Set IRQ bit (IRQs routed to EL3)
|
||||
msr SCR_EL3, x1
|
||||
|
||||
/*configure cpu auxiliary control register EL1 */
|
||||
ldr x0,=0x80CA000 // L1 Data prefetch control - 5, Enable device split throttle, 2 independent data prefetch streams
|
||||
#if CONFIG_ARM_ERRATA_855873
|
||||
/*
|
||||
* Set ENDCCASCI bit in CPUACTLR_EL1 register, to execute data
|
||||
* cache clean operations as data cache clean and invalidate
|
||||
*
|
||||
*/
|
||||
orr x0, x0, #(1 << 44) //; Set ENDCCASCI bit
|
||||
#endif
|
||||
msr S3_1_C15_C2_0, x0 //CPUACTLR_EL1
|
||||
|
||||
/* program the counter frequency */
|
||||
ldr x0,=counterfreq
|
||||
msr CNTFRQ_EL0, x0
|
||||
|
||||
/*Enable hardware coherency between cores*/
|
||||
mrs x0, S3_1_c15_c2_1 //Read EL1 CPU Extended Control Register
|
||||
orr x0, x0, #(1 << 6) //Set the SMPEN bit
|
||||
msr S3_1_c15_c2_1, x0 //Write EL1 CPU Extended Control Register
|
||||
isb
|
||||
|
||||
tlbi ALLE3
|
||||
ic IALLU //; Invalidate I cache to PoU
|
||||
bl invalidate_dcaches
|
||||
dsb sy
|
||||
isb
|
||||
|
||||
ldr x1, =L0Table //; Get address of level 0 for TTBR0_EL3
|
||||
msr TTBR0_EL3, x1 //; Set TTBR0_EL3
|
||||
|
||||
/**********************************************
|
||||
* Set up memory attributes
|
||||
* This equates to:
|
||||
* 0 = b01000100 = Normal, Inner/Outer Non-Cacheable
|
||||
* 1 = b11111111 = Normal, Inner/Outer WB/WA/RA
|
||||
* 2 = b00000000 = Device-nGnRnE
|
||||
* 3 = b00000100 = Device-nGnRE
|
||||
* 4 = b10111011 = Normal, Inner/Outer WT/WA/RA
|
||||
**********************************************/
|
||||
ldr x1, =0x000000BB0400FF44
|
||||
msr MAIR_EL3, x1
|
||||
|
||||
#if defined (versal)
|
||||
/**********************************************
|
||||
* Set up TCR_EL3
|
||||
* Physical Address Size PS = 100 -> 44bits 16 TB
|
||||
* Granual Size TG0 = 00 -> 4KB
|
||||
* size offset of the memory region T0SZ = 20 -> (region size 2^(64-20) = 2^44)
|
||||
***************************************************/
|
||||
ldr x1,=0x80843514
|
||||
#else
|
||||
/**********************************************
|
||||
* Set up TCR_EL3
|
||||
* Physical Address Size PS = 010 -> 40bits 1TB
|
||||
* Granual Size TG0 = 00 -> 4KB
|
||||
* size offset of the memory region T0SZ = 24 -> (region size 2^(64-24) = 2^40)
|
||||
***************************************************/
|
||||
ldr x1,=0x80823518
|
||||
#endif
|
||||
msr TCR_EL3, x1
|
||||
isb
|
||||
|
||||
/* Enable SError Exception for asynchronous abort */
|
||||
mrs x1,DAIF
|
||||
bic x1,x1,#(0x1<<8)
|
||||
msr DAIF,x1
|
||||
|
||||
/* Configure SCTLR_EL3 */
|
||||
mov x1, #0 //Most of the SCTLR_EL3 bits are unknown at reset
|
||||
orr x1, x1, #(1 << 12) //Enable I cache
|
||||
orr x1, x1, #(1 << 3) //Enable SP alignment check
|
||||
orr x1, x1, #(1 << 2) //Enable caches
|
||||
orr x1, x1, #(1 << 0) //Enable MMU
|
||||
msr SCTLR_EL3, x1
|
||||
dsb sy
|
||||
isb
|
||||
|
||||
b _startup //jump to start
|
||||
.else
|
||||
b error // present exception level and selected exception level mismatch
|
||||
.endif
|
||||
|
||||
InitEL1:
|
||||
.if (EL1_NONSECURE == 1)
|
||||
/*Set vector table base address*/
|
||||
ldr x1, =vector_base
|
||||
msr VBAR_EL1,x1
|
||||
|
||||
mrs x0, CPACR_EL1
|
||||
bic x0, x0, #(0x3 << 0x20)
|
||||
msr CPACR_EL1, x0
|
||||
isb
|
||||
|
||||
/*
|
||||
* Clear FPUStatus variable to make sure that it contains current
|
||||
* status of FPU i.e. disabled. In case of a warm restart execution
|
||||
* when bss sections are not cleared, it may contain previously updated
|
||||
* value which does not hold true now.
|
||||
*/
|
||||
#ifndef FREERTOS_BSP
|
||||
ldr x0,=FPUStatus
|
||||
str xzr, [x0]
|
||||
#endif
|
||||
/*Define stack pointer for current exception level*/
|
||||
#ifdef FREERTOS_SMP
|
||||
/*EL3_stack_end */
|
||||
/*------------*/
|
||||
/* CPU0 stack */
|
||||
/*------------*/
|
||||
/* CPU1 stack */
|
||||
/*------------*/
|
||||
/* CPU2 stack */
|
||||
/*------------*/
|
||||
/* CPU3 stack */
|
||||
/*------------*/
|
||||
/* EL3_stack */
|
||||
mov x0, N_CPUS_SHIFT
|
||||
ldr x1, =EL1_stack_end
|
||||
ldr x2, =EL1_stack
|
||||
subs x1, x2, x1
|
||||
lsr x1, x1, x0
|
||||
mul x0, x1, x4
|
||||
add x2, x2, x0
|
||||
mov sp, x2
|
||||
#else
|
||||
ldr x2, =EL1_stack
|
||||
mov sp, x2
|
||||
#endif
|
||||
|
||||
/* Disable MMU first */
|
||||
mov x1,#0x0
|
||||
msr SCTLR_EL1, x1
|
||||
isb
|
||||
|
||||
TLBI VMALLE1
|
||||
|
||||
ic IALLU //; Invalidate I cache to PoU
|
||||
bl invalidate_dcaches
|
||||
dsb sy
|
||||
isb
|
||||
|
||||
ldr x1, =L0Table //; Get address of level 0 for TTBR0_EL1
|
||||
msr TTBR0_EL1, x1 //; Set TTBR0_EL1
|
||||
|
||||
/**********************************************
|
||||
* Set up memory attributes
|
||||
* This equates to:
|
||||
* 0 = b01000100 = Normal, Inner/Outer Non-Cacheable
|
||||
* 1 = b11111111 = Normal, Inner/Outer WB/WA/RA
|
||||
* 2 = b00000000 = Device-nGnRnE
|
||||
* 3 = b00000100 = Device-nGnRE
|
||||
* 4 = b10111011 = Normal, Inner/Outer WT/WA/RA
|
||||
**********************************************/
|
||||
ldr x1, =0x000000BB0400FF44
|
||||
msr MAIR_EL1, x1
|
||||
|
||||
#if defined (versal)
|
||||
/**********************************************
|
||||
* Set up TCR_EL1
|
||||
* Physical Address Size PS = 100 -> 44bits 16TB
|
||||
* Granual Size TG0 = 00 -> 4KB
|
||||
* size offset of the memory region T0SZ = 20 -> (region size 2^(64-20) = 2^44)
|
||||
***************************************************/
|
||||
ldr x1,=0x485800514
|
||||
#else
|
||||
/**********************************************
|
||||
* Set up TCR_EL1
|
||||
* Physical Address Size PS = 010 -> 44bits 16TB
|
||||
* Granual Size TG0 = 00 -> 4KB
|
||||
* size offset of the memory region T0SZ = 24 -> (region size 2^(64-24) = 2^40)
|
||||
***************************************************/
|
||||
ldr x1,=0x285800518
|
||||
#endif
|
||||
msr TCR_EL1, x1
|
||||
isb
|
||||
/* Enable SError Exception for asynchronous abort */
|
||||
mrs x1,DAIF
|
||||
bic x1,x1,#(0x1<<8)
|
||||
msr DAIF,x1
|
||||
|
||||
//; Enable MMU
|
||||
mov x1,#0x0
|
||||
orr x1, x1, #(1 << 18) // ; Set WFE non trapping
|
||||
orr x1, x1, #(1 << 17) // ; Set WFI non trapping
|
||||
orr x1, x1, #(1 << 5) // ; Set CP15 barrier enabled
|
||||
orr x1, x1, #(1 << 12) // ; Set I bit
|
||||
orr x1, x1, #(1 << 2) // ; Set C bit
|
||||
orr x1, x1, #(1 << 0) // ; Set M bit
|
||||
msr SCTLR_EL1, x1
|
||||
isb
|
||||
|
||||
bl _startup //jump to start
|
||||
.else
|
||||
b error // present exception level and selected exception level mismatch
|
||||
.endif
|
||||
|
||||
error:
|
||||
b error
|
||||
|
||||
|
||||
invalidate_dcaches:
|
||||
|
||||
dmb ISH
|
||||
mrs x0, CLIDR_EL1 //; x0 = CLIDR
|
||||
ubfx w2, w0, #24, #3 //; w2 = CLIDR.LoC
|
||||
cmp w2, #0 //; LoC is 0?
|
||||
b.eq invalidateCaches_end //; No cleaning required and enable MMU
|
||||
mov w1, #0 //; w1 = level iterator
|
||||
|
||||
invalidateCaches_flush_level:
|
||||
add w3, w1, w1, lsl #1 //; w3 = w1 * 3 (right-shift for cache type)
|
||||
lsr w3, w0, w3 //; w3 = w0 >> w3
|
||||
ubfx w3, w3, #0, #3 //; w3 = cache type of this level
|
||||
cmp w3, #2 //; No cache at this level?
|
||||
b.lt invalidateCaches_next_level
|
||||
|
||||
lsl w4, w1, #1
|
||||
msr CSSELR_EL1, x4 //; Select current cache level in CSSELR
|
||||
isb //; ISB required to reflect new CSIDR
|
||||
mrs x4, CCSIDR_EL1 //; w4 = CSIDR
|
||||
|
||||
ubfx w3, w4, #0, #3
|
||||
add w3, w3, #2 //; w3 = log2(line size)
|
||||
ubfx w5, w4, #13, #15
|
||||
ubfx w4, w4, #3, #10 //; w4 = Way number
|
||||
clz w6, w4 //; w6 = 32 - log2(number of ways)
|
||||
|
||||
invalidateCaches_flush_set:
|
||||
mov w8, w4 //; w8 = Way number
|
||||
invalidateCaches_flush_way:
|
||||
lsl w7, w1, #1 //; Fill level field
|
||||
lsl w9, w5, w3
|
||||
orr w7, w7, w9 //; Fill index field
|
||||
lsl w9, w8, w6
|
||||
orr w7, w7, w9 //; Fill way field
|
||||
dc CISW, x7 //; Invalidate by set/way to point of coherency
|
||||
subs w8, w8, #1 //; Decrement way
|
||||
b.ge invalidateCaches_flush_way
|
||||
subs w5, w5, #1 //; Descrement set
|
||||
b.ge invalidateCaches_flush_set
|
||||
|
||||
invalidateCaches_next_level:
|
||||
add w1, w1, #1 //; Next level
|
||||
cmp w2, w1
|
||||
b.gt invalidateCaches_flush_level
|
||||
|
||||
invalidateCaches_end:
|
||||
ret
|
||||
|
||||
.end
|
||||
/**
|
||||
* @} End of "addtogroup a53_64_boot_code".
|
||||
*/
|
||||
+240
@@ -0,0 +1,240 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2024 - 2028 MindCurise, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -------------------------------------------------------
|
||||
* 1.00 yafeng.yun 5/31/24 Initial version
|
||||
******************************************************************************/
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
#define CPU_OK 0
|
||||
#define CPU_FAIL 1
|
||||
|
||||
#define CPU_A53_0 (uint32_t)(0x0u)
|
||||
#define CPU_A53_1 (uint32_t)(0x1u)
|
||||
#define CPU_A53_2 (uint32_t)(0x2u)
|
||||
#define CPU_A53_3 (uint32_t)(0x3u)
|
||||
|
||||
|
||||
|
||||
static uint32_t PowerUpIsland(uint32_t PwrIslandMask)
|
||||
{
|
||||
uint32_t RegVal;
|
||||
uint32_t Status = CPU_OK;
|
||||
|
||||
/* Power up request enable */
|
||||
Xil_Out32(PMU_GLOBAL_REQ_PWRUP_INT_EN, PwrIslandMask);
|
||||
|
||||
/* Trigger power up request */
|
||||
Xil_Out32(PMU_GLOBAL_REQ_PWRUP_TRIG, PwrIslandMask);
|
||||
|
||||
/* Poll for Power up complete */
|
||||
do {
|
||||
RegVal = Xil_In32(PMU_GLOBAL_REQ_PWRUP_STATUS) & PwrIslandMask;
|
||||
} while (RegVal != 0x0U);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
static uint32_t ReleaseReset_A53 (uint32_t CpuID)
|
||||
{
|
||||
uint32_t RegValue;
|
||||
uint32_t Status;
|
||||
uint32_t PwrStateMask;
|
||||
switch(CpuID)
|
||||
{
|
||||
|
||||
case CPU_A53_0:
|
||||
PwrStateMask = PMU_GLOBAL_PWR_STATE_ACPU0_MASK | PMU_GLOBAL_PWR_STATE_FP_MASK | PMU_GLOBAL_PWR_STATE_L2_BANK0_MASK;
|
||||
Status = PowerUpIsland(PwrStateMask);
|
||||
if (Status != CPU_OK) {
|
||||
goto END;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the clock
|
||||
*/
|
||||
RegValue = Xil_In32(CRF_APB_ACPU_CTRL);
|
||||
RegValue |= (CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK | CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK);
|
||||
Xil_Out32(CRF_APB_ACPU_CTRL, RegValue);
|
||||
|
||||
/**
|
||||
* Release reset
|
||||
*/
|
||||
RegValue = Xil_In32(CRF_APB_RST_FPD_APU);
|
||||
RegValue &= ~(CRF_APB_RST_FPD_APU_ACPU0_RESET_MASK | CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK | CRF_APB_RST_FPD_APU_ACPU0_PWRON_RESET_MASK);
|
||||
Xil_Out32(CRF_APB_RST_FPD_APU, RegValue);
|
||||
break;
|
||||
|
||||
case CPU_A53_1:
|
||||
PwrStateMask = PMU_GLOBAL_PWR_STATE_ACPU1_MASK | PMU_GLOBAL_PWR_STATE_FP_MASK | PMU_GLOBAL_PWR_STATE_L2_BANK0_MASK;
|
||||
Status = PowerUpIsland(PwrStateMask);
|
||||
if (Status != CPU_OK) {
|
||||
goto END;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the clock
|
||||
*/
|
||||
RegValue = Xil_In32(CRF_APB_ACPU_CTRL);
|
||||
RegValue |= (CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK | CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK);
|
||||
Xil_Out32(CRF_APB_ACPU_CTRL, RegValue);
|
||||
|
||||
/**
|
||||
* Release reset
|
||||
*/
|
||||
RegValue = Xil_In32(CRF_APB_RST_FPD_APU);
|
||||
RegValue &= ~(CRF_APB_RST_FPD_APU_ACPU1_RESET_MASK | CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK | CRF_APB_RST_FPD_APU_ACPU1_PWRON_RESET_MASK);
|
||||
Xil_Out32(CRF_APB_RST_FPD_APU, RegValue);
|
||||
break;
|
||||
|
||||
case CPU_A53_2:
|
||||
PwrStateMask = PMU_GLOBAL_PWR_STATE_ACPU2_MASK | PMU_GLOBAL_PWR_STATE_FP_MASK | PMU_GLOBAL_PWR_STATE_L2_BANK0_MASK;
|
||||
Status = PowerUpIsland(PwrStateMask);
|
||||
if (Status != CPU_OK) {
|
||||
goto END;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the clock
|
||||
*/
|
||||
RegValue = Xil_In32(CRF_APB_ACPU_CTRL);
|
||||
RegValue |= (CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK | CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK);
|
||||
Xil_Out32(CRF_APB_ACPU_CTRL, RegValue);
|
||||
|
||||
/**
|
||||
* Release reset
|
||||
*/
|
||||
RegValue = Xil_In32(CRF_APB_RST_FPD_APU);
|
||||
RegValue &= ~(CRF_APB_RST_FPD_APU_ACPU2_RESET_MASK | CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK | CRF_APB_RST_FPD_APU_ACPU2_PWRON_RESET_MASK);
|
||||
Xil_Out32(CRF_APB_RST_FPD_APU, RegValue);
|
||||
break;
|
||||
|
||||
case CPU_A53_3:
|
||||
PwrStateMask = PMU_GLOBAL_PWR_STATE_ACPU3_MASK | PMU_GLOBAL_PWR_STATE_FP_MASK | PMU_GLOBAL_PWR_STATE_L2_BANK0_MASK;
|
||||
Status = PowerUpIsland(PwrStateMask);
|
||||
if (Status != CPU_OK) {
|
||||
goto END;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the clock
|
||||
*/
|
||||
RegValue = Xil_In32(CRF_APB_ACPU_CTRL);
|
||||
RegValue |= (CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK | CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK);
|
||||
Xil_Out32(CRF_APB_ACPU_CTRL, RegValue);
|
||||
|
||||
/**
|
||||
* Release reset
|
||||
*/
|
||||
RegValue = Xil_In32(CRF_APB_RST_FPD_APU);
|
||||
RegValue &= ~(CRF_APB_RST_FPD_APU_ACPU3_RESET_MASK | CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK | CRF_APB_RST_FPD_APU_ACPU3_PWRON_RESET_MASK);
|
||||
Xil_Out32(CRF_APB_RST_FPD_APU, RegValue);
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = CPU_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
END:
|
||||
return Status;
|
||||
}
|
||||
|
||||
static void SetCoreResetVector_A53 (uint32_t CpuID, uint64_t VectorAddr)
|
||||
{
|
||||
uint32_t VectorAddrLow;
|
||||
uint32_t VectorAddrHigh;
|
||||
uint32_t LowAddressReg;
|
||||
uint32_t HighAddressReg;
|
||||
|
||||
/**
|
||||
* for A53 cpu, write 64bit handoff address
|
||||
* to the RVBARADDR in APU
|
||||
*/
|
||||
VectorAddrLow = (uint32_t )(VectorAddr & 0xFFFFFFFFU);
|
||||
VectorAddrHigh = (uint32_t )((VectorAddr>>32) & 0xFFFFFFFFU);
|
||||
switch (CpuID)
|
||||
{
|
||||
case CPU_A53_0:
|
||||
LowAddressReg = APU_RVBARADDR0L;
|
||||
HighAddressReg = APU_RVBARADDR0H;
|
||||
break;
|
||||
case CPU_A53_1:
|
||||
LowAddressReg = APU_RVBARADDR1L;
|
||||
HighAddressReg = APU_RVBARADDR1H;
|
||||
break;
|
||||
case CPU_A53_2:
|
||||
LowAddressReg = APU_RVBARADDR2L;
|
||||
HighAddressReg = APU_RVBARADDR2H;
|
||||
break;
|
||||
case CPU_A53_3:
|
||||
LowAddressReg = APU_RVBARADDR3L;
|
||||
HighAddressReg = APU_RVBARADDR3H;
|
||||
break;
|
||||
|
||||
default:
|
||||
/**
|
||||
* error can be triggered here
|
||||
*/
|
||||
LowAddressReg = 0U;
|
||||
HighAddressReg = 0U;
|
||||
break;
|
||||
}
|
||||
Xil_Out32(LowAddressReg, VectorAddrLow);
|
||||
Xil_Out32(HighAddressReg, VectorAddrHigh);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
uint32_t CpuUp_A53(uint32_t CpuID, uint64_t ResetAddress)
|
||||
{
|
||||
Xil_DCacheDisable();
|
||||
|
||||
// Step 1: Setup Reset vector of the core
|
||||
SetCoreResetVector_A53(CpuID, ResetAddress);
|
||||
|
||||
// Step 2: Take the core out of reset
|
||||
ReleaseReset_A53(CpuID);
|
||||
|
||||
Xil_DCacheEnable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void StartAndWaitSecondaryCpuUp(uint64_t CpuID, uint64_t ResetAddr)
|
||||
{
|
||||
static volatile uint32_t CpuUpFlags[4] = {0};
|
||||
if (CpuID == 0)
|
||||
{
|
||||
CpuUpFlags[CpuID] = 1;
|
||||
for (CpuID = 1; CpuID < 4; ++CpuID)
|
||||
{
|
||||
|
||||
extern void Xil_Assert(const char *File, int32_t Line);
|
||||
if (CpuUp_A53((uint32_t)CpuID, ResetAddr) != 0)
|
||||
{
|
||||
Xil_Assert(__FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for secondary CPUs up
|
||||
int CpuIndx = 0;
|
||||
while (CpuIndx < 4)
|
||||
{
|
||||
if (CpuUpFlags[CpuIndx] != 0)
|
||||
{
|
||||
CpuIndx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CpuUpFlags[CpuID] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
+979
@@ -0,0 +1,979 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2015 - 2020 Xilinx, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* @file portZynqHW.h
|
||||
*
|
||||
* This is the header file which contains definitions for the hardware
|
||||
* registers.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -------------------------------------------------------
|
||||
* 1.00 kc 10/21/13 Initial release
|
||||
* 2.0 bv 12/05/16 Made compliance to MISRAC 2012 guidelines
|
||||
* 3.0 vns 09/08/17 Added eFUSE secure control register masks for PPK revoke
|
||||
* 4.0 vns 02/02/18 Added warning message to notify SHA2 support
|
||||
* deprecation in future releases.
|
||||
* vns 03/07/18 Added ENC_ONLY mask
|
||||
* 4.0 vns 03/14/19 Added AES reset offset and Mask values.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @note Copied from xfsbl_hw.h of 'zynqmp_fsbl'
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef CPU_H
|
||||
#define CPU_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
#include "xil_io.h"
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
|
||||
/* csu */
|
||||
|
||||
/**
|
||||
* CSU Base Address
|
||||
*/
|
||||
#define CSU_BASEADDR 0XFFCA0000U
|
||||
|
||||
/**
|
||||
* Register: CSU_CSU_SSS_CFG
|
||||
*/
|
||||
#define CSU_CSU_SSS_CFG ( ( CSU_BASEADDR ) + 0X00000008U )
|
||||
#define CSU_CSU_SSS_CFG_PCAP_SSS_MASK 0X0000000FU
|
||||
#define CSU_CSU_SSS_CFG_PCAP_SSS_SHIFT 0U
|
||||
#define CSU_CSU_SSS_CFG_DMA_SSS_SHIFT 1U
|
||||
|
||||
/**
|
||||
* Register: CSU AES RESET
|
||||
*/
|
||||
#define CSU_AES_RESET ( ( CSU_BASEADDR ) + 0X00001010U )
|
||||
#define CSU_AES_RESET_RESET_MASK 0X00000001U
|
||||
|
||||
/**
|
||||
* Register: CSU_PCAP_STATUS
|
||||
*/
|
||||
#define CSU_PCAP_STATUS ( ( CSU_BASEADDR ) + 0X00003010U )
|
||||
#define CSU_PCAP_STATUS_PL_INIT_SHIFT 2U
|
||||
#define CSU_PCAP_STATUS_PL_INIT_MASK 0X00000004U
|
||||
#define CSU_PCAP_STATUS_PCAP_WR_IDLE_MASK 0X00000001U
|
||||
#define CSU_PCAP_STATUS_PL_DONE_MASK 0X00000008U
|
||||
#define CSU_PCAP_STATUS_PL_CFG_RST_MASK 0x00000040U
|
||||
|
||||
/**
|
||||
* Register: CSU_PCAP_RDWR
|
||||
*/
|
||||
#define CSU_PCAP_RDWR ( ( CSU_BASEADDR ) + 0X00003004U )
|
||||
#define CSU_PCAP_RDWR_PCAP_RDWR_B_SHIFT 0U
|
||||
|
||||
/* Register: CSU_PCAP_PROG */
|
||||
#define CSU_PCAP_PROG ( ( CSU_BASEADDR ) + 0X00003000U )
|
||||
#define CSU_PCAP_PROG_PCFG_PROG_B_MASK 0X00000001U
|
||||
#define CSU_PCAP_PROG_PCFG_PROG_B_SHIFT 0U
|
||||
|
||||
/**
|
||||
* Register: CSU_VERSION
|
||||
*/
|
||||
#define CSU_VERSION ( ( CSU_BASEADDR ) + 0X00000044U )
|
||||
|
||||
#define CSU_VERSION_PLATFORM_MASK 0X0000F000U
|
||||
|
||||
/**
|
||||
* Register: CSU_CSU_MULTI_BOOT
|
||||
*/
|
||||
#define CSU_CSU_MULTI_BOOT ( ( CSU_BASEADDR ) + 0X00000010U )
|
||||
|
||||
/**
|
||||
* Register: CSU_SHA_RESET
|
||||
*/
|
||||
#define CSU_SHA_RESET ( ( CSU_BASEADDR ) + 0X00002004U )
|
||||
#define CSU_SHA_RESET_RESET_MASK 0X00000001U
|
||||
|
||||
/**
|
||||
* Register: CSU_SHA_START
|
||||
*/
|
||||
#define CSU_SHA_START ( ( CSU_BASEADDR ) + 0X00002000U )
|
||||
#define CSU_SHA_START_START_MSG_MASK 0X00000001U
|
||||
|
||||
/**
|
||||
* Register: CSU_SHA_DONE
|
||||
*/
|
||||
#define CSU_SHA_DONE ( ( CSU_BASEADDR ) + 0X00002008U )
|
||||
#define CSU_SHA_DONE_SHA_DONE_MASK 0X00000001U
|
||||
|
||||
/**
|
||||
* Register: CSU_SHA_DIGEST_0
|
||||
*/
|
||||
#define CSU_SHA_DIGEST_0 ( ( CSU_BASEADDR ) + 0X00002010U )
|
||||
|
||||
/* Register: CSU_PCAP_RESET */
|
||||
#define CSU_PCAP_RESET ( ( CSU_BASEADDR ) + 0X0000300CU )
|
||||
#define CSU_PCAP_RESET_RESET_MASK 0X00000001U
|
||||
|
||||
/* Register: CSU_PCAP_CTRL */
|
||||
#define CSU_PCAP_CTRL ( ( CSU_BASEADDR ) + 0X00003008U )
|
||||
#define CSU_PCAP_CTRL_PCAP_PR_MASK 0X00000001U
|
||||
|
||||
/* Register: CSU_IDCODE */
|
||||
#define CSU_IDCODE ( ( CSU_BASEADDR ) + 0X00000040U )
|
||||
|
||||
#define CSU_IDCODE_SVD_SHIFT 12U
|
||||
#define CSU_IDCODE_SVD_MASK (0x7U << CSU_IDCODE_SVD_SHIFT)
|
||||
#define CSU_IDCODE_DEVICE_CODE_SHIFT 15U
|
||||
#define CSU_IDCODE_DEVICE_CODE_MASK (0xFU << CSU_IDCODE_DEVICE_CODE_SHIFT)
|
||||
|
||||
/* efuse */
|
||||
|
||||
/**
|
||||
* EFUSE Base Address
|
||||
*/
|
||||
#define EFUSE_BASEADDR 0XFFCC0000U
|
||||
|
||||
/**
|
||||
* Register: EFUSE_SEC_CTRL
|
||||
*/
|
||||
#define EFUSE_SEC_CTRL ( ( EFUSE_BASEADDR ) + 0X00001058U )
|
||||
#define EFUSE_SEC_CTRL_ENC_ONLY_MASK 0x00000004U
|
||||
#define EFUSE_SEC_CTRL_RSA_EN_MASK 0x03FFF800U
|
||||
#define EFUSE_SEC_CTRL_PPK0_RVK_MASK 0x18000000U
|
||||
#define EFUSE_SEC_CTRL_PPK1_RVK_MASK 0xC0000000U
|
||||
|
||||
/* Register: EFUSE_IPDISABLE */
|
||||
#define EFUSE_IPDISABLE ( ( EFUSE_BASEADDR ) + 0X00001018U )
|
||||
|
||||
#define EFUSE_IPDISABLE_GPU_DIS_MASK 0X00000020U
|
||||
#define EFUSE_IPDISABLE_APU3_DIS_MASK 0X00000008U
|
||||
#define EFUSE_IPDISABLE_APU2_DIS_MASK 0X00000004U
|
||||
#define EFUSE_IPDISABLE_VCU_DIS_MASK 0x00000100U
|
||||
|
||||
/* Register PPK0_0 */
|
||||
#define EFUSE_PPK0 (EFUSE_BASEADDR + 0x000010A0U)
|
||||
|
||||
/* Register PPK1_0 */
|
||||
#define EFUSE_PPK1 (EFUSE_BASEADDR + 0x000010D0U)
|
||||
|
||||
/* Register SPK ID */
|
||||
#define EFUSE_SPKID (EFUSE_BASEADDR + 0x0000105CU)
|
||||
|
||||
/* csudma */
|
||||
|
||||
/**
|
||||
* CSUDMA Base Address
|
||||
*/
|
||||
#define CSUDMA_BASEADDR 0XFFC80000U
|
||||
|
||||
/* crf_apb */
|
||||
|
||||
/**
|
||||
* CRF_APB Base Address
|
||||
*/
|
||||
#define CRF_APB_BASEADDR 0XFD1A0000U
|
||||
|
||||
/**
|
||||
* Register: CRF_APB_RST_FPD_APU
|
||||
*/
|
||||
#define CRF_APB_RST_FPD_APU ( ( CRF_APB_BASEADDR ) + 0X00000104U )
|
||||
#define CRF_APB_RST_FPD_APU_ACPU0_RESET_MASK (u32)0X00000001U
|
||||
#define CRF_APB_RST_FPD_APU_APU_L2_RESET_MASK (u32)0X00000100U
|
||||
|
||||
/**
|
||||
* Register: CRF_APB_ACPU_CTRL
|
||||
*/
|
||||
#define CRF_APB_ACPU_CTRL ( ( CRF_APB_BASEADDR ) + 0X00000060U )
|
||||
#define CRF_APB_ACPU_CTRL_CLKACT_FULL_MASK 0X01000000U
|
||||
#define CRF_APB_ACPU_CTRL_CLKACT_HALF_MASK 0X02000000U
|
||||
#define CRF_APB_RST_FPD_APU_ACPU1_RESET_MASK (u32)0X00000002U
|
||||
#define CRF_APB_RST_FPD_APU_ACPU2_RESET_MASK (u32)0X00000004U
|
||||
#define CRF_APB_RST_FPD_APU_ACPU3_RESET_MASK (u32) 0X00000008U
|
||||
|
||||
#define CRF_APB_RST_FPD_APU_ACPU3_PWRON_RESET_MASK (u32)0X00002000U
|
||||
#define CRF_APB_RST_FPD_APU_ACPU2_PWRON_RESET_MASK (u32)0X00001000U
|
||||
#define CRF_APB_RST_FPD_APU_ACPU1_PWRON_RESET_MASK (u32)0X00000800U
|
||||
#define CRF_APB_RST_FPD_APU_ACPU0_PWRON_RESET_MASK (u32)0X00000400U
|
||||
|
||||
/* crl_apb */
|
||||
|
||||
/**
|
||||
* CRL_APB Base Address
|
||||
*/
|
||||
#define CRL_APB_BASEADDR 0XFF5E0000U
|
||||
|
||||
/**
|
||||
* Register: CRL_APB_CPU_R5_CTRL
|
||||
*/
|
||||
#define CRL_APB_CPU_R5_CTRL ( ( CRL_APB_BASEADDR ) + 0X00000090U )
|
||||
#define CRL_APB_CPU_R5_CTRL_CLKACT_MASK 0X01000000U
|
||||
|
||||
/**
|
||||
* Register: CRL_APB_RST_LPD_TOP
|
||||
*/
|
||||
#define CRL_APB_RST_LPD_TOP ( ( CRL_APB_BASEADDR ) + 0X0000023CU )
|
||||
#define CRL_APB_RST_LPD_TOP_RPU_R50_RESET_MASK (u32)0X00000001U
|
||||
#define CRL_APB_RST_LPD_TOP_RPU_AMBA_RESET_MASK (u32)0X00000004U
|
||||
#define CRL_APB_RST_LPD_TOP_RPU_R51_RESET_MASK (u32)0X00000002U
|
||||
|
||||
/**
|
||||
* Register: CRL_APB_BOOT_MODE_USER
|
||||
*/
|
||||
#define CRL_APB_BOOT_MODE_USER ( ( CRL_APB_BASEADDR ) + 0X00000200U )
|
||||
#define CRL_APB_BOOT_MODE_USER_BOOT_MODE_MASK 0X0000000FU
|
||||
|
||||
/**
|
||||
* Register: CRL_APB_RESET_CTRL
|
||||
*/
|
||||
#define CRL_APB_RESET_CTRL ( ( CRL_APB_BASEADDR ) + 0X00000218U )
|
||||
#define CRL_APB_RESET_CTRL_SOFT_RESET_MASK 0X00000010U
|
||||
|
||||
/* Register: CRL_APB_PCAP_CTRL */
|
||||
#define CRL_APB_PCAP_CTRL ( ( CRL_APB_BASEADDR ) + 0X000000A4U )
|
||||
#define CRL_APB_PCAP_CTRL_DIVISOR0_SHIFT 8U
|
||||
#define CRL_APB_PCAP_CTRL_DIVISOR0_MASK 0X00003F00U
|
||||
#define CRL_APB_PCAP_CTRL_CLKACT_MASK 0X01000000U
|
||||
|
||||
/* Register: CRL_APB_RESET_REASON */
|
||||
#define CRL_APB_RESET_REASON ( ( CRL_APB_BASEADDR ) + 0X00000220U )
|
||||
#define CRL_APB_RESET_REASON_PMU_SYS_RESET_MASK 0X00000004U
|
||||
#define CRL_APB_RESET_REASON_PSONLY_RESET_REQ_MASK 0x00000008U
|
||||
|
||||
/**
|
||||
* Register: CRL_APB_RPLL_CTRL
|
||||
*/
|
||||
#define CRL_APB_RPLL_CTRL ( ( CRL_APB_BASEADDR ) + 0X00000030U )
|
||||
#define CRL_APB_RPLL_CTRL_BYPASS_MASK 0X00000008U
|
||||
|
||||
|
||||
/* apu */
|
||||
|
||||
/**
|
||||
* APU Base Address
|
||||
*/
|
||||
#define APU_BASEADDR 0XFD5C0000U
|
||||
|
||||
/**
|
||||
* Register: APU_CONFIG_0
|
||||
*/
|
||||
#define APU_CONFIG_0 ( ( APU_BASEADDR ) + 0X00000020U )
|
||||
#define APU_CONFIG_0_VINITHI_MASK 0x000000F0
|
||||
|
||||
/**
|
||||
* Register: APU_RVBARADDR0L
|
||||
*/
|
||||
#define APU_RVBARADDR0L ( ( APU_BASEADDR ) + 0X00000040U )
|
||||
|
||||
/**
|
||||
* Register: APU_RVBARADDR0H
|
||||
*/
|
||||
#define APU_RVBARADDR0H ( ( APU_BASEADDR ) + 0X00000044U )
|
||||
|
||||
/**
|
||||
* Register: APU_RVBARADDR1L
|
||||
*/
|
||||
#define APU_RVBARADDR1L ( ( APU_BASEADDR ) + 0X00000048U )
|
||||
|
||||
/**
|
||||
* Register: APU_RVBARADDR1H
|
||||
*/
|
||||
#define APU_RVBARADDR1H ( ( APU_BASEADDR ) + 0X0000004CU )
|
||||
|
||||
/**
|
||||
* Register: APU_RVBARADDR2L
|
||||
*/
|
||||
#define APU_RVBARADDR2L ( ( APU_BASEADDR ) + 0X00000050U )
|
||||
|
||||
/**
|
||||
* Register: APU_RVBARADDR2H
|
||||
*/
|
||||
#define APU_RVBARADDR2H ( ( APU_BASEADDR ) + 0X00000054U )
|
||||
|
||||
/**
|
||||
* Register: APU_RVBARADDR3L
|
||||
*/
|
||||
#define APU_RVBARADDR3L ( ( APU_BASEADDR ) + 0X00000058U )
|
||||
|
||||
/**
|
||||
* Register: APU_RVBARADDR3H
|
||||
*/
|
||||
#define APU_RVBARADDR3H ( ( APU_BASEADDR ) + 0X0000005CU )
|
||||
|
||||
/* pmu_global */
|
||||
#define PMU_GLOBAL_GLOB_GEN_STORAGE6 ( ( PMU_GLOBAL_BASEADDR ) + 0X48U )
|
||||
#define PMU_GLOBAL_GLOB_GEN_STORAGE5 ( ( PMU_GLOBAL_BASEADDR ) + 0x44U )
|
||||
#define PMU_GLOBAL_GLOB_GEN_STORAGE4 ( ( PMU_GLOBAL_BASEADDR ) + 0X40U )
|
||||
#define PMU_GLOBAL_GLOB_GEN_STORAGE1 ( ( PMU_GLOBAL_BASEADDR ) + 0X34U )
|
||||
#define PMU_GLOBAL_GLOB_GEN_STORAGE2 ( ( PMU_GLOBAL_BASEADDR ) + 0X38U )
|
||||
|
||||
/**
|
||||
* Register: PMU_GLOBAL_PERS_GLOB_GEN_STORAGE4
|
||||
*/
|
||||
#define PMU_GLOBAL_PERS_GLOB_GEN_STORAGE4 ( ( PMU_GLOBAL_BASEADDR ) + 0X00000060U )
|
||||
|
||||
/**
|
||||
* Register: PMU_GLOBAL_PERS_GLOB_GEN_STORAGE5
|
||||
*/
|
||||
#define PMU_GLOBAL_PERS_GLOB_GEN_STORAGE5 ( ( PMU_GLOBAL_BASEADDR ) + 0X00000064U )
|
||||
|
||||
/*
|
||||
* Register: PMU_GLOBAL_PERS_GLOB_GEN_STORAGE7
|
||||
*/
|
||||
#define PMU_GLOBAL_PERS_GLOB_GEN_STORAGE7 ( ( PMU_GLOBAL_BASEADDR ) + 0X0000006CU )
|
||||
|
||||
/**
|
||||
* PMU_GLOBAL Base Address
|
||||
*/
|
||||
#define PMU_GLOBAL_BASEADDR 0XFFD80000U
|
||||
|
||||
#define PMU_GLOBAL_GLOBAL_CNTRL ( ( PMU_GLOBAL_BASEADDR ) + 0X00000000U )
|
||||
#define PMU_GLOBAL_GLOBAL_CNTRL_MB_SLEEP_MASK 0X00010000U
|
||||
#define PMU_GLOBAL_GLOBAL_CNTRL_FW_IS_PRESENT_MASK 0X00000010U
|
||||
|
||||
#define PMU_GLOBAL_PS_CNTRL ( (PMU_GLOBAL_BASEADDR ) + 0x4U)
|
||||
#define PMU_GLOBAL_PS_CNTRL_PROG_ENABLE_MASK 0x2U
|
||||
#define PMU_GLOBAL_PS_CNTRL_PROG_GATE_MASK 0x1U
|
||||
|
||||
#define PMU_GLOBAL_AIB_CNTRL ( ( PMU_GLOBAL_BASEADDR ) + 0X600U )
|
||||
#define PMU_GLOBAL_AIB_STATUS ( ( PMU_GLOBAL_BASEADDR ) + 0X604U )
|
||||
|
||||
/* Register: PMU_GLOBAL_REQ_PWRUP_INT_EN */
|
||||
#define PMU_GLOBAL_REQ_PWRUP_INT_EN ( ( PMU_GLOBAL_BASEADDR ) + 0X00000118U )
|
||||
#define PMU_GLOBAL_REQ_PWRUP_INT_EN_PL_MASK 0X00800000U
|
||||
|
||||
/* Register: PMU_GLOBAL_REQ_PWRUP_TRIG */
|
||||
#define PMU_GLOBAL_REQ_PWRUP_TRIG ( ( PMU_GLOBAL_BASEADDR ) + 0X00000120U )
|
||||
#define PMU_GLOBAL_REQ_PWRUP_TRIG_PL_MASK 0X00800000U
|
||||
|
||||
/* Register: PMU_GLOBAL_REQ_PWRUP_STATUS */
|
||||
#define PMU_GLOBAL_REQ_PWRUP_STATUS ( ( PMU_GLOBAL_BASEADDR ) + 0X00000110U )
|
||||
#define PMU_GLOBAL_REQ_PWRUP_STATUS_PL_SHIFT 23U
|
||||
#define PMU_GLOBAL_REQ_PWRUP_STATUS_PL_MASK 0X00800000U
|
||||
|
||||
/* Register: PMU_GLOBAL_PWR_STATE */
|
||||
#define PMU_GLOBAL_PWR_STATE ( ( PMU_GLOBAL_BASEADDR ) + 0X00000100U )
|
||||
#define PMU_GLOBAL_PWR_STATE_PL_MASK 0X00800000U
|
||||
#define PMU_GLOBAL_PWR_STATE_FP_MASK 0X00400000U
|
||||
#define PMU_GLOBAL_PWR_STATE_USB1_MASK 0X00200000U
|
||||
#define PMU_GLOBAL_PWR_STATE_USB0_MASK 0X00100000U
|
||||
#define PMU_GLOBAL_PWR_STATE_OCM_BANK3_MASK 0X00080000U
|
||||
#define PMU_GLOBAL_PWR_STATE_OCM_BANK2_MASK 0X00040000U
|
||||
#define PMU_GLOBAL_PWR_STATE_OCM_BANK1_MASK 0X00020000U
|
||||
#define PMU_GLOBAL_PWR_STATE_OCM_BANK0_MASK 0X00010000U
|
||||
#define PMU_GLOBAL_PWR_STATE_TCM1B_MASK (u32)0X00008000U
|
||||
#define PMU_GLOBAL_PWR_STATE_TCM1A_MASK (u32)0X00004000U
|
||||
#define PMU_GLOBAL_PWR_STATE_TCM0B_MASK (u32)0X00002000U
|
||||
#define PMU_GLOBAL_PWR_STATE_TCM0A_MASK (u32)0X00001000U
|
||||
#define PMU_GLOBAL_PWR_STATE_R5_1_MASK (u32)0X00000800U
|
||||
#define PMU_GLOBAL_PWR_STATE_R5_0_MASK (u32)0X00000400U
|
||||
#define PMU_GLOBAL_PWR_STATE_L2_BANK0_MASK 0X00000080U
|
||||
#define PMU_GLOBAL_PWR_STATE_PP1_MASK 0X00000020U
|
||||
#define PMU_GLOBAL_PWR_STATE_PP0_MASK 0X00000010U
|
||||
#define PMU_GLOBAL_PWR_STATE_ACPU3_MASK 0X00000008U
|
||||
#define PMU_GLOBAL_PWR_STATE_ACPU2_MASK 0X00000004U
|
||||
#define PMU_GLOBAL_PWR_STATE_ACPU1_MASK 0X00000002U
|
||||
#define PMU_GLOBAL_PWR_STATE_ACPU0_MASK 0X00000001U
|
||||
|
||||
/* Register: PMU_GLOBAL_ERROR_STATUS_1 */
|
||||
#define PMU_GLOBAL_ERROR_STATUS_1 ( ( PMU_GLOBAL_BASEADDR ) + 0X00000530U )
|
||||
#define PMU_GLOBAL_ERROR_STATUS_1_LPD_SWDT_MASK 0X00001000U
|
||||
|
||||
/* Register: PMU_GLOBAL_ERROR_SRST_EN_1 */
|
||||
#define PMU_GLOBAL_ERROR_SRST_EN_1 ( ( PMU_GLOBAL_BASEADDR ) + 0X0000056CU )
|
||||
#define PMU_GLOBAL_ERROR_SRST_EN_1_LPD_SWDT_MASK 0X00001000U
|
||||
#define PMU_GLOBAL_ERROR_SRST_EN_1_FPD_SWDT_MASK 0X00002000U
|
||||
|
||||
/* Register: PMU_GLOBAL_ERROR_SRST_DIS_1 */
|
||||
#define PMU_GLOBAL_ERROR_SRST_DIS_1 ( ( PMU_GLOBAL_BASEADDR ) + 0X00000570U )
|
||||
#define PMU_GLOBAL_ERROR_SRST_DIS_1_LPD_SWDT_MASK 0X00001000U
|
||||
#define PMU_GLOBAL_ERROR_SRST_DIS_1_FPD_SWDT_MASK 0X00002000U
|
||||
|
||||
/* Register: PMU_GLOBAL_ERROR_EN_1 */
|
||||
#define PMU_GLOBAL_ERROR_EN_1 ( ( PMU_GLOBAL_BASEADDR ) + 0X000005A0U )
|
||||
#define PMU_GLOBAL_ERROR_EN_1_LPD_SWDT_MASK 0X00001000U
|
||||
|
||||
/* Register: PMU_GLOBAL_REQ_ISO_INT_EN */
|
||||
#define PMU_GLOBAL_REQ_ISO_INT_EN ( ( PMU_GLOBAL_BASEADDR ) + 0X00000318U )
|
||||
#define PMU_GLOBAL_REQ_ISO_INT_EN_PL_NONPCAP_MASK 0X00000004U
|
||||
|
||||
/* Register: PMU_GLOBAL_REQ_ISO_TRIG */
|
||||
#define PMU_GLOBAL_REQ_ISO_TRIG ( ( PMU_GLOBAL_BASEADDR ) + 0X00000320U )
|
||||
|
||||
/* Register: PMU_GLOBAL_REQ_ISO_STATUS */
|
||||
#define PMU_GLOBAL_REQ_ISO_STATUS ( ( PMU_GLOBAL_BASEADDR ) + 0X00000310U )
|
||||
|
||||
/* rpu */
|
||||
|
||||
/**
|
||||
* RPU Base Address
|
||||
*/
|
||||
#define RPU_BASEADDR 0XFF9A0000U
|
||||
|
||||
/**
|
||||
* Register: RPU_RPU_GLBL_CNTL
|
||||
*/
|
||||
#define RPU_RPU_GLBL_CNTL ( ( RPU_BASEADDR ) + 0X00000000U )
|
||||
#define RPU_RPU_GLBL_CNTL_SLSPLIT_MASK 0X00000008U
|
||||
#define RPU_RPU_GLBL_CNTL_TCM_COMB_MASK 0X00000040U
|
||||
#define RPU_RPU_GLBL_CNTL_SLCLAMP_MASK 0X00000010U
|
||||
|
||||
/**
|
||||
* Register: RPU_RPU_0_CFG
|
||||
*/
|
||||
#define RPU_RPU_0_CFG ( ( RPU_BASEADDR ) + 0X00000100U )
|
||||
#define RPU_RPU_0_CFG_VINITHI_SHIFT 2U
|
||||
#define RPU_RPU_0_CFG_VINITHI_MASK 0x00000004U
|
||||
#define RPU_RPU_0_CFG_NCPUHALT_MASK 0X00000001U
|
||||
|
||||
/**
|
||||
* Register: RPU_RPU_1_CFG
|
||||
*/
|
||||
#define RPU_RPU_1_CFG ( ( RPU_BASEADDR ) + 0X00000200U )
|
||||
#define RPU_RPU_1_CFG_VINITHI_SHIFT 2U
|
||||
#define RPU_RPU_1_CFG_VINITHI_MASK 0x00000004U
|
||||
#define RPU_RPU_1_CFG_NCPUHALT_MASK 0X00000001U
|
||||
|
||||
/* rsa */
|
||||
|
||||
/**
|
||||
* RSA Base Address
|
||||
*/
|
||||
#define RSA_BASEADDR 0XFFCE002CU
|
||||
|
||||
/**
|
||||
* Register: RSA_WR_DATA_0
|
||||
*/
|
||||
#define RSA_WR_DATA_0 ( ( RSA_BASEADDR ) + 0X00000000U )
|
||||
|
||||
/**
|
||||
* Register: RSA_WR_ADDR
|
||||
*/
|
||||
#define RSA_WR_ADDR ( ( RSA_BASEADDR ) + 0X00000018U )
|
||||
|
||||
/**
|
||||
* Register: RSA_RD_ADDR
|
||||
*/
|
||||
#define RSA_RD_ADDR ( ( RSA_BASEADDR ) + 0X00000034U )
|
||||
|
||||
/**
|
||||
* Register: RSA_RD_DATA_0
|
||||
*/
|
||||
#define RSA_RD_DATA_0 ( ( RSA_BASEADDR ) + 0X0000001CU )
|
||||
|
||||
/* rsa_core */
|
||||
|
||||
/**
|
||||
* RSA_CORE Base Address
|
||||
*/
|
||||
#define RSA_CORE_BASEADDR 0XFFCE0000U
|
||||
|
||||
/**
|
||||
* Register: RSA_CORE_MINV0
|
||||
*/
|
||||
#define RSA_CORE_MINV0 ( ( RSA_CORE_BASEADDR ) + 0X00000018U )
|
||||
|
||||
/**
|
||||
* Register: RSA_CORE_MINV1
|
||||
*/
|
||||
#define RSA_CORE_MINV1 ( ( RSA_CORE_BASEADDR ) + 0X0000001CU )
|
||||
|
||||
/**
|
||||
* Register: RSA_CORE_MINV2
|
||||
*/
|
||||
#define RSA_CORE_MINV2 ( ( RSA_CORE_BASEADDR ) + 0X00000020U )
|
||||
|
||||
/**
|
||||
* Register: RSA_CORE_MINV3
|
||||
*/
|
||||
#define RSA_CORE_MINV3 ( ( RSA_CORE_BASEADDR ) + 0X00000024U )
|
||||
|
||||
/**
|
||||
* Register: RSA_CORE_STATUS
|
||||
*/
|
||||
#define RSA_CORE_STATUS ( ( RSA_CORE_BASEADDR ) + 0X00000014U )
|
||||
#define RSA_CORE_STATUS_ERROR_MASK 0X00000004U
|
||||
#define RSA_CORE_STATUS_DONE_MASK 0X00000001U
|
||||
|
||||
/**
|
||||
* Register: RSA_CORE_CTRL
|
||||
*/
|
||||
#define RSA_CORE_CTRL ( ( RSA_CORE_BASEADDR ) + 0X00000010U )
|
||||
|
||||
/* LPD_SLCR Base Address */
|
||||
#define LPD_SLCR_BASEADDR 0XFF410000U
|
||||
|
||||
/* Register: LPD_SLCR_PERSISTENT4 */
|
||||
#define LPD_SLCR_PERSISTENT4 ( ( LPD_SLCR_BASEADDR ) + 0X00000030U )
|
||||
|
||||
/* Register: LPD_SLCR_PERSISTENT5 */
|
||||
#define LPD_SLCR_PERSISTENT5 ( ( LPD_SLCR_BASEADDR ) + 0X00000034U )
|
||||
|
||||
/* IPI Base Address */
|
||||
#define IPI_BASEADDR 0XFF300000U
|
||||
|
||||
/* Register: IPI_PMU_0_TRIG */
|
||||
#define IPI_PMU_0_TRIG ( ( IPI_BASEADDR ) + 0X00030000U )
|
||||
#define IPI_PMU_0_TRIG_PMU_0_MASK 0X00010000U
|
||||
|
||||
#define IPI_PMU_0_IER ( ( IPI_BASEADDR ) + 0X00030018U )
|
||||
#define IPI_PMU_0_IER_PMU_0_MASK 0X00010000U
|
||||
|
||||
/* serdes */
|
||||
/* SERDES Base Address */
|
||||
#define SERDES_BASEADDR 0XFD400000U
|
||||
|
||||
#define SERDES_ICM_CFG0 ( ( SERDES_BASEADDR ) + 0X00010010U )
|
||||
#define SERDES_ICM_CFG0_L1_ICM_CFG_SHIFT 4U
|
||||
#define SERDES_ICM_CFG0_L1_ICM_CFG_MASK 0X00000070U
|
||||
#define SERDES_ICM_CFG0_L0_ICM_CFG_MASK 0X00000007U
|
||||
|
||||
#define SERDES_ICM_CFG1 ( ( SERDES_BASEADDR ) + 0X00010014U )
|
||||
#define SERDES_ICM_CFG1_L3_ICM_CFG_SHIFT 4U
|
||||
#define SERDES_ICM_CFG1_L3_ICM_CFG_MASK 0X00000070U
|
||||
#define SERDES_ICM_CFG1_L2_ICM_CFG_MASK 0X00000007U
|
||||
|
||||
/* gpio */
|
||||
/* GPIO Base Address */
|
||||
#define GPIO_BASEADDR 0XFF0A0000U
|
||||
|
||||
#define GPIO_DATA_1 ( ( GPIO_BASEADDR ) + 0X00000044U )
|
||||
#define GPIO_DIRM_1 ( ( GPIO_BASEADDR ) + 0X00000244U )
|
||||
#define GPIO_OEN_1 ( ( GPIO_BASEADDR ) + 0X00000248U )
|
||||
|
||||
/* IOU_SLCR Base Address */
|
||||
#define IOU_SLCR_BASEADDR 0XFF180000U
|
||||
|
||||
/* Register: IOU_SLCR_SD_CDN_CTRL */
|
||||
#define IOU_SLCR_SD_CDN_CTRL ( ( IOU_SLCR_BASEADDR ) + 0X0000035CU )
|
||||
|
||||
#define IOU_SLCR_SD_CDN_CTRL_SD1_CDN_CTRL_MASK 0X00010000U
|
||||
#define IOU_SLCR_SD_CDN_CTRL_SD0_CDN_CTRL_MASK 0X00000001U
|
||||
|
||||
|
||||
/* Register: ADMA_CH0 Base Address */
|
||||
#define ADMA_CH0_BASEADDR 0XFFA80000U
|
||||
|
||||
/* Register: ADMA_CH0_ZDMA_CH_STATUS */
|
||||
#define ADMA_CH0_ZDMA_CH_STATUS ( ( ADMA_CH0_BASEADDR ) + 0X0000011CU )
|
||||
#define ADMA_CH0_ZDMA_CH_STATUS_STATE_MASK 0X00000003U
|
||||
#define ADMA_CH0_ZDMA_CH_STATUS_STATE_DONE 0X00000000U
|
||||
#define ADMA_CH0_ZDMA_CH_STATUS_STATE_ERR 0X00000003U
|
||||
|
||||
/* Register: ADMA_CH0_ZDMA_CH_CTRL0 */
|
||||
#define ADMA_CH0_ZDMA_CH_CTRL0 ( ( ADMA_CH0_BASEADDR ) + 0X00000110U )
|
||||
#define ADMA_CH0_ZDMA_CH_CTRL0_POINT_TYPE_MASK (u32)0X00000040U
|
||||
#define ADMA_CH0_ZDMA_CH_CTRL0_POINT_TYPE_NORMAL (u32)0X00000000U
|
||||
#define ADMA_CH0_ZDMA_CH_CTRL0_MODE_MASK (u32)0X00000030U
|
||||
#define ADMA_CH0_ZDMA_CH_CTRL0_MODE_WR_ONLY (u32)0X00000010U
|
||||
#define ADMA_CH0_ZDMA_CH_CTRL0_TOTAL_BYTE_COUNT ( ( ADMA_CH0_BASEADDR ) + 0X00000188U )
|
||||
|
||||
/* Register: ADMA_CH0_ZDMA_CH_WR_ONLY_WORD0 */
|
||||
#define ADMA_CH0_ZDMA_CH_WR_ONLY_WORD0 ( ( ADMA_CH0_BASEADDR ) + 0X00000148U )
|
||||
|
||||
/* Register: ADMA_CH0_ZDMA_CH_WR_ONLY_WORD1 */
|
||||
#define ADMA_CH0_ZDMA_CH_WR_ONLY_WORD1 ( ( ADMA_CH0_BASEADDR ) + 0X0000014CU )
|
||||
|
||||
/* Register: ADMA_CH0_ZDMA_CH_WR_ONLY_WORD2 */
|
||||
#define ADMA_CH0_ZDMA_CH_WR_ONLY_WORD2 ( ( ADMA_CH0_BASEADDR ) + 0X00000150U )
|
||||
|
||||
/* Register: ADMA_CH0_ZDMA_CH_WR_ONLY_WORD3 */
|
||||
#define ADMA_CH0_ZDMA_CH_WR_ONLY_WORD3 ( ( ADMA_CH0_BASEADDR ) + 0X00000154U )
|
||||
|
||||
/* Register: ADMA_CH0_ZDMA_CH_DST_DSCR_WORD0 */
|
||||
#define ADMA_CH0_ZDMA_CH_DST_DSCR_WORD0 ( ( ADMA_CH0_BASEADDR ) + 0X00000138U )
|
||||
#define ADMA_CH0_ZDMA_CH_DST_DSCR_WORD0_LSB_MASK 0XFFFFFFFFU
|
||||
|
||||
/* Register: ADMA_CH0_ZDMA_CH_DST_DSCR_WORD1 */
|
||||
#define ADMA_CH0_ZDMA_CH_DST_DSCR_WORD1 ( ( ADMA_CH0_BASEADDR ) + 0X0000013CU )
|
||||
#define ADMA_CH0_ZDMA_CH_DST_DSCR_WORD1_MSB_MASK 0X0001FFFFU
|
||||
|
||||
/* Register: ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD2 */
|
||||
#define ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD2 ( ( ADMA_CH0_BASEADDR ) + 0X00000130U )
|
||||
|
||||
/* Register: ADMA_CH0_ZDMA_CH_DST_DSCR_WORD2 */
|
||||
#define ADMA_CH0_ZDMA_CH_DST_DSCR_WORD2 ( ( ADMA_CH0_BASEADDR ) + 0X00000140U )
|
||||
|
||||
/* Register: ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD1 */
|
||||
#define ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD1 ( ( ADMA_CH0_BASEADDR ) + 0X0000012CU )
|
||||
|
||||
/* Register: ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD0 */
|
||||
#define ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD0 ( ( ADMA_CH0_BASEADDR ) + 0X00000128U )
|
||||
|
||||
/* Register: ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD3 */
|
||||
#define ADMA_CH0_ZDMA_CH_SRC_DSCR_WORD3 ( ( ADMA_CH0_BASEADDR ) + 0X00000134U )
|
||||
|
||||
/* Register: ADMA_CH0_ZDMA_CH_DST_DSCR_WORD3 */
|
||||
#define ADMA_CH0_ZDMA_CH_DST_DSCR_WORD3 ( ( ADMA_CH0_BASEADDR ) + 0X00000144U )
|
||||
|
||||
/* Register: ADMA_CH0_ZDMA_CH_CTRL2 */
|
||||
#define ADMA_CH0_ZDMA_CH_CTRL2 ( ( ADMA_CH0_BASEADDR ) + 0X00000200U )
|
||||
#define ADMA_CH0_ZDMA_CH_CTRL2_EN_MASK 0X00000001U
|
||||
|
||||
/* Register: ADMA_CH0_ZDMA_CH_ISR */
|
||||
#define ADMA_CH0_ZDMA_CH_ISR ( ( ADMA_CH0_BASEADDR ) + 0X00000100U )
|
||||
#define ADMA_CH0_ZDMA_CH_ISR_DMA_DONE_MASK 0X00000400U
|
||||
|
||||
/* AMS_PS_SYSMON Base Address */
|
||||
#define AMS_PS_SYSMON_BASEADDR 0XFFA50800U
|
||||
#define XFSBL_PS_SYSMON_CONFIGREG1 0XFFA50904U
|
||||
#define XFSBL_PS_SYSMON_CONFIGREG3 0XFFA5090CU
|
||||
#define XFSBL_PS_SYSMON_CFGREG1_ALRM_DISBL_MASK 0X0F0EU
|
||||
#define XFSBL_PS_SYSMON_CFGREG3_ALRM_DISBL_MASK 0X3FU
|
||||
|
||||
|
||||
/* Register: AMS_PS_SYSMON_ANALOG_BUS */
|
||||
#define AMS_PS_SYSMON_ANALOG_BUS ( ( AMS_PS_SYSMON_BASEADDR ) + 0X00000114U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ISPENDR0 */
|
||||
#define ACPU_GIC_BASEADDR 0xF9000000U
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICENBLR0 */
|
||||
#define ACPU_GIC_GICD_ICENBLR0 ( ( ACPU_GIC_BASEADDR ) + 0X00010180U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICENBLR1 */
|
||||
#define ACPU_GIC_GICD_ICENBLR1 ( ( ACPU_GIC_BASEADDR ) + 0X00010184U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICENBLR2 */
|
||||
#define ACPU_GIC_GICD_ICENBLR2 ( ( ACPU_GIC_BASEADDR ) + 0X00010188U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICENBLR3 */
|
||||
#define ACPU_GIC_GICD_ICENBLR3 ( ( ACPU_GIC_BASEADDR ) + 0X0001018CU )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICENBLR4 */
|
||||
#define ACPU_GIC_GICD_ICENBLR4 ( ( ACPU_GIC_BASEADDR ) + 0X00010190U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICENBLR5 */
|
||||
#define ACPU_GIC_GICD_ICENBLR5 ( ( ACPU_GIC_BASEADDR ) + 0X00010194U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICPENDR0 */
|
||||
#define ACPU_GIC_GICD_ICPENDR0 ( ( ACPU_GIC_BASEADDR ) + 0X00010280U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICPENDR1 */
|
||||
#define ACPU_GIC_GICD_ICPENDR1 ( ( ACPU_GIC_BASEADDR ) + 0X00010284U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICPENDR2 */
|
||||
#define ACPU_GIC_GICD_ICPENDR2 ( ( ACPU_GIC_BASEADDR ) + 0X00010288U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICPENDR3 */
|
||||
#define ACPU_GIC_GICD_ICPENDR3 ( ( ACPU_GIC_BASEADDR ) + 0X0001028CU )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICPENDR4 */
|
||||
#define ACPU_GIC_GICD_ICPENDR4 ( ( ACPU_GIC_BASEADDR ) + 0X00010290U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICPENDR5 */
|
||||
#define ACPU_GIC_GICD_ICPENDR5 ( ( ACPU_GIC_BASEADDR ) + 0X00010294U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICACTIVER0 */
|
||||
#define ACPU_GIC_GICD_ICACTIVER0 ( ( ACPU_GIC_BASEADDR ) + 0X00010380U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICACTIVER1 */
|
||||
#define ACPU_GIC_GICD_ICACTIVER1 ( ( ACPU_GIC_BASEADDR ) + 0X00010384U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICACTIVER2 */
|
||||
#define ACPU_GIC_GICD_ICACTIVER2 ( ( ACPU_GIC_BASEADDR ) + 0X00010388U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICACTIVER3 */
|
||||
#define ACPU_GIC_GICD_ICACTIVER3 ( ( ACPU_GIC_BASEADDR ) + 0X0001038CU )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICACTIVER4 */
|
||||
#define ACPU_GIC_GICD_ICACTIVER4 ( ( ACPU_GIC_BASEADDR ) + 0X00010390U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_ICACTIVER5 */
|
||||
#define ACPU_GIC_GICD_ICACTIVER5 ( ( ACPU_GIC_BASEADDR ) + 0X00010394U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_CPENDSGIR0 */
|
||||
#define ACPU_GIC_GICD_CPENDSGIR0 ( ( ACPU_GIC_BASEADDR ) + 0X00010F10U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_CPENDSGIR1 */
|
||||
#define ACPU_GIC_GICD_CPENDSGIR1 ( ( ACPU_GIC_BASEADDR ) + 0X00010F14U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_CPENDSGIR2 */
|
||||
#define ACPU_GIC_GICD_CPENDSGIR2 ( ( ACPU_GIC_BASEADDR ) + 0X00010F18U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_CPENDSGIR3 */
|
||||
#define ACPU_GIC_GICD_CPENDSGIR3 ( ( ACPU_GIC_BASEADDR ) + 0X00010F1CU )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_INTR_ACK_REG */
|
||||
#define ACPU_GIC_GICD_INTR_ACK_REG ( ( ACPU_GIC_BASEADDR ) + 0X0002000CU )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_END_INTR_REG */
|
||||
#define ACPU_GIC_GICD_END_INTR_REG ( ( ACPU_GIC_BASEADDR ) + 0X00020010U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_CACTIVESGIR0 */
|
||||
#define ACPU_GIC_GICD_CACTIVESGIR0 ( ( ACPU_GIC_BASEADDR ) + 0X00010F10U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_CACTIVESGIR1 */
|
||||
#define ACPU_GIC_GICD_CACTIVESGIR1 ( ( ACPU_GIC_BASEADDR ) + 0X00010F14U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_CACTIVESGIR2 */
|
||||
#define ACPU_GIC_GICD_CACTIVESGIR2 ( ( ACPU_GIC_BASEADDR ) + 0X00010F18U )
|
||||
|
||||
/* Register: ACPU_GIC_GICD_CACTIVESGIR3 */
|
||||
#define ACPU_GIC_GICD_CACTIVESGIR3 ( ( ACPU_GIC_BASEADDR ) + 0X00010F1CU )
|
||||
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* For error reporting PMU_GLOBAL_PERS_GLOB_GEN_STORAGE4 is used
|
||||
*/
|
||||
#define XFSBL_ERROR_STATUS_REGISTER_OFFSET (PMU_GLOBAL_PERS_GLOB_GEN_STORAGE4)
|
||||
|
||||
|
||||
/* PMU RAM address for PMU FW */
|
||||
#define XFSBL_PMU_RAM_START_ADDRESS (0xFFDC0000U)
|
||||
#define XFSBL_PMU_RAM_END_ADDRESS (0xFFDDFFFFU)
|
||||
|
||||
/**
|
||||
* If address where bitstream need to be copied is not configured, below will
|
||||
* be the default address to indicate it is invalid address. In such cases,
|
||||
* XFSBL_DDR_TEMP_ADDRESS is used as load address.
|
||||
*/
|
||||
#define XFSBL_DUMMY_PL_ADDR (0xFFFFFFFFU)
|
||||
|
||||
/**
|
||||
* ARM Processor defines
|
||||
*/
|
||||
#define XFSBL_CLUSTER_ID_MASK (0x00000F00U)
|
||||
#define XFSBL_A53_PROCESSOR (0x00000000U)
|
||||
#define XFSBL_R5_PROCESSOR (0x00000100U)
|
||||
|
||||
|
||||
/**
|
||||
* Other FSBL defines
|
||||
* this can defined in xfsbl_main.h
|
||||
*/
|
||||
#define XFSBL_R5_0 (0x1U)
|
||||
#define XFSBL_R5_L (0x2U)
|
||||
|
||||
/**
|
||||
* To indicate usage of RPU cores to PMU, PMU_GLOBAL_GLOB_GEN_STORAGE4 is used
|
||||
*/
|
||||
#define XFSBL_R5_USAGE_STATUS_REG (PMU_GLOBAL_GLOB_GEN_STORAGE4)
|
||||
/* Bit 1 of rpu uasge status register is used for R50 status */
|
||||
#define XFSBL_R5_0_STATUS_MASK (1U << 1)
|
||||
/* Bit 2 of rpu usage status register is used for R51 status */
|
||||
#define XFSBL_R5_1_STATUS_MASK (1U << 2)
|
||||
|
||||
/**
|
||||
* TCM address for R5
|
||||
*/
|
||||
#define XFSBL_R5_TCM_START_ADDRESS (u32)(0x0U)
|
||||
#define XFSBL_R5_BTCM_START_ADDRESS (0x20000U)
|
||||
|
||||
#define XFSBL_R50_HIGH_ATCM_START_ADDRESS (0xFFE00000U)
|
||||
#define XFSBL_R50_HIGH_BTCM_START_ADDRESS (0xFFE20000U)
|
||||
#define XFSBL_R51_HIGH_ATCM_START_ADDRESS (0xFFE90000U)
|
||||
#define XFSBL_R51_HIGH_BTCM_START_ADDRESS (0xFFEB0000U)
|
||||
|
||||
#define XFSBL_R5_TCM_BANK_LENGTH (0x10000U)
|
||||
|
||||
/**
|
||||
* defines for the FSBL peripherals present
|
||||
*/
|
||||
|
||||
/**
|
||||
* Definition for WDT to be included
|
||||
*/
|
||||
#if (!defined(FSBL_WDT_EXCLUDE) && defined(XPAR_PSU_WDT_0_DEVICE_ID))
|
||||
#define XFSBL_WDT_PRESENT
|
||||
#define XFSBL_WDT_DEVICE_ID XPAR_PSU_WDT_0_DEVICE_ID
|
||||
#define XFSBL_WDT_MASK PMU_GLOBAL_ERROR_SRST_EN_1_LPD_SWDT_MASK
|
||||
#elif (!defined(FSBL_WDT_EXCLUDE) && defined(XPAR_PSU_WDT_1_DEVICE_ID))
|
||||
#define XFSBL_WDT_PRESENT
|
||||
#define XFSBL_WDT_DEVICE_ID XPAR_PSU_WDT_1_DEVICE_ID
|
||||
#define XFSBL_WDT_MASK PMU_GLOBAL_ERROR_SRST_EN_1_FPD_SWDT_MASK
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Definitions for SD to be included
|
||||
*/
|
||||
#if (!defined(FSBL_SD_EXCLUDE) && (XPAR_XSDPS_0_BASEADDR == 0xFF160000))
|
||||
#define XFSBL_SD_0
|
||||
#endif
|
||||
|
||||
#if (!defined(FSBL_SD_EXCLUDE) && (XPAR_XSDPS_0_BASEADDR == 0xFF170000) ||\
|
||||
(XPAR_XSDPS_1_BASEADDR == 0xFF170000))
|
||||
#define XFSBL_SD_1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Definition for QSPI to be included
|
||||
*/
|
||||
#if (!defined(FSBL_QSPI_EXCLUDE) && defined(XPAR_XQSPIPSU_0_DEVICE_ID))
|
||||
#define XFSBL_QSPI
|
||||
#define XFSBL_QSPI_BASEADDRESS XPAR_XQSPIPS_0_BASEADDR
|
||||
#define XFSBL_QSPI_BUSWIDTH_ONE 0U
|
||||
#define XFSBL_QSPI_BUSWIDTH_TWO 1U
|
||||
#define XFSBL_QSPI_BUSWIDTH_FOUR 2U
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Definition for NAND to be included
|
||||
*/
|
||||
#if (!defined(FSBL_NAND_EXCLUDE) && defined(XPAR_XNANDPSU_0_DEVICE_ID))
|
||||
#define XFSBL_NAND
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Definition for SECURE to be included
|
||||
*/
|
||||
#if !defined(FSBL_SECURE_EXCLUDE)
|
||||
#define XFSBL_SECURE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Definition for PL bitsream feature to be included
|
||||
*/
|
||||
#if !defined(FSBL_BS_EXCLUDE)
|
||||
#define XFSBL_BS
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Definition for early handoff feature to be included
|
||||
*/
|
||||
#if !defined(FSBL_EARLY_HANDOFF_EXCLUDE)
|
||||
#define XFSBL_EARLY_HANDOFF
|
||||
#endif
|
||||
|
||||
#if !defined(FSBL_PERF_EXCLUDE) && (!defined(ARMR5) || (defined(ARMR5) && defined(SLEEP_TIMER_BASEADDR)))
|
||||
#define XFSBL_PERF
|
||||
#endif
|
||||
|
||||
/* Definition for TCM ECC Enable for A53 to be included */
|
||||
#if !defined(FSBL_A53_TCM_ECC_EXCLUDE)
|
||||
#define XFSBL_A53_TCM_ECC
|
||||
#endif
|
||||
|
||||
/* Definition for PL clear include irrespective of boot image has bitstream or not */
|
||||
#if !defined(FSBL_PL_CLEAR_EXCLUDE)
|
||||
#define XFSBL_PL_CLEAR
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Definition for forcing encryption for each partition
|
||||
* when ENC_ONLY FUSE bit is blown
|
||||
*/
|
||||
#if !defined(FSBL_FORCE_ENC_EXCLUDE)
|
||||
#define XFSBL_FORCE_ENC
|
||||
#endif
|
||||
|
||||
#define XFSBL_QSPI_LINEAR_BASE_ADDRESS_START (0xC0000000U)
|
||||
#define XFSBL_QSPI_LINEAR_BASE_ADDRESS_END (0xDFFFFFFFU)
|
||||
|
||||
#if defined(XPAR_PSU_DDR_0_S_AXI_BASEADDR) \
|
||||
|| defined(XPAR_PSU_R5_DDR_0_S_AXI_BASEADDR)
|
||||
#define XFSBL_PS_DDR
|
||||
#endif
|
||||
|
||||
#define XFSBL_PS_DDR_START_ADDRESS (0x0U)
|
||||
#define XFSBL_PS_DDR_START_ADDRESS_R5 (0x100000U)
|
||||
|
||||
#if (!defined(FSBL_USB_EXCLUDE) && defined(XPAR_XUSBPSU_0_DEVICE_ID) && (XPAR_XUSBPSU_0_BASEADDR == 0xFE200000) && defined(XFSBL_PS_DDR))
|
||||
#define XFSBL_USB
|
||||
#endif
|
||||
|
||||
#if !defined(FSBL_PROT_BYPASS_EXCLUDE)
|
||||
#define XFSBL_PROT_BYPASS
|
||||
#endif
|
||||
|
||||
#ifdef ARMR5
|
||||
#define XFSBL_PS_DDR_INIT_START_ADDRESS XFSBL_PS_DDR_START_ADDRESS_R5
|
||||
#if defined(XPAR_PSU_R5_DDR_1_S_AXI_BASEADDR)
|
||||
#define XFSBL_PS_HI_DDR_START_ADDRESS XPAR_PSU_R5_DDR_1_S_AXI_BASEADDR
|
||||
#define XFSBL_PS_HI_DDR_END_ADDRESS XPAR_PSU_R5_DDR_1_S_AXI_HIGHADDR
|
||||
#endif
|
||||
#else
|
||||
#define XFSBL_PS_DDR_INIT_START_ADDRESS XFSBL_PS_DDR_START_ADDRESS
|
||||
#if defined(XPAR_PSU_DDR_1_S_AXI_BASEADDR)
|
||||
#define XFSBL_PS_HI_DDR_START_ADDRESS XPAR_PSU_DDR_1_S_AXI_BASEADDR
|
||||
#define XFSBL_PS_HI_DDR_END_ADDRESS XPAR_PSU_DDR_1_S_AXI_HIGHADDR
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef XFSBL_PS_DDR
|
||||
#ifdef ARMR5
|
||||
#define XFSBL_PS_DDR_END_ADDRESS (XPAR_PSU_R5_DDR_0_S_AXI_HIGHADDR)
|
||||
#else
|
||||
#define XFSBL_PS_DDR_END_ADDRESS (XPAR_PSU_DDR_0_S_AXI_HIGHADDR)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef XFSBL_ENABLE_DDR_SR
|
||||
/*
|
||||
* For DDR status PMU_GLOBAL_PERS_GLOB_GEN_STORAGE7 is used
|
||||
*/
|
||||
#define XFSBL_DDR_STATUS_REGISTER_OFFSET (PMU_GLOBAL_PERS_GLOB_GEN_STORAGE7)
|
||||
/*
|
||||
* DDR controller initialization flag mask
|
||||
*
|
||||
* This flag signals whether DDR controller have been initialized or not. It is
|
||||
* used by FSBL to inform PMU that DDR controller is initialized. When booting
|
||||
* with DDR in self refresh mode, PMU must wait until DDR controller have been
|
||||
* initialized by the FSBL before it can bring the DDR out of self refresh mode.
|
||||
*/
|
||||
#define DDRC_INIT_FLAG_MASK (1U << 4)
|
||||
/*
|
||||
* DDR self refresh mode indication flag mask
|
||||
*
|
||||
* This flag indicates whether DDR is in self refresh mode or not. It is used
|
||||
* by PMU to signal FSBL in order to skip over DDR phy and ECC initialization
|
||||
* at boot time.
|
||||
*/
|
||||
#define DDR_STATUS_FLAG_MASK (1U << 3)
|
||||
#endif
|
||||
|
||||
/* The number of bytes transferred per cycle of DMA should be
|
||||
* 64 bit aligned to avoid any ECC errors. Hence, even though the maximum
|
||||
* number of bytes that can be sent per cycle is 1GB -1, only 1GB -8 bytes
|
||||
* are sent to preserve the 64 bit alignment.
|
||||
*/
|
||||
#define ZDMA_TRANSFER_MAX_LEN (0x3FFFFFFFU - 7U)
|
||||
|
||||
#define EFUSE_IPDISABLE_CG_MASK ((EFUSE_IPDISABLE_GPU_DIS_MASK) | \
|
||||
(EFUSE_IPDISABLE_APU2_DIS_MASK) | (EFUSE_IPDISABLE_APU3_DIS_MASK))
|
||||
|
||||
#define XFSBL_OCM
|
||||
#define XFSBL_OCM_START_ADDRESS (0xFFFEA000U)
|
||||
#define XFSBL_OCM_END_ADDRESS (0xFFFFFFFFU)
|
||||
|
||||
/* Different Memory types */
|
||||
#define XFSBL_R5_0_TCM (0x1U)
|
||||
#define XFSBL_R5_1_TCM (0x2U)
|
||||
#define XFSBL_R5_L_TCM (0x3U)
|
||||
|
||||
#define PTRSIZE UINTPTR
|
||||
|
||||
/* Reset Reason */
|
||||
#define XFSBL_SYSTEM_RESET 0U
|
||||
#define XFSBL_PS_ONLY_RESET 1U
|
||||
#define XFSBL_MASTER_ONLY_RESET 2U
|
||||
|
||||
/* AMS PS Sysmon ANALOG_BUS value */
|
||||
#define PS_SYSMON_ANALOG_BUS_VAL 0X00003210U
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CPU_H */
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 132 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 512 KiB |
+149
@@ -0,0 +1,149 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2014 - 2020 Xilinx, Inc. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
******************************************************************************/
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file xil-crt0.S
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- ---------------------------------------------------
|
||||
* 5.00 pkp 05/21/14 Initial version
|
||||
* 5.04 pkp 12/18/15 Initialized global constructor for C++ applications
|
||||
* 5.04 pkp 01/05/16 Set the reset vector register RVBAR equivalent to
|
||||
* vector table base address
|
||||
* 6.02 pkp 01/22/17 Added support for EL1 non-secure
|
||||
* 6.6 srm 10/18/17 Added timer configuration using XTime_StartTTCTimer API.
|
||||
* Now the TTC instance as specified by the user will be
|
||||
* started.
|
||||
* 6.6 mus 01/29/18 Initialized the xen PV console for Cortexa53 64 bit
|
||||
* EL1 NS BSP.
|
||||
* 7.2 sd 02/23/20 Clock Init is called
|
||||
* 7.2 sd 02/23/20 Clock code added under XCLOCKING flag
|
||||
* </pre>
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
******************************************************************************/
|
||||
#include "xparameters.h"
|
||||
#include "bspconfig.h"
|
||||
.file "xil-crt0.S"
|
||||
.section ".got2","aw"
|
||||
.align 2
|
||||
.globl _vector_table
|
||||
|
||||
#define FREERTOS_SMP
|
||||
|
||||
#ifdef FREERTOS_SMP
|
||||
.set secondary_cpu_reset_vector, _vector_table
|
||||
#endif
|
||||
|
||||
.text
|
||||
.Lsbss_start:
|
||||
.quad __sbss_start
|
||||
|
||||
.Lsbss_end:
|
||||
.quad __sbss_end
|
||||
|
||||
.Lbss_start:
|
||||
.quad __bss_start__
|
||||
|
||||
.Lbss_end:
|
||||
.quad __bss_end__
|
||||
|
||||
.extern StartAndWaitSecondaryCpuUp
|
||||
|
||||
.set APU_PWRCTL, 0xFD5C0090
|
||||
|
||||
.globl _startup
|
||||
_startup:
|
||||
|
||||
#ifdef FREERTOS_SMP
|
||||
/* Get CPU Id */
|
||||
mrs x0, MPIDR_EL1
|
||||
and x0, x0, #0xFF
|
||||
cmp x0, #0
|
||||
bne c_init_end
|
||||
#endif
|
||||
|
||||
mov x0, #0
|
||||
.if (EL3 == 1)
|
||||
/* Check whether the clearing of bss sections shall be skipped */
|
||||
ldr x10, =APU_PWRCTL /* Load PWRCTRL address */
|
||||
ldr w11, [x10] /* Read PWRCTRL register */
|
||||
mrs x2, MPIDR_EL1 /* Read MPIDR_EL1 */
|
||||
ubfx x2, x2, #0, #8 /* Extract CPU ID (affinity level 0) */
|
||||
mov w1, #1
|
||||
lsl w2, w1, w2 /* Shift CPU ID to get one-hot ID */
|
||||
ands w11, w11, w2 /* Get PWRCTRL bit for this core */
|
||||
bne .Lenclbss /* Skip BSS and SBSS clearing */
|
||||
.endif
|
||||
/* clear sbss */
|
||||
ldr x1,.Lsbss_start /* calculate beginning of the SBSS */
|
||||
ldr x2,.Lsbss_end /* calculate end of the SBSS */
|
||||
|
||||
.Lloop_sbss:
|
||||
cmp x1,x2
|
||||
bge .Lenclsbss /* If no SBSS, no clearing required */
|
||||
str x0, [x1], #8
|
||||
b .Lloop_sbss
|
||||
|
||||
.Lenclsbss:
|
||||
/* clear bss */
|
||||
ldr x1,.Lbss_start /* calculate beginning of the BSS */
|
||||
ldr x2,.Lbss_end /* calculate end of the BSS */
|
||||
|
||||
.Lloop_bss:
|
||||
cmp x1,x2
|
||||
bge .Lenclbss /* If no BSS, no clearing required */
|
||||
str x0, [x1], #8
|
||||
b .Lloop_bss
|
||||
|
||||
.Lenclbss:
|
||||
/* run global constructors */
|
||||
bl __libc_init_array
|
||||
|
||||
c_init_end:
|
||||
/* Reset and start Triple Timer Counter */
|
||||
#if defined (SLEEP_TIMER_BASEADDR)
|
||||
bl XTime_StartTTCTimer
|
||||
#endif
|
||||
|
||||
.if (EL1_NONSECURE == 1 && HYP_GUEST == 1 && \
|
||||
XEN_USE_PV_CONSOLE == 1)
|
||||
bl XPVXenConsole_Init
|
||||
.endif
|
||||
|
||||
#ifdef FREERTOS_SMP
|
||||
/* Get CPU Id */
|
||||
mrs x0, MPIDR_EL1
|
||||
and x0, x0, #0xFF
|
||||
ldr x1, =secondary_cpu_reset_vector
|
||||
/* void StartAndWaitSecondaryCpuUp(uint64_t CpuID, uint64_t ResetAddr) */
|
||||
bl StartAndWaitSecondaryCpuUp
|
||||
#endif
|
||||
/* make sure argc and argv are valid */
|
||||
mov x0, #0
|
||||
mov x1, #0
|
||||
|
||||
#ifdef XCLOCKING
|
||||
bl Xil_ClockInit
|
||||
#endif
|
||||
|
||||
bl main /* Jump to main C code */
|
||||
|
||||
/* Cleanup global constructors */
|
||||
bl __libc_fini_array
|
||||
|
||||
bl exit
|
||||
|
||||
.Lexit: /* should never get here */
|
||||
b .Lexit
|
||||
|
||||
.Lstart:
|
||||
.size _startup,.Lstart-_startup
|
||||
+1221
File diff suppressed because it is too large
Load Diff
FreeRTOS/portable/ThirdParty/Community-Supported-Ports/GCC/CORTEX_A53_64-bit_UltraScale_MPSoC/port.c
Vendored
+927
@@ -0,0 +1,927 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Copyright (C) 2014 - 2020 Xilinx, Inc. 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "xpseudo_asm.h"
|
||||
|
||||
/* Xilinx includes. */
|
||||
#include "xscugic.h"
|
||||
|
||||
|
||||
#ifndef configINTERRUPT_CONTROLLER_BASE_ADDRESS
|
||||
#error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#endif
|
||||
|
||||
#ifndef configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET
|
||||
#error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#endif
|
||||
|
||||
#ifndef configUNIQUE_INTERRUPT_PRIORITIES
|
||||
#error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#endif
|
||||
|
||||
#ifndef configSETUP_TICK_INTERRUPT
|
||||
#error configSETUP_TICK_INTERRUPT() must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#endif /* configSETUP_TICK_INTERRUPT */
|
||||
|
||||
#ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#endif
|
||||
|
||||
#if configMAX_API_CALL_INTERRUPT_PRIORITY == 0
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0
|
||||
#endif
|
||||
|
||||
#if configMAX_API_CALL_INTERRUPT_PRIORITY > configUNIQUE_INTERRUPT_PRIORITIES
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority
|
||||
#endif
|
||||
|
||||
#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 */
|
||||
|
||||
/* In case security extensions are implemented. */
|
||||
#if configMAX_API_CALL_INTERRUPT_PRIORITY <= ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
|
||||
#endif
|
||||
|
||||
/* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in
|
||||
portmacro.h. */
|
||||
#ifndef configCLEAR_TICK_INTERRUPT
|
||||
#define configCLEAR_TICK_INTERRUPT()
|
||||
#endif
|
||||
|
||||
/* A critical section is exited when the critical section nesting count reaches
|
||||
this value. */
|
||||
#define portNO_CRITICAL_NESTING ( ( size_t ) 0 )
|
||||
|
||||
/* In all GICs 255 can be written to the priority mask register to unmask all
|
||||
(but the lowest) interrupt priority. */
|
||||
#define portUNMASK_VALUE ( 0xFFUL )
|
||||
|
||||
/* 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_ELx ( ( StackType_t ) 0x01 )
|
||||
#define portSP_EL0 ( ( StackType_t ) 0x00 )
|
||||
|
||||
#if defined( GUEST )
|
||||
#define portEL1 ( ( StackType_t ) 0x04 )
|
||||
#define portINITIAL_PSTATE ( portEL1 | portSP_EL0 )
|
||||
#else
|
||||
#define portEL3 ( ( StackType_t ) 0x0c )
|
||||
/* At the time of writing, the BSP only supports EL3. */
|
||||
#define portINITIAL_PSTATE ( portEL3 | portSP_EL0 )
|
||||
#endif
|
||||
|
||||
/* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
|
||||
point is zero. */
|
||||
#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 )
|
||||
|
||||
/* Masks all bits in the APSR other than the mode bits. */
|
||||
#define portAPSR_MODE_BITS_MASK ( 0x0C )
|
||||
|
||||
/* The I bit in the DAIF bits. */
|
||||
#define portDAIF_I ( 0x80 )
|
||||
|
||||
#if defined (GICv2)
|
||||
/* Macro to unmask all interrupt priorities. */
|
||||
#define portCLEAR_INTERRUPT_MASK_P() \
|
||||
{ \
|
||||
portDISABLE_INTERRUPTS(); \
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \
|
||||
__asm volatile ( "DSB SY \n" \
|
||||
"ISB SY \n" ); \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
}
|
||||
#else
|
||||
#define portCLEAR_INTERRUPT_MASK_P() \
|
||||
{ \
|
||||
portDISABLE_INTERRUPTS(); \
|
||||
mtcp(S3_0_C4_C6_0, portUNMASK_VALUE); \
|
||||
__asm volatile ( "DSB SY \n" \
|
||||
"ISB SY \n" ); \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Hardware specifics used when sanity checking the configuration. */
|
||||
#define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL
|
||||
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||
#define portBIT_0_SET ( ( uint8_t ) 0x01 )
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Starts the first task executing. This function is necessarily written in
|
||||
* assembly code so is implemented in portASM.s.
|
||||
*/
|
||||
extern void vPortRestoreTaskContext( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* A variable is used to keep track of the critical section nesting. This
|
||||
variable has to be stored as part of the task context and must be initialised to
|
||||
a non zero value to ensure interrupts don't inadvertently become unmasked before
|
||||
the scheduler starts. As it is stored as part of the task context it will
|
||||
automatically be set to 0 when the first task is started. */
|
||||
volatile uint64_t ullCriticalNesting = 9999ULL;
|
||||
|
||||
/*
|
||||
* The instance of the interrupt controller used by this port. This is required
|
||||
* by the Xilinx library API functions.
|
||||
*/
|
||||
extern XScuGic xInterruptController;
|
||||
|
||||
/* Saved as part of the task context. If ullPortTaskHasFPUContext is non-zero
|
||||
then floating point context must be saved and restored for the task. */
|
||||
uint64_t ullPortTaskHasFPUContext = pdFALSE;
|
||||
|
||||
/* Set to 1 to pend a context switch from an ISR. */
|
||||
uint64_t ullPortYieldRequired[configNUMBER_OF_CORES] = { pdFALSE };
|
||||
|
||||
/* Counts the interrupt nesting depth. A context switch is only performed if
|
||||
if the nesting depth is 0. */
|
||||
uint64_t ullPortInterruptNesting[configNUMBER_OF_CORES] = { 0 };
|
||||
|
||||
/* Used for check IN ISR */
|
||||
volatile uint64_t uxCoreInIsr[configNUMBER_OF_CORES] = {0};
|
||||
|
||||
/*
|
||||
* Global counter used for calculation of run time statistics of tasks.
|
||||
* Defined only when the relevant option is turned on
|
||||
*/
|
||||
#if (configGENERATE_RUN_TIME_STATS==1)
|
||||
volatile uint32_t ulHighFrequencyTimerTicks;
|
||||
#endif
|
||||
|
||||
/* The space on the stack required to hold the FPU registers. This is 32 128-bit
|
||||
* registers */
|
||||
#define portFPU_REGISTER_WORDS ( 2 * 32 )
|
||||
|
||||
#if defined(GICv2)
|
||||
/* Used in the ASM code. */
|
||||
__attribute__(( used )) const uint64_t ullICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS;
|
||||
__attribute__(( used )) const uint64_t ullICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS;
|
||||
__attribute__(( used )) const uint64_t ullICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS;
|
||||
#endif
|
||||
__attribute__(( used )) const uint64_t ullMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
* Initialise the interrupt controller instance.
|
||||
*/
|
||||
static int32_t prvInitialiseInterruptController( void );
|
||||
|
||||
/* Ensure the interrupt controller instance variable is initialised before it is
|
||||
* used, and that the initialisation only happens once.
|
||||
*/
|
||||
static int32_t prvEnsureInterruptControllerIsInitialised( void );
|
||||
|
||||
int32_t lInterruptControllerInitialised[configNUMBER_OF_CORES] = {0};
|
||||
|
||||
/*
|
||||
* 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. */
|
||||
|
||||
#if( configUSE_TASK_FPU_SUPPORT == 1 )
|
||||
{
|
||||
/* 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. */
|
||||
/* The task will start with a critical nesting count of 0 as interrupts are
|
||||
enabled. */
|
||||
pxTopOfStack--
|
||||
*pxTopOfStack = portNO_CRITICAL_NESTING;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
|
||||
}
|
||||
#elif( configUSE_TASK_FPU_SUPPORT == 2 )
|
||||
{
|
||||
/* The task will start with a floating point context. Leave enough
|
||||
* space for the registers - and ensure they are initialised to 0. */
|
||||
pxTopOfStack -= portFPU_REGISTER_WORDS;
|
||||
BaseType_t i = 0;
|
||||
for (i = 0; i < portFPU_REGISTER_WORDS; ++i)
|
||||
{
|
||||
pxTopOfStack[i] = 0ULL;
|
||||
}
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portNO_CRITICAL_NESTING;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = pdTRUE;
|
||||
ullPortTaskHasFPUContext = pdTRUE;
|
||||
}
|
||||
#else
|
||||
{
|
||||
#error Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 1, 2, or left undefined.
|
||||
}
|
||||
#endif
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef )
|
||||
{
|
||||
int32_t lReturn;
|
||||
|
||||
/* An API function is provided to install an interrupt handler */
|
||||
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
lReturn = XScuGic_Connect( &xInterruptController, ucInterruptID, pxHandler, pvCallBackRef );
|
||||
}
|
||||
if( lReturn == XST_SUCCESS )
|
||||
{
|
||||
lReturn = pdPASS;
|
||||
}
|
||||
configASSERT( lReturn == pdPASS );
|
||||
|
||||
return lReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static int32_t prvEnsureInterruptControllerIsInitialised( void )
|
||||
{
|
||||
int32_t lReturn;
|
||||
|
||||
/* Ensure the interrupt controller instance variable is initialised before
|
||||
it is used, and that the initialisation only happens once. */
|
||||
uint32_t ulCoreID = portGET_CORE_ID();
|
||||
if( lInterruptControllerInitialised[ulCoreID] != pdTRUE )
|
||||
{
|
||||
lReturn = prvInitialiseInterruptController();
|
||||
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
lInterruptControllerInitialised[ulCoreID] = pdTRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lReturn = pdPASS;
|
||||
}
|
||||
|
||||
return lReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
uint32_t TSCIsrCnt[4] = {0, 0, 0, 0};
|
||||
void vTaskSwitchContextISR(void* arg)
|
||||
{
|
||||
portEND_SWITCHING_ISR(pdTRUE);
|
||||
TSCIsrCnt[portGET_CORE_ID()]++;
|
||||
}
|
||||
|
||||
uint32_t IntCoreCnt[4] = {0, 0, 0, 0};
|
||||
|
||||
void vInterruptCore(uint32_t ulInterruptID, uint32_t ulCoreID)
|
||||
{
|
||||
configASSERT(ulCoreID < configNUMBER_OF_CORES);
|
||||
configASSERT(ulInterruptID < 16);
|
||||
uint32_t ulRegVal = 0;
|
||||
uint32_t ulCoreMask = (1 << ulCoreID);
|
||||
ulRegVal |= ulInterruptID & 0xFu;
|
||||
ulRegVal |= (ulCoreMask << 16U);
|
||||
*((volatile uint32_t*)portICD_SGIR_ADDRESS) = ulRegVal;
|
||||
IntCoreCnt[ulCoreID] ++;
|
||||
}
|
||||
|
||||
static int32_t prvInitialiseInterruptController( void )
|
||||
{
|
||||
BaseType_t xulStatus;
|
||||
XScuGic_Config *pxGICConfig;
|
||||
|
||||
BaseType_t xCoreID = portGET_CORE_ID();
|
||||
if (xCoreID == 0)
|
||||
{
|
||||
pxGICConfig = XScuGic_LookupConfig( configINTERRUPT_CONTROLLER_DEVICE_ID );
|
||||
xulStatus = XScuGic_CfgInitialize( &xInterruptController, pxGICConfig, pxGICConfig->CpuBaseAddress );
|
||||
/* Connect the interrupt controller interrupt handler to the hardware
|
||||
interrupt handling logic in the ARM processor. */
|
||||
Xil_ExceptionRegisterHandler( XIL_EXCEPTION_ID_IRQ_INT,
|
||||
( Xil_ExceptionHandler ) XScuGic_InterruptHandler,
|
||||
&xInterruptController);
|
||||
XScuGic_SetPPI_SGI_Priority(&xInterruptController, portYIELD_CORE_INT_ID, portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT);
|
||||
XScuGic_Connect(&xInterruptController, portYIELD_CORE_INT_ID, vTaskSwitchContextISR, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Secondary COREs only handle the portYIELD_CORE interrrupt, any other interrupts should be handled by CORE 0
|
||||
extern s32 XScuGic_CpuIfInitialize(XScuGic *InstancePtr);
|
||||
xulStatus = XScuGic_CpuIfInitialize(&xInterruptController);
|
||||
XScuGic_SetPPI_SGI_Priority(&xInterruptController, portYIELD_CORE_INT_ID, portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT);
|
||||
XScuGic_Connect(&xInterruptController, portYIELD_CORE_INT_ID, vTaskSwitchContextISR, NULL);
|
||||
}
|
||||
|
||||
/* For FreeRTOS SMP port, Exception will be enable at the end of vPortRestoreTaskContext */
|
||||
// Xil_ExceptionEnable();
|
||||
|
||||
if( xulStatus == XST_SUCCESS )
|
||||
{
|
||||
xulStatus = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
xulStatus = pdFAIL;
|
||||
}
|
||||
configASSERT( xulStatus == pdPASS );
|
||||
|
||||
return xulStatus;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnableInterrupt( uint8_t ucInterruptID )
|
||||
{
|
||||
int32_t lReturn;
|
||||
|
||||
/* An API function is provided to enable an interrupt in the interrupt
|
||||
controller. */
|
||||
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
XScuGic_Enable( &xInterruptController, ucInterruptID );
|
||||
}
|
||||
configASSERT( lReturn );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortDisableInterrupt( uint8_t ucInterruptID )
|
||||
{
|
||||
int32_t lReturn;
|
||||
|
||||
/* An API function is provided to disable an interrupt in the interrupt
|
||||
controller. */
|
||||
lReturn = prvEnsureInterruptControllerIsInitialised();
|
||||
if( lReturn == pdPASS )
|
||||
{
|
||||
XScuGic_Disable( &xInterruptController, ucInterruptID );
|
||||
}
|
||||
configASSERT( lReturn );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* flag to control tick ISR handling, this is made true just before schedular start */
|
||||
|
||||
volatile uint64_t uxPortSchedularRunning = pdFALSE;
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
uint32_t ulAPSR;
|
||||
#if defined(GICv3)
|
||||
uint32_t ulBpr;
|
||||
#endif
|
||||
|
||||
prvEnsureInterruptControllerIsInitialised();
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
if (portGET_CORE_ID() == 0)
|
||||
{
|
||||
volatile uint32_t ulOriginalPriority;
|
||||
#if defined(GICv2)
|
||||
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );
|
||||
#else
|
||||
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + 0x420 );
|
||||
#endif
|
||||
volatile uint8_t ucMaxPriorityValue;
|
||||
|
||||
/* Determine how many priority bits are implemented in the GIC.
|
||||
|
||||
Save the interrupt priority value that is about to be clobbered. */
|
||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Determine the number of priority bits available. First write to
|
||||
all possible bits. */
|
||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||
|
||||
/* Read the value back to see how many bits stuck. */
|
||||
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Shift to the least significant bits. */
|
||||
while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
|
||||
{
|
||||
ucMaxPriorityValue >>= ( uint8_t ) 0x01;
|
||||
}
|
||||
|
||||
/* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
|
||||
value. */
|
||||
|
||||
configASSERT( ucMaxPriorityValue >= portLOWEST_INTERRUPT_PRIORITY );
|
||||
|
||||
|
||||
/* Restore the clobbered interrupt priority register to its original
|
||||
value. */
|
||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||
}
|
||||
}
|
||||
#endif /* conifgASSERT_DEFINED */
|
||||
|
||||
/* At the time of writing, the BSP only supports EL3. */
|
||||
__asm volatile ( "MRS %0, CurrentEL" : "=r" ( ulAPSR ) );
|
||||
ulAPSR &= portAPSR_MODE_BITS_MASK;
|
||||
|
||||
#if defined( GUEST )
|
||||
#warning Building for execution as a guest under XEN. THIS IS NOT A FULLY TESTED PATH.
|
||||
configASSERT( ulAPSR == portEL1 );
|
||||
if( ulAPSR == portEL1 )
|
||||
#else
|
||||
configASSERT( ulAPSR == portEL3 );
|
||||
if( ulAPSR == portEL3 )
|
||||
#endif
|
||||
{
|
||||
/* Only continue if the binary point value is set to its lowest possible
|
||||
setting. See the comments in vPortValidateInterruptPriority() below for
|
||||
more information. */
|
||||
#if defined(GICv2)
|
||||
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
|
||||
|
||||
if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
|
||||
#else
|
||||
ulBpr = mfcp(S3_0_C12_C8_3);
|
||||
configASSERT( ( ulBpr & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
|
||||
|
||||
if( ( ulBpr & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
|
||||
#endif
|
||||
{
|
||||
/* 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 (portGET_CORE_ID() == 0)
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. */
|
||||
configSETUP_TICK_INTERRUPT();
|
||||
uxPortSchedularRunning = 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 FreeRTOS_Tick_Handler( void )
|
||||
{
|
||||
#if defined(GICv3)
|
||||
unsigned int ulRpr;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The Xilinx implementation of generating run time task stats uses the same timer used for generating
|
||||
* FreeRTOS ticks. In case user decides to generate run time stats the tick handler is called more
|
||||
* frequently (10 times faster). The timer/tick handler uses logic to handle the same. It handles
|
||||
* the FreeRTOS tick once per 10 interrupts.
|
||||
* For handling generation of run time stats, it increments a pre-defined counter every time the
|
||||
* interrupt handler executes.
|
||||
*/
|
||||
#if (configGENERATE_RUN_TIME_STATS == 1)
|
||||
ulHighFrequencyTimerTicks++;
|
||||
if (!(ulHighFrequencyTimerTicks % 10))
|
||||
#endif
|
||||
{
|
||||
|
||||
/* Must be the lowest possible priority. */
|
||||
#if !defined( QEMU )
|
||||
{
|
||||
#if defined(GICv2)
|
||||
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER == ( uint32_t ) ( portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
|
||||
#else
|
||||
ulRpr = mfcp(S3_0_C12_C11_3);
|
||||
configASSERT( ulRpr == ( uint32_t ) ( portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Interrupts should not be enabled before this point. */
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
uint32_t ulMaskBits;
|
||||
|
||||
__asm volatile( "mrs %0, daif" : "=r"( ulMaskBits ) :: "memory" );
|
||||
configASSERT( ( ulMaskBits & portDAIF_I ) != 0 );
|
||||
}
|
||||
#endif /* configASSERT_DEFINED */
|
||||
/* Set interrupt mask before altering scheduler structures. The tick
|
||||
handler runs at the lowest priority, so interrupts cannot already be masked,
|
||||
so there is no need to save and restore the current mask value. It is
|
||||
necessary to turn off interrupts in the CPU itself while the ICCPMR is being
|
||||
updated. */
|
||||
#if defined(GICv2)
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
#else
|
||||
mtcp(S3_0_C4_C6_0, ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ));
|
||||
#endif
|
||||
__asm volatile ( "dsb sy \n"
|
||||
"isb sy \n" ::: "memory" );
|
||||
|
||||
/* Ok to enable interrupts after the interrupt source has been cleared. */
|
||||
configCLEAR_TICK_INTERRUPT();
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
UBaseType_t x = portENTER_CRITICAL_FROM_ISR();
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
ullPortYieldRequired[portGET_CORE_ID()] = pdTRUE;
|
||||
}
|
||||
portEXIT_CRITICAL_FROM_ISR(x);
|
||||
}
|
||||
|
||||
/* Ensure all interrupt priorities are active again. */
|
||||
portCLEAR_INTERRUPT_MASK_P();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
#if( configUSE_TASK_FPU_SUPPORT != 2 )
|
||||
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 = pdTRUE;
|
||||
|
||||
/* Consider initialising the FPSR here - but probably not necessary in
|
||||
AArch64. */
|
||||
}
|
||||
#endif /* configUSE_TASK_FPU_SUPPORT */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortClearInterruptMask( UBaseType_t uxNewMaskValue )
|
||||
{
|
||||
if( uxNewMaskValue == pdFALSE )
|
||||
{
|
||||
portCLEAR_INTERRUPT_MASK_P();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
UBaseType_t uxPortSetInterruptMask( void )
|
||||
{
|
||||
uint32_t ulReturn;
|
||||
uint32_t mask;
|
||||
|
||||
if (lInterruptControllerInitialised[portGET_CORE_ID()] == pdTRUE) {
|
||||
/* Interrupt in the CPU must be turned off while the ICCPMR is being
|
||||
updated. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
#if defined(GICv2)
|
||||
mask = portICCPMR_PRIORITY_MASK_REGISTER;
|
||||
#else
|
||||
mask = mfcp(S3_0_C4_C6_0);
|
||||
#endif
|
||||
if( mask == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
|
||||
{
|
||||
/* Interrupts were already masked. */
|
||||
ulReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulReturn = pdFALSE;
|
||||
#if defined(GICv2)
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
#else
|
||||
mtcp(S3_0_C4_C6_0, ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ));
|
||||
#endif
|
||||
__asm volatile ( "dsb sy \n"
|
||||
"isb sy \n" ::: "memory" );
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
} else {
|
||||
ulReturn = pdTRUE;
|
||||
}
|
||||
return ulReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
#if defined(GICv3)
|
||||
unsigned int ulRpr;
|
||||
unsigned int ulBpr;
|
||||
#endif
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
an interrupt that has been assigned a priority above
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
function. ISR safe FreeRTOS API functions must *only* be called
|
||||
from interrupts that have been assigned a priority at or below
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
|
||||
Numerically low interrupt priority numbers represent logically high
|
||||
interrupt priorities, therefore the priority of the interrupt must
|
||||
be set to a value equal to or numerically *higher* than
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
|
||||
FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||
interrupt entry is as fast and simple as possible. */
|
||||
#if defined(GICv2)
|
||||
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
|
||||
#else
|
||||
ulRpr = mfcp(S3_0_C12_C11_3);
|
||||
configASSERT( ulRpr >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
|
||||
#endif
|
||||
/* Priority grouping: The interrupt controller (GIC) allows the bits
|
||||
that define each interrupt's priority to be split between bits that
|
||||
define the interrupt's pre-emption priority bits and bits that define
|
||||
the interrupt's sub-priority. For simplicity all bits must be defined
|
||||
to be pre-emption priority bits. The following assertion will fail if
|
||||
this is not the case (if some bits represent a sub-priority).
|
||||
|
||||
The priority grouping is configured by the GIC's binary point register
|
||||
(ICCBPR). Writing 0 to ICCBPR will ensure it is set to its lowest
|
||||
possible value (which may be above 0). */
|
||||
#if defined(GICv2)
|
||||
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
|
||||
#else
|
||||
ulBpr = mfcp(S3_0_C12_C8_3);
|
||||
configASSERT( ( ulBpr & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* configASSERT_DEFINED */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vIRQHandler( uint32_t ulICCIAR )
|
||||
{
|
||||
BaseType_t xCoreId = portGET_CORE_ID();
|
||||
uxCoreInIsr[xCoreId]++;
|
||||
|
||||
extern void vApplicationIRQHandler( uint32_t ulICCIAR );
|
||||
vApplicationIRQHandler(ulICCIAR);
|
||||
|
||||
uxCoreInIsr[xCoreId]--;
|
||||
}
|
||||
|
||||
#define portRTOS_LOCK_COUNT (2u)
|
||||
#define portMAX_CORE_COUNT configNUMBER_OF_CORES
|
||||
|
||||
/* 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 ulGateWord[ portRTOS_LOCK_COUNT ];
|
||||
|
||||
|
||||
static inline void vSpinUnlock(uint32_t* ulLock)
|
||||
{
|
||||
__asm volatile(
|
||||
"dmb sy\n"
|
||||
"mov w1, #0\n"
|
||||
"str w1, [%x0]\n"
|
||||
"dsb sy\n"
|
||||
"sev\n"
|
||||
:
|
||||
:"r" (ulLock)
|
||||
: "memory", "w1"
|
||||
);
|
||||
}
|
||||
|
||||
static inline int32_t lSpinTrylock(uint32_t* ulLock)
|
||||
{
|
||||
register int32_t lRet;
|
||||
|
||||
__asm volatile(
|
||||
"1:\n"
|
||||
"ldxr w1, [%x1]\n"
|
||||
"cmp w1, #1\n"
|
||||
"beq 2f\n"
|
||||
"mov w2, #1\n"
|
||||
"stxr w1, w2, [%x1]\n"
|
||||
"cmp w1, #0\n"
|
||||
"bne 1b\n"
|
||||
"2:\n"
|
||||
"mov %w0, w1\n"
|
||||
:"=r" (lRet)
|
||||
:"r" (ulLock)
|
||||
: "memory", "w1", "w2"
|
||||
);
|
||||
|
||||
return lRet;
|
||||
}
|
||||
|
||||
/* Read 64b value shared between cores */
|
||||
static inline uint64_t uxGet64(volatile uint64_t* x)
|
||||
{
|
||||
__asm("dsb sy");
|
||||
return *x;
|
||||
}
|
||||
|
||||
/* Write 64b value shared between cores */
|
||||
static inline void vSet64(volatile uint64_t* x, uint64_t value)
|
||||
{
|
||||
*x = value;
|
||||
__asm("dsb sy");
|
||||
}
|
||||
|
||||
void vPortRecursiveLock(BaseType_t xCoreID, uint32_t ulLockNum, BaseType_t uxAcquire)
|
||||
{
|
||||
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( lSpinTrylock(&ulGateWord[ulLockNum]) != 0)
|
||||
{
|
||||
/* Check if the core owns the spinlock */
|
||||
if( uxGet64(&ucOwnedByCore[xCoreID]) & ulLockBit )
|
||||
{
|
||||
configASSERT( uxGet64(&ucRecursionCountByLock[ulLockNum]) != 255u);
|
||||
vSet64(&ucRecursionCountByLock[ulLockNum], (uxGet64(&ucRecursionCountByLock[ulLockNum])+1));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Preload the gate word into the cache */
|
||||
uint32_t dummy = ulGateWord[ulLockNum];
|
||||
dummy++;
|
||||
|
||||
while (lSpinTrylock(&ulGateWord[ulLockNum]) != 0)
|
||||
__asm volatile ("wfe");
|
||||
}
|
||||
|
||||
/* 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(uxGet64(&ucRecursionCountByLock[ulLockNum]) == 0);
|
||||
|
||||
/* Set lock count as 1 */
|
||||
vSet64(&ucRecursionCountByLock[ulLockNum], 1);
|
||||
/* Set ucOwnedByCore */
|
||||
vSet64(&ucOwnedByCore[xCoreID], (uxGet64(&ucOwnedByCore[xCoreID]) | ulLockBit));
|
||||
}
|
||||
/* Lock release */
|
||||
else
|
||||
{
|
||||
/* Assert the lock is not free already */
|
||||
configASSERT( (uxGet64(&ucOwnedByCore[xCoreID]) & ulLockBit) != 0 );
|
||||
configASSERT( uxGet64(&ucRecursionCountByLock[ulLockNum]) != 0 );
|
||||
|
||||
/* Reduce ucRecursionCountByLock by 1 */
|
||||
vSet64(&ucRecursionCountByLock[ulLockNum], (uxGet64(&ucRecursionCountByLock[ulLockNum]) - 1) );
|
||||
|
||||
if( !uxGet64(&ucRecursionCountByLock[ulLockNum]) )
|
||||
{
|
||||
vSet64(&ucOwnedByCore[xCoreID], (uxGet64(&ucOwnedByCore[xCoreID]) & ~ulLockBit));
|
||||
vSpinUnlock(&ulGateWord[ulLockNum]);
|
||||
__asm volatile("sev");
|
||||
/* Add barrier to ensure lock is taken before we proceed */
|
||||
__asm__ __volatile__ ( "dmb sy" ::: "memory" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if( configGENERATE_RUN_TIME_STATS == 1 )
|
||||
/*
|
||||
* For Xilinx implementation this is a dummy function that does a redundant operation
|
||||
* of zeroing out the global counter.
|
||||
* It is called by FreeRTOS kernel.
|
||||
*/
|
||||
void xCONFIGURE_TIMER_FOR_RUN_TIME_STATS (void)
|
||||
{
|
||||
ulHighFrequencyTimerTicks = 0;
|
||||
}
|
||||
/*
|
||||
* For Xilinx implementation this function returns the global counter used for
|
||||
* run time task stats calculation.
|
||||
* It is called by FreeRTOS kernel task handling logic.
|
||||
*/
|
||||
uint32_t xGET_RUN_TIME_COUNTER_VALUE (void)
|
||||
{
|
||||
return ulHighFrequencyTimerTicks;
|
||||
}
|
||||
#endif
|
||||
+533
@@ -0,0 +1,533 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Copyright (C) 2014 - 2020 Xilinx, Inc. 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
#if defined (versal) && !defined(ARMR5)
|
||||
#define GICv3
|
||||
#else
|
||||
#define GICv2
|
||||
#endif
|
||||
|
||||
.text
|
||||
|
||||
/* Variables AND functions. */
|
||||
.extern ullMaxAPIPriorityMask
|
||||
.extern pxCurrentTCBs
|
||||
.extern vTaskSwitchContext
|
||||
.extern vIRQHandler
|
||||
.extern ullPortInterruptNesting
|
||||
.extern ullPortTaskHasFPUContext
|
||||
.extern ullCriticalNesting
|
||||
.extern ullPortYieldRequired
|
||||
.extern ullICCEOIR
|
||||
.extern ullICCIAR
|
||||
.extern _freertos_vector_table
|
||||
|
||||
.global FreeRTOS_IRQ_Handler
|
||||
.global FreeRTOS_SWI_Handler
|
||||
.global vPortRestoreTaskContext
|
||||
|
||||
|
||||
.macro portSAVE_CONTEXT
|
||||
|
||||
/* Switch to use the EL0 stack pointer. */
|
||||
MSR SPSEL, #0
|
||||
|
||||
/* Save the entire context. */
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
STP X4, X5, [SP, #-0x10]!
|
||||
STP X6, X7, [SP, #-0x10]!
|
||||
STP X8, X9, [SP, #-0x10]!
|
||||
STP X10, X11, [SP, #-0x10]!
|
||||
STP X12, X13, [SP, #-0x10]!
|
||||
STP X14, X15, [SP, #-0x10]!
|
||||
STP X16, X17, [SP, #-0x10]!
|
||||
STP X18, X19, [SP, #-0x10]!
|
||||
STP X20, X21, [SP, #-0x10]!
|
||||
STP X22, X23, [SP, #-0x10]!
|
||||
STP X24, X25, [SP, #-0x10]!
|
||||
STP X26, X27, [SP, #-0x10]!
|
||||
STP X28, X29, [SP, #-0x10]!
|
||||
STP X30, XZR, [SP, #-0x10]!
|
||||
|
||||
/* Save the SPSR. */
|
||||
#if defined( GUEST )
|
||||
MRS X3, SPSR_EL1
|
||||
MRS X2, ELR_EL1
|
||||
#else
|
||||
MRS X3, SPSR_EL3
|
||||
/* Save the ELR. */
|
||||
MRS X2, ELR_EL3
|
||||
#endif
|
||||
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
|
||||
/* Save the FPU context indicator. */
|
||||
LDR X0, ullPortTaskHasFPUContextConst
|
||||
LDR X2, [X0]
|
||||
|
||||
/* Save the FPU context, if any (32 128-bit registers). */
|
||||
CMP X2, #0
|
||||
B.EQ 1f
|
||||
STP Q0, Q1, [SP,#-0x20]!
|
||||
STP Q2, Q3, [SP,#-0x20]!
|
||||
STP Q4, Q5, [SP,#-0x20]!
|
||||
STP Q6, Q7, [SP,#-0x20]!
|
||||
STP Q8, Q9, [SP,#-0x20]!
|
||||
STP Q10, Q11, [SP,#-0x20]!
|
||||
STP Q12, Q13, [SP,#-0x20]!
|
||||
STP Q14, Q15, [SP,#-0x20]!
|
||||
STP Q16, Q17, [SP,#-0x20]!
|
||||
STP Q18, Q19, [SP,#-0x20]!
|
||||
STP Q20, Q21, [SP,#-0x20]!
|
||||
STP Q22, Q23, [SP,#-0x20]!
|
||||
STP Q24, Q25, [SP,#-0x20]!
|
||||
STP Q26, Q27, [SP,#-0x20]!
|
||||
STP Q28, Q29, [SP,#-0x20]!
|
||||
STP Q30, Q31, [SP,#-0x20]!
|
||||
|
||||
1:
|
||||
/* Store the critical nesting count AND 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
|
||||
LSL X1, X1, #3 /* X1 = X1 * 8 */
|
||||
ADD X0, X0, X1
|
||||
|
||||
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
|
||||
LSL X1, X1, #3 /* X1 = X1 * 8 */
|
||||
ADD X0, X0, X1
|
||||
|
||||
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. */
|
||||
#if defined(GICv2)
|
||||
LDR X4, ullICCPMRConst /* X4 holds the address of the ICCPMR constant. */
|
||||
/* CMP X3, #0 */
|
||||
LDR X5, [X4] /* X5 holds the address of the ICCPMR register. */
|
||||
/* B.EQ 1f */ /* Jump to Label 1 Forward */
|
||||
/* LDR X6, ullMaxAPIPriorityMaskConst */
|
||||
/* LDR X1, [X6] */ /* X1 holds the mask value. */
|
||||
1:
|
||||
STR W1, [X5] /* Write the mask value to ICCPMR. */
|
||||
#else
|
||||
CMP X3, #0
|
||||
B.EQ 2f
|
||||
LDR X6, ullMaxAPIPriorityMaskConst
|
||||
LDR X1, [X6] /* X1 holds the mask value. */
|
||||
2:
|
||||
MSR S3_0_C4_C6_0, X1
|
||||
#endif
|
||||
DSB SY /* _RB_Barriers probably not required here. */
|
||||
ISB SY
|
||||
|
||||
/* Restore the FPU context indicator. */
|
||||
LDR X0, ullPortTaskHasFPUContextConst
|
||||
STR X2, [X0]
|
||||
|
||||
/* Restore the FPU context, if any. */
|
||||
CMP X2, #0
|
||||
B.EQ 1f
|
||||
LDP Q30, Q31, [SP], #0x20
|
||||
LDP Q28, Q29, [SP], #0x20
|
||||
LDP Q26, Q27, [SP], #0x20
|
||||
LDP Q24, Q25, [SP], #0x20
|
||||
LDP Q22, Q23, [SP], #0x20
|
||||
LDP Q20, Q21, [SP], #0x20
|
||||
LDP Q18, Q19, [SP], #0x20
|
||||
LDP Q16, Q17, [SP], #0x20
|
||||
LDP Q14, Q15, [SP], #0x20
|
||||
LDP Q12, Q13, [SP], #0x20
|
||||
LDP Q10, Q11, [SP], #0x20
|
||||
LDP Q8, Q9, [SP], #0x20
|
||||
LDP Q6, Q7, [SP], #0x20
|
||||
LDP Q4, Q5, [SP], #0x20
|
||||
LDP Q2, Q3, [SP], #0x20
|
||||
LDP Q0, Q1, [SP], #0x20
|
||||
1:
|
||||
LDP X2, X3, [SP], #0x10 /* SPSR AND ELR. */
|
||||
|
||||
#if defined( GUEST )
|
||||
/* Restore the SPSR. */
|
||||
MSR SPSR_EL1, X3
|
||||
/* Restore the ELR. */
|
||||
MSR ELR_EL1, X2
|
||||
#else
|
||||
/* Restore the SPSR. */
|
||||
MSR SPSR_EL3, X3 /*_RB_ Assumes started in EL3. */
|
||||
/* Restore the ELR. */
|
||||
MSR ELR_EL3, X2
|
||||
#endif
|
||||
|
||||
LDP X30, XZR, [SP], #0x10
|
||||
LDP X28, X29, [SP], #0x10
|
||||
LDP X26, X27, [SP], #0x10
|
||||
LDP X24, X25, [SP], #0x10
|
||||
LDP X22, X23, [SP], #0x10
|
||||
LDP X20, X21, [SP], #0x10
|
||||
LDP X18, X19, [SP], #0x10
|
||||
LDP X16, X17, [SP], #0x10
|
||||
LDP X14, X15, [SP], #0x10
|
||||
LDP X12, X13, [SP], #0x10
|
||||
LDP X10, X11, [SP], #0x10
|
||||
LDP X8, X9, [SP], #0x10
|
||||
LDP X6, X7, [SP], #0x10
|
||||
LDP X4, X5, [SP], #0x10
|
||||
LDP X2, X3, [SP], #0x10
|
||||
LDP X0, X1, [SP], #0x10
|
||||
|
||||
/* Switch to use the ELx stack pointer. _RB_ Might not be required. */
|
||||
MSR SPSEL, #1
|
||||
|
||||
ERET
|
||||
|
||||
.endm
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* vPortRestoreTaskContext is used to start the scheduler.
|
||||
*****************************************************************************/
|
||||
.align 8
|
||||
.type vPortRestoreTaskContext, %function
|
||||
vPortRestoreTaskContext:
|
||||
.set freertos_vector_base, _freertos_vector_table
|
||||
/* Install the FreeRTOS interrupt handlers. */
|
||||
LDR X1, =freertos_vector_base
|
||||
#if defined( GUEST )
|
||||
MSR VBAR_EL1, X1
|
||||
#else
|
||||
MSR VBAR_EL3, X1
|
||||
#endif
|
||||
/* Enable IRQ */
|
||||
MSR DAIFCLR, #2
|
||||
DSB SY
|
||||
ISB SY
|
||||
|
||||
/* Start the first task. */
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* FreeRTOS_SWI_Handler handler is used to perform a context switch.
|
||||
*****************************************************************************/
|
||||
.align 8
|
||||
.type FreeRTOS_SWI_Handler, %function
|
||||
FreeRTOS_SWI_Handler:
|
||||
/* Save the context of the current task AND select a new task to run. */
|
||||
portSAVE_CONTEXT
|
||||
|
||||
#if defined( GUEST )
|
||||
MRS X0, ESR_EL1
|
||||
#else
|
||||
MRS X0, ESR_EL3
|
||||
#endif
|
||||
LSR X1, X0, #26
|
||||
#if defined( GUEST )
|
||||
CMP X1, #0x15 /* 0x15 = SVC instruction. */
|
||||
#else
|
||||
CMP X1, #0x17 /* 0x17 = SMC instruction. */
|
||||
#endif
|
||||
B.NE FreeRTOS_Abort
|
||||
MRS x0, MPIDR_EL1 /* Get CoreID */
|
||||
AND x0, x0, #0xff
|
||||
BL vTaskSwitchContext
|
||||
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
FreeRTOS_Abort:
|
||||
/* Full ESR is in X0, exception class code is in X1. */
|
||||
B .
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* FreeRTOS_IRQ_Handler handles IRQ entry AND exit.
|
||||
*****************************************************************************/
|
||||
.align 8
|
||||
.type FreeRTOS_IRQ_Handler, %function
|
||||
FreeRTOS_IRQ_Handler:
|
||||
/* Save volatile registers. */
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
STP X4, X5, [SP, #-0x10]!
|
||||
STP X6, X7, [SP, #-0x10]!
|
||||
STP X8, X9, [SP, #-0x10]!
|
||||
STP X10, X11, [SP, #-0x10]!
|
||||
STP X12, X13, [SP, #-0x10]!
|
||||
STP X14, X15, [SP, #-0x10]!
|
||||
STP X16, X17, [SP, #-0x10]!
|
||||
STP X18, X19, [SP, #-0x10]!
|
||||
STP X29, X30, [SP, #-0x10]!
|
||||
|
||||
/* Save FPU registers */
|
||||
STP Q0, Q1, [SP,#-0x20]!
|
||||
STP Q2, Q3, [SP,#-0x20]!
|
||||
STP Q4, Q5, [SP,#-0x20]!
|
||||
STP Q6, Q7, [SP,#-0x20]!
|
||||
STP Q8, Q9, [SP,#-0x20]!
|
||||
STP Q10, Q11, [SP,#-0x20]!
|
||||
STP Q12, Q13, [SP,#-0x20]!
|
||||
STP Q14, Q15, [SP,#-0x20]!
|
||||
STP Q16, Q17, [SP,#-0x20]!
|
||||
STP Q18, Q19, [SP,#-0x20]!
|
||||
STP Q20, Q21, [SP,#-0x20]!
|
||||
STP Q22, Q23, [SP,#-0x20]!
|
||||
STP Q24, Q25, [SP,#-0x20]!
|
||||
STP Q26, Q27, [SP,#-0x20]!
|
||||
STP Q28, Q29, [SP,#-0x20]!
|
||||
STP Q30, Q31, [SP,#-0x20]!
|
||||
|
||||
/* Save the SPSR AND ELR. */
|
||||
#if defined( GUEST )
|
||||
MRS X3, SPSR_EL1
|
||||
MRS X2, ELR_EL1
|
||||
#else
|
||||
MRS X3, SPSR_EL3
|
||||
MRS X2, ELR_EL3
|
||||
#endif
|
||||
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
|
||||
LSL X1, X1, #3 /* X1 = X1 * 8 */
|
||||
ADD X5, X5, X1
|
||||
|
||||
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]!
|
||||
|
||||
/* Read value from the interrupt acknowledge register, which is stored in W0
|
||||
for future parameter AND interrupt clearing use. */
|
||||
#if defined(GICv2)
|
||||
LDR X2, ullICCIARConst
|
||||
LDR X3, [X2]
|
||||
LDR W0, [X3] /* ICCIAR in W0 as parameter. */
|
||||
#else
|
||||
|
||||
MRS X0, S3_0_C12_C8_0
|
||||
#endif
|
||||
|
||||
/* ICCIAR in W0 as parameter. */
|
||||
/* Maintain the ICCIAR value across the function call. */
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
|
||||
/* Call the C handler. */
|
||||
BL vIRQHandler
|
||||
/* Disable interrupts. */
|
||||
|
||||
#if defined(GICv2)
|
||||
MSR DAIFSET, #3
|
||||
#else
|
||||
MSR DAIFSET, #2
|
||||
#endif
|
||||
DSB SY
|
||||
ISB SY
|
||||
|
||||
/* Restore the ICCIAR value. */
|
||||
LDP X0, X1, [SP], #0x10
|
||||
|
||||
/* End IRQ processing by writing ICCIAR to the EOI register. */
|
||||
#if defined(GICv2)
|
||||
LDR X4, ullICCEOIRConst
|
||||
LDR X4, [X4]
|
||||
STR W0, [X4]
|
||||
#else
|
||||
MSR S3_0_C12_C8_1, X0
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
|
||||
/* Choose the corresponding index for core in ullPortYieldRequired */
|
||||
MRS X1, MPIDR_EL1
|
||||
AND X1, X1, #0xff
|
||||
LSL X1, X1, #3 /* X1 = X1 * 8 */
|
||||
ADD X0, X0, X1
|
||||
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. */
|
||||
#if defined( GUEST )
|
||||
MSR SPSR_EL1, X5
|
||||
MSR ELR_EL1, X4
|
||||
#else
|
||||
MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
|
||||
MSR ELR_EL3, X4
|
||||
#endif
|
||||
DSB SY
|
||||
ISB SY
|
||||
|
||||
/* Restore FPU registers */
|
||||
LDP Q30, Q31, [SP], #0x20
|
||||
LDP Q28, Q29, [SP], #0x20
|
||||
LDP Q26, Q27, [SP], #0x20
|
||||
LDP Q24, Q25, [SP], #0x20
|
||||
LDP Q22, Q23, [SP], #0x20
|
||||
LDP Q20, Q21, [SP], #0x20
|
||||
LDP Q18, Q19, [SP], #0x20
|
||||
LDP Q16, Q17, [SP], #0x20
|
||||
LDP Q14, Q15, [SP], #0x20
|
||||
LDP Q12, Q13, [SP], #0x20
|
||||
LDP Q10, Q11, [SP], #0x20
|
||||
LDP Q8, Q9, [SP], #0x20
|
||||
LDP Q6, Q7, [SP], #0x20
|
||||
LDP Q4, Q5, [SP], #0x20
|
||||
LDP Q2, Q3, [SP], #0x20
|
||||
LDP Q0, Q1, [SP], #0x20
|
||||
|
||||
LDP X29, X30, [SP], #0x10
|
||||
LDP X18, X19, [SP], #0x10
|
||||
LDP X16, X17, [SP], #0x10
|
||||
LDP X14, X15, [SP], #0x10
|
||||
LDP X12, X13, [SP], #0x10
|
||||
LDP X10, X11, [SP], #0x10
|
||||
LDP X8, X9, [SP], #0x10
|
||||
LDP X6, X7, [SP], #0x10
|
||||
LDP X4, X5, [SP], #0x10
|
||||
LDP X2, X3, [SP], #0x10
|
||||
LDP X0, X1, [SP], #0x10
|
||||
|
||||
/* 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. */
|
||||
#if defined( GUEST )
|
||||
MSR SPSR_EL1, X5
|
||||
MSR ELR_EL1, X4
|
||||
#else
|
||||
MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
|
||||
MSR ELR_EL3, X4
|
||||
#endif
|
||||
DSB SY
|
||||
ISB SY
|
||||
|
||||
LDP Q30, Q31, [SP], #0x20
|
||||
LDP Q28, Q29, [SP], #0x20
|
||||
LDP Q26, Q27, [SP], #0x20
|
||||
LDP Q24, Q25, [SP], #0x20
|
||||
LDP Q22, Q23, [SP], #0x20
|
||||
LDP Q20, Q21, [SP], #0x20
|
||||
LDP Q18, Q19, [SP], #0x20
|
||||
LDP Q16, Q17, [SP], #0x20
|
||||
LDP Q14, Q15, [SP], #0x20
|
||||
LDP Q12, Q13, [SP], #0x20
|
||||
LDP Q10, Q11, [SP], #0x20
|
||||
LDP Q8, Q9, [SP], #0x20
|
||||
LDP Q6, Q7, [SP], #0x20
|
||||
LDP Q4, Q5, [SP], #0x20
|
||||
LDP Q2, Q3, [SP], #0x20
|
||||
LDP Q0, Q1, [SP], #0x20
|
||||
|
||||
LDP X29, X30, [SP], #0x10
|
||||
LDP X18, X19, [SP], #0x10
|
||||
LDP X16, X17, [SP], #0x10
|
||||
LDP X14, X15, [SP], #0x10
|
||||
LDP X12, X13, [SP], #0x10
|
||||
LDP X10, X11, [SP], #0x10
|
||||
LDP X8, X9, [SP], #0x10
|
||||
LDP X6, X7, [SP], #0x10
|
||||
LDP X4, X5, [SP], #0x10
|
||||
LDP X2, X3, [SP], #0x10
|
||||
LDP X0, X1, [SP], #0x10
|
||||
|
||||
ERET
|
||||
|
||||
|
||||
pxCurrentTCBConst: .dword pxCurrentTCBs
|
||||
ullPortTaskHasFPUContextConst: .dword ullPortTaskHasFPUContext
|
||||
ullMaxAPIPriorityMaskConst: .dword ullMaxAPIPriorityMask
|
||||
vIRQHandlerConst: .dword vIRQHandler
|
||||
ullPortInterruptNestingConst: .dword ullPortInterruptNesting
|
||||
ullPortYieldRequiredConst: .dword ullPortYieldRequired
|
||||
|
||||
#if defined(GICv2)
|
||||
ullICCPMRConst: .dword ullICCPMR
|
||||
ullICCIARConst: .dword ullICCIAR
|
||||
ullICCEOIRConst: .dword ullICCEOIR
|
||||
#endif
|
||||
|
||||
.end
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Copyright (C) 2014 - 2020 Xilinx, Inc. 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Xilinx includes. */
|
||||
#include "xttcps.h"
|
||||
#include "xscugic.h"
|
||||
|
||||
void vApplicationAssert( const char *pcFileName, uint32_t ulLine )
|
||||
__attribute__((weak));
|
||||
|
||||
/* Timer used to generate the tick interrupt. */
|
||||
XTtcPs xTimerInstance;
|
||||
XScuGic xInterruptController;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void FreeRTOS_SetupTickInterrupt( void )
|
||||
{
|
||||
BaseType_t xStatus;
|
||||
XTtcPs_Config *pxTimerConfiguration;
|
||||
XInterval usInterval;
|
||||
uint8_t ucPrescale;
|
||||
const uint8_t ucLevelSensitive = 1;
|
||||
|
||||
pxTimerConfiguration = XTtcPs_LookupConfig( configTIMER_ID );
|
||||
|
||||
/* Initialise the device. */
|
||||
xStatus = XTtcPs_CfgInitialize( &xTimerInstance, pxTimerConfiguration, pxTimerConfiguration->BaseAddress );
|
||||
|
||||
if( xStatus != XST_SUCCESS )
|
||||
{
|
||||
/* Not sure how to do this before XTtcPs_CfgInitialize is called as
|
||||
*xRTOSTickTimerInstance is set within XTtcPs_CfgInitialize(). */
|
||||
XTtcPs_Stop( &xTimerInstance );
|
||||
xStatus = XTtcPs_CfgInitialize( &xTimerInstance, pxTimerConfiguration, pxTimerConfiguration->BaseAddress );
|
||||
configASSERT( xStatus == XST_SUCCESS );
|
||||
}
|
||||
|
||||
/* Set the options. */
|
||||
XTtcPs_SetOptions( &xTimerInstance, ( XTTCPS_OPTION_INTERVAL_MODE | XTTCPS_OPTION_WAVE_DISABLE ) );
|
||||
/*
|
||||
* The Xilinx implementation of generating run time task stats uses the same timer used for generating
|
||||
* FreeRTOS ticks. In case user decides to generate run time stats the timer time out interval is changed
|
||||
* as "configured tick rate * 10". The multiplying factor of 10 is hard coded for Xilinx FreeRTOS ports.
|
||||
*/
|
||||
#if (configGENERATE_RUN_TIME_STATS == 1)
|
||||
XTtcPs_CalcIntervalFromFreq( &xTimerInstance, configTICK_RATE_HZ*10, &usInterval, &ucPrescale );
|
||||
#else
|
||||
XTtcPs_CalcIntervalFromFreq( &xTimerInstance, configTICK_RATE_HZ, &( usInterval ), &( ucPrescale ) );
|
||||
#endif
|
||||
|
||||
/* Set the interval and prescale. */
|
||||
XTtcPs_SetInterval( &xTimerInstance, usInterval );
|
||||
XTtcPs_SetPrescaler( &xTimerInstance, ucPrescale );
|
||||
|
||||
xPortInstallInterruptHandler(configTIMER_INTERRUPT_ID,
|
||||
( Xil_InterruptHandler ) FreeRTOS_Tick_Handler,
|
||||
( void * ) &xTimerInstance);
|
||||
/* The priority must be the lowest possible. */
|
||||
XScuGic_SetPriorityTriggerType( &xInterruptController, configTIMER_INTERRUPT_ID, portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT, ucLevelSensitive );
|
||||
|
||||
vPortEnableInterrupt(configTIMER_INTERRUPT_ID);
|
||||
|
||||
/* Enable the interrupts in the timer. */
|
||||
XTtcPs_EnableInterrupts( &xTimerInstance, XTTCPS_IXR_INTERVAL_MASK );
|
||||
|
||||
/* Start the timer. */
|
||||
XTtcPs_Start( &xTimerInstance );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void FreeRTOS_ClearTickInterrupt( void )
|
||||
{
|
||||
|
||||
XTtcPs_ClearInterruptStatus( &xTimerInstance, XTtcPs_GetInterruptStatus( &xTimerInstance ) );
|
||||
__asm volatile( "DSB SY" );
|
||||
__asm volatile( "ISB SY" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vApplicationIRQHandler( uint32_t ulICCIAR )
|
||||
{
|
||||
extern const XScuGic_Config XScuGic_ConfigTable[];
|
||||
static const XScuGic_VectorTableEntry *pxVectorTable = XScuGic_ConfigTable[ XPAR_SCUGIC_SINGLE_DEVICE_ID ].HandlerTable;
|
||||
uint32_t ulInterruptID;
|
||||
const XScuGic_VectorTableEntry *pxVectorEntry;
|
||||
|
||||
/* Interrupts cannot be re-enabled until the source of the interrupt is
|
||||
cleared. The ID of the interrupt is obtained by bitwise ANDing the ICCIAR
|
||||
value with 0x3FF. */
|
||||
ulInterruptID = ulICCIAR & 0x3FFUL;
|
||||
|
||||
if( ulInterruptID < XSCUGIC_MAX_NUM_INTR_INPUTS )
|
||||
{
|
||||
/* Call the function installed in the array of installed handler
|
||||
functions. */
|
||||
pxVectorEntry = &( pxVectorTable[ ulInterruptID ] );
|
||||
configASSERT( pxVectorEntry );
|
||||
pxVectorEntry->Handler( pxVectorEntry->CallBackRef );
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* This version of vApplicationAssert() is declared as a weak symbol to allow it
|
||||
to be overridden by a version implemented within the application that is using
|
||||
this BSP. */
|
||||
void vApplicationAssert( const char *pcFileName, uint32_t ulLine )
|
||||
{
|
||||
volatile uint32_t ul = 0;
|
||||
volatile const char *pcLocalFileName = pcFileName; /* To prevent pcFileName being optimized away. */
|
||||
volatile uint32_t ulLocalLine = ulLine; /* To prevent ulLine being optimized away. */
|
||||
|
||||
/* Prevent compile warnings about the following two variables being set but
|
||||
not referenced. They are intended for viewing in the debugger. */
|
||||
( void ) pcLocalFileName;
|
||||
( void ) ulLocalLine;
|
||||
|
||||
xil_printf( "Assert failed in file %s, line %lu\r\n", pcLocalFileName, ulLocalLine );
|
||||
|
||||
/* If this function is entered then a call to configASSERT() failed in the
|
||||
FreeRTOS code because of a fatal error. The pcFileName and ulLine
|
||||
parameters hold the file name and line number in that file of the assert
|
||||
that failed. Additionally, if using the debugger, the function call stack
|
||||
can be viewed to find which line failed its configASSERT() test. Finally,
|
||||
the debugger can be used to set ul to a non-zero value, then step out of
|
||||
this function to find where the assert function was entered. */
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
while( ul == 0 )
|
||||
{
|
||||
__asm volatile( "NOP" );
|
||||
}
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if 0
|
||||
/* This default tick hook does nothing and is declared as a weak symbol to allow
|
||||
the application writer to override this default by providing their own
|
||||
implementation in the application code. */
|
||||
void vApplicationTickHook( void )
|
||||
{
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* This default idle hook does nothing and is declared as a weak symbol to allow
|
||||
the application writer to override this default by providing their own
|
||||
implementation in the application code. */
|
||||
void vApplicationIdleHook( void )
|
||||
{
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* This default malloc failed hook does nothing and is declared as a weak symbol
|
||||
to allow the application writer to override this default by providing their own
|
||||
implementation in the application code. */
|
||||
void vApplicationMallocFailedHook( void )
|
||||
{
|
||||
xil_printf( "vApplicationMallocFailedHook() called\n" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* This default stack overflow hook will stop the application for executing. It
|
||||
is declared as a weak symbol to allow the application writer to override this
|
||||
default by providing their own implementation in the application code. */
|
||||
void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName )
|
||||
{
|
||||
/* Attempt to prevent the handle and name of the task that overflowed its stack
|
||||
from being optimised away because they are not used. */
|
||||
volatile TaskHandle_t xOverflowingTaskHandle = xTask;
|
||||
volatile char *pcOverflowingTaskName = pcTaskName;
|
||||
|
||||
( void ) xOverflowingTaskHandle;
|
||||
( void ) pcOverflowingTaskName;
|
||||
|
||||
xil_printf( "HALT: Task %s overflowed its stack.", pcOverflowingTaskName );
|
||||
portDISABLE_INTERRUPTS();
|
||||
for( ;; );
|
||||
}
|
||||
#endif
|
||||
|
||||
+312
@@ -0,0 +1,312 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Copyright (C) 2014 - 2020 Xilinx, Inc. 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*
|
||||
******************************************************************************/
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* @file asm_vectors.s
|
||||
*
|
||||
* This file contains the initial vector table for the Cortex A53 processor
|
||||
* Currently NEON registers are not saved on stack if interrupt is taken.
|
||||
* It will be implemented.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ------- -------- ---------------------------------------------------
|
||||
* 5.00 pkp 5/21/14 Initial version
|
||||
* </pre>
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#if defined (versal) && !defined(ARMR5)
|
||||
#define GICv3
|
||||
#else
|
||||
#define GICv2
|
||||
#endif
|
||||
|
||||
|
||||
.org 0
|
||||
.text
|
||||
|
||||
.globl _boot
|
||||
.globl _vector_table
|
||||
.globl _freertos_vector_table
|
||||
|
||||
.globl FIQInterrupt
|
||||
.globl IRQInterrupt
|
||||
.globl SErrorInterrupt
|
||||
.globl SynchronousInterrupt
|
||||
|
||||
|
||||
.org 0
|
||||
|
||||
.section .vectors, "a"
|
||||
|
||||
_vector_table:
|
||||
|
||||
.set VBAR, _vector_table
|
||||
|
||||
.org VBAR
|
||||
b _boot
|
||||
|
||||
.org (VBAR + 0x80)
|
||||
b .
|
||||
|
||||
.org (VBAR + 0x100)
|
||||
b .
|
||||
|
||||
.org (VBAR + 0x180)
|
||||
b .
|
||||
|
||||
|
||||
.org (VBAR + 0x200)
|
||||
b .
|
||||
|
||||
.org (VBAR + 0x280)
|
||||
b .
|
||||
|
||||
.org (VBAR + 0x300)
|
||||
b .
|
||||
|
||||
.org (VBAR + 0x380)
|
||||
b .
|
||||
|
||||
|
||||
|
||||
.org (VBAR + 0x400)
|
||||
b .
|
||||
|
||||
.org (VBAR + 0x480)
|
||||
b .
|
||||
|
||||
.org (VBAR + 0x500)
|
||||
b .
|
||||
|
||||
.org (VBAR + 0x580)
|
||||
b .
|
||||
|
||||
.org (VBAR + 0x600)
|
||||
b .
|
||||
|
||||
.org (VBAR + 0x680)
|
||||
b .
|
||||
|
||||
.org (VBAR + 0x700)
|
||||
b .
|
||||
|
||||
.org (VBAR + 0x780)
|
||||
b .
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Vector table to use when FreeRTOS is running.
|
||||
*****************************************************************************/
|
||||
.set FREERTOS_VBAR, (VBAR+0x1000)
|
||||
|
||||
.org(FREERTOS_VBAR)
|
||||
_freertos_vector_table:
|
||||
b FreeRTOS_SWI_Handler
|
||||
|
||||
.org (FREERTOS_VBAR + 0x80)
|
||||
b FreeRTOS_IRQ_Handler
|
||||
|
||||
.org (FREERTOS_VBAR + 0x100)
|
||||
#if defined(GICv3)
|
||||
b FreeRTOS_IRQ_Handler
|
||||
#else
|
||||
b .
|
||||
#endif
|
||||
.org (FREERTOS_VBAR + 0x180)
|
||||
b .
|
||||
|
||||
.org (FREERTOS_VBAR + 0x200)
|
||||
b FreeRTOS_SWI_Handler
|
||||
|
||||
.org (FREERTOS_VBAR + 0x280)
|
||||
b FreeRTOS_IRQ_Handler
|
||||
|
||||
.org (FREERTOS_VBAR + 0x300)
|
||||
b FreeRTOS_IRQ_Handler
|
||||
|
||||
.org (FREERTOS_VBAR + 0x380)
|
||||
b .
|
||||
|
||||
.org (FREERTOS_VBAR + 0x400)
|
||||
b .
|
||||
|
||||
.org (FREERTOS_VBAR + 0x480)
|
||||
b .
|
||||
|
||||
.org (FREERTOS_VBAR + 0x500)
|
||||
b .
|
||||
|
||||
.org (FREERTOS_VBAR + 0x580)
|
||||
b .
|
||||
|
||||
.org (FREERTOS_VBAR + 0x600)
|
||||
b .
|
||||
|
||||
.org (FREERTOS_VBAR + 0x680)
|
||||
b .
|
||||
|
||||
.org (FREERTOS_VBAR + 0x700)
|
||||
b .
|
||||
|
||||
.org (FREERTOS_VBAR + 0x780)
|
||||
b .
|
||||
|
||||
.org (FREERTOS_VBAR + 0x800)
|
||||
|
||||
|
||||
|
||||
|
||||
SynchronousInterruptHandler:
|
||||
stp X0,X1, [sp,#-0x10]!
|
||||
stp X2,X3, [sp,#-0x10]!
|
||||
stp X4,X5, [sp,#-0x10]!
|
||||
stp X6,X7, [sp,#-0x10]!
|
||||
stp X8,X9, [sp,#-0x10]!
|
||||
stp X10,X11, [sp,#-0x10]!
|
||||
stp X12,X13, [sp,#-0x10]!
|
||||
stp X14,X15, [sp,#-0x10]!
|
||||
stp X16,X17, [sp,#-0x10]!
|
||||
stp X18,X19, [sp,#-0x10]!
|
||||
stp X29,X30, [sp,#-0x10]!
|
||||
|
||||
bl SynchronousInterrupt
|
||||
|
||||
ldp X29,X30, [sp], #0x10
|
||||
ldp X18,X19, [sp], #0x10
|
||||
ldp X16,X17, [sp], #0x10
|
||||
ldp X14,X15, [sp], #0x10
|
||||
ldp X12,X13, [sp], #0x10
|
||||
ldp X10,X11, [sp], #0x10
|
||||
ldp X8,X9, [sp], #0x10
|
||||
ldp X6,X7, [sp], #0x10
|
||||
ldp X4,X5, [sp], #0x10
|
||||
ldp X2,X3, [sp], #0x10
|
||||
ldp X0,X1, [sp], #0x10
|
||||
|
||||
eret
|
||||
|
||||
IRQInterruptHandler:
|
||||
stp X0,X1, [sp,#-0x10]!
|
||||
stp X2,X3, [sp,#-0x10]!
|
||||
stp X4,X5, [sp,#-0x10]!
|
||||
stp X6,X7, [sp,#-0x10]!
|
||||
stp X8,X9, [sp,#-0x10]!
|
||||
stp X10,X11, [sp,#-0x10]!
|
||||
stp X12,X13, [sp,#-0x10]!
|
||||
stp X14,X15, [sp,#-0x10]!
|
||||
stp X16,X17, [sp,#-0x10]!
|
||||
stp X18,X19, [sp,#-0x10]!
|
||||
stp X29,X30, [sp,#-0x10]!
|
||||
|
||||
bl IRQInterrupt
|
||||
|
||||
ldp X29,X30, [sp], #0x10
|
||||
ldp X18,X19, [sp], #0x10
|
||||
ldp X16,X17, [sp], #0x10
|
||||
ldp X14,X15, [sp], #0x10
|
||||
ldp X12,X13, [sp], #0x10
|
||||
ldp X10,X11, [sp], #0x10
|
||||
ldp X8,X9, [sp], #0x10
|
||||
ldp X6,X7, [sp], #0x10
|
||||
ldp X4,X5, [sp], #0x10
|
||||
ldp X2,X3, [sp], #0x10
|
||||
ldp X0,X1, [sp], #0x10
|
||||
|
||||
eret
|
||||
|
||||
FIQInterruptHandler:
|
||||
|
||||
stp X0,X1, [sp,#-0x10]!
|
||||
stp X2,X3, [sp,#-0x10]!
|
||||
stp X4,X5, [sp,#-0x10]!
|
||||
stp X6,X7, [sp,#-0x10]!
|
||||
stp X8,X9, [sp,#-0x10]!
|
||||
stp X10,X11, [sp,#-0x10]!
|
||||
stp X12,X13, [sp,#-0x10]!
|
||||
stp X14,X15, [sp,#-0x10]!
|
||||
stp X16,X17, [sp,#-0x10]!
|
||||
stp X18,X19, [sp,#-0x10]!
|
||||
stp X29,X30, [sp,#-0x10]!
|
||||
|
||||
bl FIQInterrupt
|
||||
|
||||
ldp X29,X30, [sp], #0x10
|
||||
ldp X18,X19, [sp], #0x10
|
||||
ldp X16,X17, [sp], #0x10
|
||||
ldp X14,X15, [sp], #0x10
|
||||
ldp X12,X13, [sp], #0x10
|
||||
ldp X10,X11, [sp], #0x10
|
||||
ldp X8,X9, [sp], #0x10
|
||||
ldp X6,X7, [sp], #0x10
|
||||
ldp X4,X5, [sp], #0x10
|
||||
ldp X2,X3, [sp], #0x10
|
||||
ldp X0,X1, [sp], #0x10
|
||||
|
||||
eret
|
||||
|
||||
SErrorInterruptHandler:
|
||||
|
||||
stp X0,X1, [sp,#-0x10]!
|
||||
stp X2,X3, [sp,#-0x10]!
|
||||
stp X4,X5, [sp,#-0x10]!
|
||||
stp X6,X7, [sp,#-0x10]!
|
||||
stp X8,X9, [sp,#-0x10]!
|
||||
stp X10,X11, [sp,#-0x10]!
|
||||
stp X12,X13, [sp,#-0x10]!
|
||||
stp X14,X15, [sp,#-0x10]!
|
||||
stp X16,X17, [sp,#-0x10]!
|
||||
stp X18,X19, [sp,#-0x10]!
|
||||
stp X29,X30, [sp,#-0x10]!
|
||||
|
||||
bl SErrorInterrupt
|
||||
|
||||
ldp X29,X30, [sp], #0x10
|
||||
ldp X18,X19, [sp], #0x10
|
||||
ldp X16,X17, [sp], #0x10
|
||||
ldp X14,X15, [sp], #0x10
|
||||
ldp X12,X13, [sp], #0x10
|
||||
ldp X10,X11, [sp], #0x10
|
||||
ldp X8,X9, [sp], #0x10
|
||||
ldp X6,X7, [sp], #0x10
|
||||
ldp X4,X5, [sp], #0x10
|
||||
ldp X2,X3, [sp], #0x10
|
||||
ldp X0,X1, [sp], #0x10
|
||||
|
||||
eret
|
||||
|
||||
.end
|
||||
+365
@@ -0,0 +1,365 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Copyright (C) 2014 - 2020 Xilinx, Inc. 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* BSP includes. */
|
||||
#include "xil_types.h"
|
||||
#include "xpseudo_asm.h"
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
#if defined (versal) && !defined(ARMR5)
|
||||
#define GICv3
|
||||
#else
|
||||
#define GICv2
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* 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 uint64_t TickType_t;
|
||||
|
||||
#define portMAX_DELAY ( ( TickType_t ) 0xffffffffffffffff )
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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 )
|
||||
#if defined( GUEST )
|
||||
#define portYIELD() __asm volatile ( "SVC 0" ::: "memory" )
|
||||
#else
|
||||
#define portYIELD() __asm volatile ( "SMC 0" ::: "memory" )
|
||||
#endif
|
||||
|
||||
|
||||
static inline UBaseType_t uxDisableInterrupts()
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
__asm volatile (
|
||||
"mrs %0, daif\n"
|
||||
"msr daifset, #2\n"
|
||||
: "=r" (flags)
|
||||
:
|
||||
: "memory"
|
||||
);
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static inline void vEnableInterrupts()
|
||||
{
|
||||
__asm volatile (
|
||||
"msr daifclr, #2\n"
|
||||
:
|
||||
:
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
|
||||
static inline void vRestoreInterrupts(UBaseType_t flags)
|
||||
{
|
||||
__asm volatile (
|
||||
"and x2, %0, #128\n"
|
||||
"mrs x1, daif\n"
|
||||
"bic x1, x1, #128\n"
|
||||
"orr x1, x1, x2\n"
|
||||
"msr daif, x1\n"
|
||||
:
|
||||
: "r" (flags)
|
||||
: "x0","x1","x2","memory"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
static inline BaseType_t xPortGetCoreID()
|
||||
{
|
||||
register BaseType_t xCoreID;
|
||||
|
||||
__asm volatile (
|
||||
"mrs x0, mpidr_el1\n"
|
||||
"and %0, x0, #0xff\n"
|
||||
: "=r" (xCoreID)
|
||||
:
|
||||
: "memory", "x0"
|
||||
);
|
||||
|
||||
return xCoreID;
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
extern void vTaskEnterCritical( void );
|
||||
extern void vTaskExitCritical( void );
|
||||
extern UBaseType_t vTaskEnterCriticalFromISR( void );
|
||||
extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
|
||||
|
||||
#define portENTER_CRITICAL() vTaskEnterCritical();
|
||||
#define portEXIT_CRITICAL() vTaskExitCritical();
|
||||
#define portENTER_CRITICAL_FROM_ISR() vTaskEnterCriticalFromISR()
|
||||
#define portEXIT_CRITICAL_FROM_ISR( x ) vTaskExitCriticalFromISR( x )
|
||||
|
||||
#define portDISABLE_INTERRUPTS() uxDisableInterrupts()
|
||||
#define portENABLE_INTERRUPTS() vEnableInterrupts()
|
||||
#define portSET_INTERRUPT_MASK() uxDisableInterrupts()
|
||||
#define portCLEAR_INTERRUPT_MASK(x) vRestoreInterrupts(x)
|
||||
|
||||
#define portHAS_NESTED_INTERRUPTS 1
|
||||
UBaseType_t uxPortSetInterruptMask( void );
|
||||
void vPortClearInterruptMask( UBaseType_t );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(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 )
|
||||
|
||||
/* Prototype of the FreeRTOS tick handler. This must be installed as the
|
||||
handler for whichever peripheral is used to generate the RTOS tick. */
|
||||
void FreeRTOS_Tick_Handler( void );
|
||||
|
||||
/*
|
||||
* Installs pxHandler as the interrupt handler for the peripheral specified by
|
||||
* the ucInterruptID parameter.
|
||||
*
|
||||
* ucInterruptID:
|
||||
*
|
||||
* The ID of the peripheral that will have pxHandler assigned as its interrupt
|
||||
* handler. Peripheral IDs are defined in the xparameters.h header file, which
|
||||
* is itself part of the BSP project.
|
||||
*
|
||||
* pxHandler:
|
||||
*
|
||||
* A pointer to the interrupt handler function itself. This must be a void
|
||||
* function that takes a (void *) parameter.
|
||||
*
|
||||
* pvCallBackRef:
|
||||
*
|
||||
* The parameter passed into the handler function. In many cases this will not
|
||||
* be used and can be NULL. Some times it is used to pass in a reference to
|
||||
* the peripheral instance variable, so it can be accessed from inside the
|
||||
* handler function.
|
||||
*
|
||||
* pdPASS is returned if the function executes successfully. Any other value
|
||||
* being returned indicates that the function did not execute correctly.
|
||||
*/
|
||||
BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef );
|
||||
|
||||
/*
|
||||
* Enables the interrupt, within the interrupt controller, for the peripheral
|
||||
* specified by the ucInterruptID parameter.
|
||||
*
|
||||
* ucInterruptID:
|
||||
*
|
||||
* The ID of the peripheral that will have its interrupt enabled in the
|
||||
* interrupt controller. Peripheral IDs are defined in the xparameters.h header
|
||||
* file, which is itself part of the BSP project.
|
||||
*/
|
||||
void vPortEnableInterrupt( uint8_t ucInterruptID );
|
||||
|
||||
/*
|
||||
* Disables the interrupt, within the interrupt controller, for the peripheral
|
||||
* specified by the ucInterruptID parameter.
|
||||
*
|
||||
* ucInterruptID:
|
||||
*
|
||||
* The ID of the peripheral that will have its interrupt disabled in the
|
||||
* interrupt controller. Peripheral IDs are defined in the xparameters.h header
|
||||
* file, which is itself part of the BSP project.
|
||||
*/
|
||||
void vPortDisableInterrupt( uint8_t ucInterruptID );
|
||||
|
||||
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
|
||||
before any floating point instructions are executed. */
|
||||
#if( configUSE_TASK_FPU_SUPPORT != 2 )
|
||||
void vPortTaskUsesFPU( void );
|
||||
#else
|
||||
/* Each task has an FPU context already, so define this function away to
|
||||
* nothing to prevent it being called accidentally. */
|
||||
#define vPortTaskUsesFPU()
|
||||
#endif
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
|
||||
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
|
||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
|
||||
|
||||
/* 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 */
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif /* configASSERT */
|
||||
|
||||
#define portNOP() __asm volatile( "NOP" )
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
|
||||
/* port for SMP */
|
||||
#define portGET_CORE_ID() xPortGetCoreID()
|
||||
|
||||
static inline void vAssertIfInIsr()
|
||||
{
|
||||
extern volatile uint64_t uxCoreInIsr[configNUMBER_OF_CORES];
|
||||
UBaseType_t x = uxDisableInterrupts();
|
||||
BaseType_t xCoreId = xPortGetCoreID();
|
||||
configASSERT(uxCoreInIsr[xCoreId] == 0);
|
||||
vRestoreInterrupts(x);
|
||||
}
|
||||
#define portASSERT_IF_IN_ISR() vAssertIfInIsr()
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Critical section locks
|
||||
*----------------------------------------------------------*/
|
||||
#define ISR_LOCK (0u)
|
||||
#define TASK_LOCK (1u)
|
||||
|
||||
extern void vPortRecursiveLock(BaseType_t xCoreID, uint32_t ulLockNum, BaseType_t uxAcquire);
|
||||
|
||||
|
||||
#define portRELEASE_ISR_LOCK( xCoreID ) vPortRecursiveLock(( xCoreID ), ISR_LOCK, pdFALSE)
|
||||
#define portGET_ISR_LOCK( xCoreID ) vPortRecursiveLock(( xCoreID ), ISR_LOCK, pdTRUE)
|
||||
|
||||
#define portRELEASE_TASK_LOCK( xCoreID ) vPortRecursiveLock(( xCoreID ), TASK_LOCK, pdFALSE)
|
||||
#define portGET_TASK_LOCK( xCoreID ) vPortRecursiveLock(( xCoreID ), TASK_LOCK, pdTRUE)
|
||||
|
||||
extern void vInterruptCore(uint32_t ulInterruptID, uint32_t ulCoreID);
|
||||
/* Use PPI 0 as the yield core interrupt. */
|
||||
#define portYIELD_CORE_INT_ID 0
|
||||
#define portYIELD_CORE( xCoreID ) vInterruptCore(portYIELD_CORE_INT_ID, (uint32_t)xCoreID)
|
||||
|
||||
|
||||
/* The number of bits to shift for an interrupt priority is dependent on the
|
||||
number of bits implemented by the interrupt controller. */
|
||||
|
||||
#if configUNIQUE_INTERRUPT_PRIORITIES == 16
|
||||
#define portPRIORITY_SHIFT 4
|
||||
#define portMAX_BINARY_POINT_VALUE 3
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32
|
||||
#define portPRIORITY_SHIFT 3
|
||||
#define portMAX_BINARY_POINT_VALUE 2
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64
|
||||
#define portPRIORITY_SHIFT 2
|
||||
#define portMAX_BINARY_POINT_VALUE 1
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128
|
||||
#define portPRIORITY_SHIFT 1
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
|
||||
#define portPRIORITY_SHIFT 0
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#else
|
||||
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(GICv2)
|
||||
/* Interrupt controller access addresses. */
|
||||
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
|
||||
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
|
||||
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
|
||||
#define portICD_SGIR_OFFSET ( 0xF00 )
|
||||
|
||||
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
|
||||
#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
|
||||
#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
|
||||
#define portICD_SGIR_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portICD_SGIR_OFFSET )
|
||||
#endif
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
+317
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.4.2
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <msp430.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the MSP430 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Constants required for hardware setup. The tick ISR runs off the ACLK,
|
||||
not the MCLK. */
|
||||
#define portACLK_FREQUENCY_HZ ( ( TickType_t ) 32768 )
|
||||
#define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 )
|
||||
#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x08 )
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Most ports implement critical sections by placing the interrupt flags on
|
||||
the stack before disabling interrupts. Exiting the critical section is then
|
||||
simply a case of popping the flags from the stack. As mspgcc does not use
|
||||
a frame pointer this cannot be done as modifying the stack will clobber all
|
||||
the stack variables. Instead each task maintains a count of the critical
|
||||
section nesting depth. Each time a critical section is entered the count is
|
||||
incremented. Each time a critical section is left the count is decremented -
|
||||
with interrupts only being re-enabled if the count is zero.
|
||||
|
||||
usCriticalNesting will get set to zero when the scheduler starts, but must
|
||||
not be initialised to zero as this will cause problems during the startup
|
||||
sequence. */
|
||||
volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Macro to save a task context to the task stack. This simply pushes all the
|
||||
* general purpose msp430 registers onto the stack, followed by the
|
||||
* usCriticalNesting value used by the task. Finally the resultant stack
|
||||
* pointer value is saved into the task control block so it can be retrieved
|
||||
* the next time the task executes.
|
||||
*/
|
||||
#ifdef __LARGE_DATA_MODEL__
|
||||
#define portSAVE_CONTEXT() \
|
||||
asm volatile ( "pushm.a #12, r15 \n\t" \
|
||||
"movx.w &usCriticalNesting, r14 \n\t" \
|
||||
"pushm.a #1, r14 \n\t" \
|
||||
"movx.a &pxCurrentTCB, r12 \n\t" \
|
||||
"movx.a sp, 0(r12) \n\t" \
|
||||
);
|
||||
#else
|
||||
#define portSAVE_CONTEXT() \
|
||||
asm volatile ( "pushm.w #12, r15 \n\t" \
|
||||
"mov.w &usCriticalNesting, r14 \n\t" \
|
||||
"push.w r14 \n\t" \
|
||||
"mov.w &pxCurrentTCB, r12 \n\t" \
|
||||
"mov.w sp, 0(r12) \r\t" \
|
||||
);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macro to restore a task context from the task stack. This is effectively
|
||||
* the reverse of portSAVE_CONTEXT(). First the stack pointer value is
|
||||
* loaded from the task control block. Next the value for usCriticalNesting
|
||||
* used by the task is retrieved from the stack - followed by the value of all
|
||||
* the general purpose msp430 registers.
|
||||
*
|
||||
*/
|
||||
#ifdef __LARGE_DATA_MODEL__
|
||||
#define portRESTORE_CONTEXT() \
|
||||
asm volatile ( "movx.a &pxCurrentTCB, r12 \n\t" \
|
||||
"movx.a @r12, sp \n\t" \
|
||||
"popm.a #1, r15 \n\t" \
|
||||
"movx.w r15, &usCriticalNesting \n\t" \
|
||||
"popm.a #12, r15 \n\t" \
|
||||
"nop \n\t" \
|
||||
"pop.w sr \n\t" \
|
||||
"nop \n\t" \
|
||||
"reta \n\t" \
|
||||
);
|
||||
#else
|
||||
#define portRESTORE_CONTEXT() \
|
||||
asm volatile ( "mov.w &pxCurrentTCB, r12 \n\t" \
|
||||
"mov.w @r12, sp \n\t" \
|
||||
"pop.w r15 \n\t" \
|
||||
"mov.w r15, &usCriticalNesting \n\t" \
|
||||
"popm.w #12, r15 \n\t" \
|
||||
"nop \n\t" \
|
||||
"pop.w sr \n\t" \
|
||||
"nop \n\t" \
|
||||
"ret \n\t" \
|
||||
);
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Sets up the periodic ISR used for the RTOS tick. This uses timer 0, but
|
||||
* could have alternatively used the watchdog timer or timer 1.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See the header file portable.h.
|
||||
*/
|
||||
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
uint16_t *pusTopOfStack;
|
||||
uint32_t *pulTopOfStack, ulTemp;
|
||||
|
||||
/*
|
||||
Place a few bytes of known values on the bottom of the stack.
|
||||
This is just useful for debugging and can be included if required.
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x1111;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x2222;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x3333;
|
||||
pxTopOfStack--;
|
||||
*/
|
||||
|
||||
/* Data types are need either 16 bits or 32 bits depending on the data
|
||||
and code model used. */
|
||||
if( sizeof( pxCode ) == sizeof( uint16_t ) )
|
||||
{
|
||||
pusTopOfStack = ( uint16_t * ) pxTopOfStack;
|
||||
ulTemp = ( uint32_t ) pxCode;
|
||||
*pusTopOfStack = ( uint16_t ) ulTemp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make room for a 20 bit value stored as a 32 bit value. */
|
||||
pusTopOfStack = ( uint16_t * ) pxTopOfStack;
|
||||
pusTopOfStack--;
|
||||
pulTopOfStack = ( uint32_t * ) pusTopOfStack;
|
||||
*pulTopOfStack = ( uint32_t ) pxCode;
|
||||
}
|
||||
|
||||
pusTopOfStack--;
|
||||
*pusTopOfStack = portFLAGS_INT_ENABLED;
|
||||
pusTopOfStack -= ( sizeof( StackType_t ) / 2 );
|
||||
|
||||
/* From here on the size of stacked items depends on the memory model. */
|
||||
pxTopOfStack = ( StackType_t * ) pusTopOfStack;
|
||||
|
||||
/* Next the general purpose registers. */
|
||||
#ifdef PRELOAD_REGISTER_VALUES
|
||||
*pxTopOfStack = ( StackType_t ) 0xffff;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xeeee;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xdddd;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xbbbb;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xaaaa;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x9999;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x8888;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x7777;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x6666;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x5555;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x4444;
|
||||
pxTopOfStack--;
|
||||
#else
|
||||
pxTopOfStack -= 3;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack -= 9;
|
||||
#endif
|
||||
|
||||
/* A variable is used to keep track of the critical section nesting.
|
||||
This variable has to be stored as part of the task context and is
|
||||
initially set to zero. */
|
||||
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
|
||||
|
||||
/* Return a pointer to the top of the stack we have generated so this can
|
||||
be stored in the task control block for the task. */
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Setup the hardware to generate the tick. Interrupts are disabled when
|
||||
this function is called. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Restore the context of the first task that is going to run. */
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
/* Should not get here as the tasks are now running! */
|
||||
return pdTRUE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the MSP430 port will get stopped. If required simply
|
||||
disable the tick interrupt here. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Manual context switch called by portYIELD or taskYIELD.
|
||||
*
|
||||
* The first thing we do is save the registers so we can use a naked attribute.
|
||||
*/
|
||||
|
||||
void vPortYield( void ) __attribute__ ( ( naked ) );
|
||||
void vPortYield( void )
|
||||
{
|
||||
asm volatile ( "push.w sr" );
|
||||
|
||||
portDISABLE_INTERRUPTS();
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
vTaskSwitchContext();
|
||||
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Hardware initialisation to generate the RTOS tick. This uses timer 0
|
||||
* but could alternatively use the watchdog timer or timer 1.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
vApplicationSetupTimerInterrupt();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The interrupt service routine used depends on whether the pre-emptive
|
||||
* scheduler is being used or not.
|
||||
*/
|
||||
|
||||
#if configUSE_PREEMPTION == 1
|
||||
void vPortPreemptiveTickISR(void)
|
||||
{
|
||||
asm volatile("push.w sr");
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
if(xTaskIncrementTick() != pdFALSE)
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
|
||||
__attribute__((interrupt(configTICK_VECTOR))) void prvTickISR(void)
|
||||
{
|
||||
__bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF );
|
||||
vPortPreemptiveTickISR();
|
||||
}
|
||||
#else
|
||||
void vPortCooperativeTickISR(void)
|
||||
{
|
||||
asm volatile("push.w sr");
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
xTaskIncrementTick();
|
||||
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
|
||||
__attribute__((interrupt(configTICK_VECTOR))) void prvTickISR(void)
|
||||
{
|
||||
__bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF );
|
||||
|
||||
vPortCooperativeTickISR();
|
||||
}
|
||||
#endif
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.4.2
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Hardware includes. */
|
||||
#include <msp430.h>
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT int
|
||||
#define portBASE_TYPE short
|
||||
|
||||
/* The stack type changes depending on the data model. */
|
||||
#ifdef __LARGE_DATA_MODEL__
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#else
|
||||
#define portSTACK_TYPE uint16_t
|
||||
#define portPOINTER_SIZE_TYPE uint16_t
|
||||
#endif
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef short BaseType_t;
|
||||
typedef unsigned short UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Interrupt control macros. */
|
||||
#define portDISABLE_INTERRUPTS() asm volatile ( "NOP" ); asm volatile ( "DINT" ); asm volatile ( "NOP" )
|
||||
#define portENABLE_INTERRUPTS() asm volatile ( "NOP" ); asm volatile ( "EINT" ); asm volatile ( "NOP" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section control macros. */
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 )
|
||||
|
||||
#define portENTER_CRITICAL() \
|
||||
{ \
|
||||
extern volatile uint16_t usCriticalNesting; \
|
||||
\
|
||||
portDISABLE_INTERRUPTS(); \
|
||||
\
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed */ \
|
||||
/* directly. Increment ulCriticalNesting to keep a count of how many */ \
|
||||
/* times portENTER_CRITICAL() has been called. */ \
|
||||
usCriticalNesting++; \
|
||||
}
|
||||
|
||||
#define portEXIT_CRITICAL() \
|
||||
{ \
|
||||
extern volatile uint16_t usCriticalNesting; \
|
||||
\
|
||||
if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \
|
||||
{ \
|
||||
/* Decrement the nesting count as we are leaving a critical section. */ \
|
||||
usCriticalNesting--; \
|
||||
\
|
||||
/* If the nesting level has reached zero then interrupts should be */ \
|
||||
/* re-enabled. */ \
|
||||
if( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
|
||||
{ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
extern void vPortYield( void ) __attribute__ ( ( naked ) );
|
||||
#define portYIELD() vPortYield()
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portBYTE_ALIGNMENT 2
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
extern void vTaskSwitchContext(void);
|
||||
#define portYIELD_FROM_ISR( x ) if( x ) vPortYield()
|
||||
void vApplicationSetupTimerInterrupt( void );
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.4.0
|
||||
* 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!
|
||||
*/
|
||||
|
||||
/*
|
||||
* The FreeRTOS kernel's RISC-V port is split between the the code that is
|
||||
* common across all currently supported RISC-V chips (implementations of the
|
||||
* RISC-V ISA), and code that tailors the port to a specific RISC-V chip:
|
||||
*
|
||||
* + FreeRTOS\Source\portable\GCC\RISC-V-RV32\portASM.S contains the code that
|
||||
* is common to all currently supported RISC-V chips. There is only one
|
||||
* portASM.S file because the same file is built for all RISC-V target chips.
|
||||
*
|
||||
* + Header files called freertos_risc_v_chip_specific_extensions.h contain the
|
||||
* code that tailors the FreeRTOS kernel's RISC-V port to a specific RISC-V
|
||||
* chip. There are multiple freertos_risc_v_chip_specific_extensions.h files
|
||||
* as there are multiple RISC-V chip implementations.
|
||||
*
|
||||
* !!!NOTE!!!
|
||||
* TAKE CARE TO INCLUDE THE CORRECT freertos_risc_v_chip_specific_extensions.h
|
||||
* HEADER FILE FOR THE CHIP IN USE. This is done using the assembler's (not the
|
||||
* compiler's!) include path. For example, if the chip in use includes a core
|
||||
* local interrupter (CLINT) and does not include any chip specific register
|
||||
* extensions then add the path below to the assembler's include path:
|
||||
* FreeRTOS\Source\portable\GCC\RISC-V-RV32\chip_specific_extensions\RV32I_CLINT_no_extensions
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __FREERTOS_RISC_V_EXTENSIONS_H__
|
||||
#define __FREERTOS_RISC_V_EXTENSIONS_H__
|
||||
|
||||
#define portasmHANDLE_INTERRUPT Default_IRQHandler
|
||||
#define portasmHAS_SIFIVE_CLINT 1
|
||||
#define portasmHAS_MTIME 0
|
||||
#define portasmADDITIONAL_CONTEXT_SIZE 0 /* Must be even number on 32-bit cores. */
|
||||
|
||||
.macro portasmSAVE_ADDITIONAL_REGISTERS
|
||||
/* save float registers */
|
||||
#if __riscv_flen == 64
|
||||
addi sp, sp, -(128+128)
|
||||
|
||||
fsd f31, (0 + 0 )(sp)
|
||||
fsd f30, (4 + 4 )(sp)
|
||||
fsd f29, (8 + 8 )(sp)
|
||||
fsd f28, (12 + 12)(sp)
|
||||
fsd f27, (16 + 16)(sp)
|
||||
fsd f26, (20 + 20)(sp)
|
||||
fsd f25, (24 + 24)(sp)
|
||||
fsd f24, (28 + 28)(sp)
|
||||
fsd f23, (32 + 32)(sp)
|
||||
fsd f22, (36 + 36)(sp)
|
||||
fsd f21, (40 + 40)(sp)
|
||||
fsd f20, (44 + 44)(sp)
|
||||
fsd f19, (48 + 48)(sp)
|
||||
fsd f18, (52 + 52)(sp)
|
||||
fsd f17, (56 + 56)(sp)
|
||||
fsd f16, (60 + 60)(sp)
|
||||
fsd f15, (64 + 64)(sp)
|
||||
fsd f14, (68 + 68)(sp)
|
||||
fsd f13, (72 + 72)(sp)
|
||||
fsd f12, (76 + 76)(sp)
|
||||
fsd f11, (80 + 80)(sp)
|
||||
fsd f10, (84 + 84)(sp)
|
||||
fsd f9, (88 + 88)(sp)
|
||||
fsd f8, (92 + 92)(sp)
|
||||
fsd f7, (96 + 96)(sp)
|
||||
fsd f6, (100+100)(sp)
|
||||
fsd f5, (104+104)(sp)
|
||||
fsd f4, (108+108)(sp)
|
||||
fsd f3, (112+112)(sp)
|
||||
fsd f2, (116+116)(sp)
|
||||
fsd f1, (120+120)(sp)
|
||||
fsd f0, (124+124)(sp)
|
||||
#elif __riscv_flen == 32
|
||||
addi sp, sp, -(128)
|
||||
|
||||
fsw f31, (0 )(sp)
|
||||
fsw f30, (4 )(sp)
|
||||
fsw f29, (8 )(sp)
|
||||
fsw f28, (12 )(sp)
|
||||
fsw f27, (16 )(sp)
|
||||
fsw f26, (20 )(sp)
|
||||
fsw f25, (24 )(sp)
|
||||
fsw f24, (28 )(sp)
|
||||
fsw f23, (32 )(sp)
|
||||
fsw f22, (36 )(sp)
|
||||
fsw f21, (40 )(sp)
|
||||
fsw f20, (44 )(sp)
|
||||
fsw f19, (48 )(sp)
|
||||
fsw f18, (52 )(sp)
|
||||
fsw f17, (56 )(sp)
|
||||
fsw f16, (60 )(sp)
|
||||
fsw f15, (64 )(sp)
|
||||
fsw f14, (68 )(sp)
|
||||
fsw f13, (72 )(sp)
|
||||
fsw f12, (76 )(sp)
|
||||
fsw f11, (80 )(sp)
|
||||
fsw f10, (84 )(sp)
|
||||
fsw f9, (88 )(sp)
|
||||
fsw f8, (92 )(sp)
|
||||
fsw f7, (96 )(sp)
|
||||
fsw f6, (100)(sp)
|
||||
fsw f5, (104)(sp)
|
||||
fsw f4, (108)(sp)
|
||||
fsw f3, (112)(sp)
|
||||
fsw f2, (116)(sp)
|
||||
fsw f1, (120)(sp)
|
||||
fsw f0, (124)(sp)
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro portasmRESTORE_ADDITIONAL_REGISTERS
|
||||
/* load float registers */
|
||||
#if __riscv_flen == 64
|
||||
fld f31, (0 + 0 )(sp)
|
||||
fld f30, (4 + 4 )(sp)
|
||||
fld f29, (8 + 8 )(sp)
|
||||
fld f28, (12 + 12)(sp)
|
||||
fld f27, (16 + 16)(sp)
|
||||
fld f26, (20 + 20)(sp)
|
||||
fld f25, (24 + 24)(sp)
|
||||
fld f24, (28 + 28)(sp)
|
||||
fld f23, (32 + 32)(sp)
|
||||
fld f22, (36 + 36)(sp)
|
||||
fld f21, (40 + 40)(sp)
|
||||
fld f20, (44 + 44)(sp)
|
||||
fld f19, (48 + 48)(sp)
|
||||
fld f18, (52 + 52)(sp)
|
||||
fld f17, (56 + 56)(sp)
|
||||
fld f16, (60 + 60)(sp)
|
||||
fld f15, (64 + 64)(sp)
|
||||
fld f14, (68 + 68)(sp)
|
||||
fld f13, (72 + 72)(sp)
|
||||
fld f12, (76 + 76)(sp)
|
||||
fld f11, (80 + 80)(sp)
|
||||
fld f10, (84 + 84)(sp)
|
||||
fld f9, (88 + 88)(sp)
|
||||
fld f8, (92 + 92)(sp)
|
||||
fld f7, (96 + 96)(sp)
|
||||
fld f6, (100+100)(sp)
|
||||
fld f5, (104+104)(sp)
|
||||
fld f4, (108+108)(sp)
|
||||
fld f3, (112+112)(sp)
|
||||
fld f2, (116+116)(sp)
|
||||
fld f1, (120+120)(sp)
|
||||
fld f0, (124+124)(sp)
|
||||
|
||||
addi sp, sp, (128+128)
|
||||
#elif __riscv_flen == 32
|
||||
flw f31, (0 )(sp)
|
||||
flw f30, (4 )(sp)
|
||||
flw f29, (8 )(sp)
|
||||
flw f28, (12 )(sp)
|
||||
flw f27, (16 )(sp)
|
||||
flw f26, (20 )(sp)
|
||||
flw f25, (24 )(sp)
|
||||
flw f24, (28 )(sp)
|
||||
flw f23, (32 )(sp)
|
||||
flw f22, (36 )(sp)
|
||||
flw f21, (40 )(sp)
|
||||
flw f20, (44 )(sp)
|
||||
flw f19, (48 )(sp)
|
||||
flw f18, (52 )(sp)
|
||||
flw f17, (56 )(sp)
|
||||
flw f16, (60 )(sp)
|
||||
flw f15, (64 )(sp)
|
||||
flw f14, (68 )(sp)
|
||||
flw f13, (72 )(sp)
|
||||
flw f12, (76 )(sp)
|
||||
flw f11, (80 )(sp)
|
||||
flw f10, (84 )(sp)
|
||||
flw f9, (88 )(sp)
|
||||
flw f8, (92 )(sp)
|
||||
flw f7, (96 )(sp)
|
||||
flw f6, (100)(sp)
|
||||
flw f5, (104)(sp)
|
||||
flw f4, (108)(sp)
|
||||
flw f3, (112)(sp)
|
||||
flw f2, (116)(sp)
|
||||
flw f1, (120)(sp)
|
||||
flw f0, (124)(sp)
|
||||
|
||||
addi sp, sp, (128)
|
||||
#endif
|
||||
.endm
|
||||
#endif /* __FREERTOS_RISC_V_EXTENSIONS_H__ */
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
if (NOT TARGET _FreeRTOS_kernel_inclusion_marker)
|
||||
add_library(_FreeRTOS_kernel_inclusion_marker INTERFACE)
|
||||
|
||||
# Pull in PICO SDK (must be before project)
|
||||
include(pico_sdk_import.cmake)
|
||||
if (PICO_SDK_VERSION_STRING VERSION_LESS "2.0.0")
|
||||
message(FATAL_ERROR "Require at least Raspberry Pi Pico SDK version 2.0.0")
|
||||
endif()
|
||||
|
||||
if (NOT FREERTOS_KERNEL_PATH)
|
||||
get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/../../../.. REALPATH)
|
||||
endif ()
|
||||
|
||||
message(DEBUG "FREERTOS_KERNEL_PATH is ${FREERTOS_KERNEL_PATH}")
|
||||
project(FreeRTOS-Kernel C CXX)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
pico_is_top_level_project(FREERTOS_KERNEL_TOP_LEVEL_PROJECT)
|
||||
|
||||
# if the SDK has already been initialized, then just add our libraries now - this allows
|
||||
# this FreeRTOS port to just be added as a sub-directory or include within another project, rather than
|
||||
# having to include it at the top level before pico_sdk_init()
|
||||
if (TARGET _pico_sdk_inclusion_marker)
|
||||
if (PICO_SDK_VERSION_STRING VERSION_LESS "1.3.2")
|
||||
message(FATAL_ERROR "Require at least Raspberry Pi Pico SDK version 1.3.2 to include FreeRTOS after pico_sdk_init()")
|
||||
endif()
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/library.cmake)
|
||||
else()
|
||||
# The real work gets done in library.cmake which is called at the end of pico_sdk_init
|
||||
list(APPEND PICO_SDK_POST_LIST_FILES ${CMAKE_CURRENT_LIST_DIR}/library.cmake)
|
||||
if (PICO_SDK_VERSION_STRING VERSION_LESS "1.3.2")
|
||||
# We need to inject the following header file into ALL SDK files (which we do via the config header)
|
||||
list(APPEND PICO_CONFIG_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/include/freertos_sdk_config.h)
|
||||
endif()
|
||||
|
||||
if (FREERTOS_KERNEL_TOP_LEVEL_PROJECT)
|
||||
message("FreeRTOS: initialize SDK since we're the top-level")
|
||||
# Initialize the SDK
|
||||
pico_sdk_init()
|
||||
else()
|
||||
set(FREERTOS_KERNEL_PATH ${FREERTOS_KERNEL_PATH} PARENT_SCOPE)
|
||||
set(PICO_CONFIG_HEADER_FILES ${PICO_CONFIG_HEADER_FILES} PARENT_SCOPE)
|
||||
set(PICO_SDK_POST_LIST_FILES ${PICO_SDK_POST_LIST_FILES} PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
# This is a copy of <FREERTOS_KERNEL_PATH>/portable/ThirdParty/GCC/RP2040/FREERTOS_KERNEL_import.cmake
|
||||
|
||||
# This can be dropped into an external project to help locate the FreeRTOS kernel
|
||||
# It should be include()ed prior to project(). Alternatively this file may
|
||||
# or the CMakeLists.txt in this directory may be included or added via add_subdirectory
|
||||
# respectively.
|
||||
|
||||
if (DEFINED ENV{FREERTOS_KERNEL_PATH} AND (NOT FREERTOS_KERNEL_PATH))
|
||||
set(FREERTOS_KERNEL_PATH $ENV{FREERTOS_KERNEL_PATH})
|
||||
message("Using FREERTOS_KERNEL_PATH from environment ('${FREERTOS_KERNEL_PATH}')")
|
||||
endif ()
|
||||
|
||||
# first pass we look in old tree; second pass we look in new tree
|
||||
foreach(SEARCH_PASS RANGE 0 1)
|
||||
if (SEARCH_PASS)
|
||||
# ports may be moving to submodule in the future
|
||||
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "portable/ThirdParty/Community-Supported-Ports/GCC")
|
||||
set(FREERTOS_KERNEL_RP2040_BACK_PATH "../../../../..")
|
||||
else()
|
||||
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "portable/ThirdParty/GCC")
|
||||
set(FREERTOS_KERNEL_RP2040_BACK_PATH "../../../..")
|
||||
endif()
|
||||
|
||||
if(PICO_PLATFORM STREQUAL "rp2040")
|
||||
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2040")
|
||||
else()
|
||||
if (PICO_PLATFORM STREQUAL "rp2350-riscv")
|
||||
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2350_RISC-V")
|
||||
else()
|
||||
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2350_ARM_NTZ")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT FREERTOS_KERNEL_PATH)
|
||||
# check if we are inside the FreeRTOS kernel tree (i.e. this file has been included directly)
|
||||
get_filename_component(_ACTUAL_PATH ${CMAKE_CURRENT_LIST_DIR} REALPATH)
|
||||
get_filename_component(_POSSIBLE_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} REALPATH)
|
||||
if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH)
|
||||
get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH)
|
||||
endif()
|
||||
if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH)
|
||||
get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH)
|
||||
message("Setting FREERTOS_KERNEL_PATH to ${FREERTOS_KERNEL_PATH} based on location of FreeRTOS-Kernel-import.cmake")
|
||||
break()
|
||||
elseif (PICO_SDK_PATH AND EXISTS "${PICO_SDK_PATH}/../FreeRTOS-Kernel")
|
||||
set(FREERTOS_KERNEL_PATH ${PICO_SDK_PATH}/../FreeRTOS-Kernel)
|
||||
message("Defaulting FREERTOS_KERNEL_PATH as sibling of PICO_SDK_PATH: ${FREERTOS_KERNEL_PATH}")
|
||||
break()
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if (NOT FREERTOS_KERNEL_PATH)
|
||||
foreach(POSSIBLE_SUFFIX Source FreeRTOS-Kernel FreeRTOS/Source)
|
||||
# check if FreeRTOS-Kernel exists under directory that included us
|
||||
set(SEARCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
get_filename_component(_POSSIBLE_PATH ${SEARCH_ROOT}/${POSSIBLE_SUFFIX} REALPATH)
|
||||
if (EXISTS ${_POSSIBLE_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt)
|
||||
get_filename_component(FREERTOS_KERNEL_PATH ${_POSSIBLE_PATH} REALPATH)
|
||||
message("Setting FREERTOS_KERNEL_PATH to '${FREERTOS_KERNEL_PATH}' found relative to enclosing project")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
if (FREERTOS_KERNEL_PATH)
|
||||
break()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# user must have specified
|
||||
if (FREERTOS_KERNEL_PATH)
|
||||
if (EXISTS "${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}")
|
||||
break()
|
||||
endif()
|
||||
endif()
|
||||
endforeach ()
|
||||
|
||||
if (NOT FREERTOS_KERNEL_PATH)
|
||||
message(FATAL_ERROR "FreeRTOS location was not specified. Please set FREERTOS_KERNEL_PATH.")
|
||||
endif()
|
||||
|
||||
set(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" CACHE PATH "Path to the FreeRTOS Kernel")
|
||||
|
||||
get_filename_component(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||
if (NOT EXISTS ${FREERTOS_KERNEL_PATH})
|
||||
message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' not found")
|
||||
endif()
|
||||
if (NOT EXISTS ${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt)
|
||||
message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' does not contain a '${PICO_PLATFORM}' port here: ${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}")
|
||||
endif()
|
||||
set(FREERTOS_KERNEL_PATH ${FREERTOS_KERNEL_PATH} CACHE PATH "Path to the FreeRTOS_KERNEL" FORCE)
|
||||
|
||||
add_subdirectory(${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} FREERTOS_KERNEL)
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
BSD-3-Clause License
|
||||
|
||||
Copyright (c) 2020-2021 Raspberry Pi (Trading) Ltd.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
|
||||
2. 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.
|
||||
|
||||
3. Neither the name of the copyright holder 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 HOLDER 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.
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
## Overview
|
||||
|
||||
This directory provides an SMP FreeRTOS-Kernel port that can be used with the Raspberry Pi Pico SDK on RP2350. It supports:
|
||||
|
||||
* Simple CMake INTERFACE libraries, to provide the FreeRTOS-Kernel and also the individual allocator types, without copying code into the user's project.
|
||||
* Running the FreeRTOS-Kernel and tasks on either core 0 or core 1, or both.
|
||||
* Use of SDK synchronization primitives (such as mutexes, semaphores, queues from pico_sync) between FreeRTOS tasks and code executing on a non FreeRTOS core, or in IRQ handlers.
|
||||
|
||||
Note that whilst this SMP version can be run on just a single (either) core, it is probably
|
||||
more efficient to use the non SMP version in the main FreeRTOS-Kernel branch in that case.
|
||||
|
||||
## Using this port
|
||||
|
||||
You can copy [FreeRTOS_Kernel_import.cmake](FreeRTOS_Kernel_import.cmake) into your project, and
|
||||
add the following in your `CMakeLists.txt`:
|
||||
|
||||
```cmake
|
||||
include(FreeRTOS_Kernel_import.cmake)
|
||||
```
|
||||
|
||||
This will locate the FreeRTOS kernel if it is a direct sub-module of your project, or if you provide the
|
||||
`FREERTOS_KERNEL_PATH` variable in your environment or via `-DFREERTOS_KERNEL_PATH=/path/to/FreeRTOS-Kernel` on the CMake command line.
|
||||
|
||||
**NOTE:** If you are using version 1.3.1 or older of the Raspberry Pi Pico SDK then this line must appear before the
|
||||
`pico_sdk_init()` and will cause FreeRTOS to be included/required in all RP2040 targets in your project. After this SDK
|
||||
version, you can include the FreeRTOS-Kernel support later in your CMake build (possibly in a subdirectory) and the
|
||||
FreeRTOS-Kernel support will only apply to those targets which explicitly include FreeRTOS support.
|
||||
|
||||
As an alternative to the `import` statement above, you can just add this directory directly via thw following (with
|
||||
the same placement restrictions related to the Raspberry Pi Pico SDK version above):
|
||||
|
||||
```cmake
|
||||
add_subdirectory(path/to/this/directory FreeRTOS-Kernel)
|
||||
```
|
||||
## FreeRTOS configuration for Armv8-M
|
||||
|
||||
The following standard FreeRTOS ARM options are required for RP2350"
|
||||
|
||||
These three options must be specified as follows, as only RP2040-like FreeRTOS implementation only is supported currently; running in at a single privilege level in the secure statea.
|
||||
|
||||
```c
|
||||
#define configENABLE_MPU 0
|
||||
#define configENABLE_TRUSTZONE 0
|
||||
#define configRUN_FREERTOS_SECURE_ONLY 1
|
||||
```
|
||||
|
||||
You can set the following to enable save/restore of FPU state (you should set this is you are using floating point operations)
|
||||
|
||||
```c
|
||||
#define configENABLE_FPU 1
|
||||
```
|
||||
|
||||
As of right now this is the only value of configMAX_SYSCALL_INTERRUPT_PRIORITY that has been tested
|
||||
|
||||
```c
|
||||
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 16
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
Some additional `config` options are defined [here](include/rp2040_config.h) which control some low level implementation details.
|
||||
|
||||
## Known Limitations
|
||||
|
||||
- Tickless idle has not currently been tested, and is likely non-functiona
|
||||
- There is no TrustZone version
|
||||
- There is no support for enabling MPU for user/handler mode within FreeRTOS
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
# Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
# Called after the Raspberry Pi Pico SDK has been initialized to add our libraries
|
||||
|
||||
add_library(FreeRTOS-Kernel-Core INTERFACE)
|
||||
target_sources(FreeRTOS-Kernel-Core INTERFACE
|
||||
${FREERTOS_KERNEL_PATH}/croutine.c
|
||||
${FREERTOS_KERNEL_PATH}/event_groups.c
|
||||
${FREERTOS_KERNEL_PATH}/list.c
|
||||
${FREERTOS_KERNEL_PATH}/queue.c
|
||||
${FREERTOS_KERNEL_PATH}/stream_buffer.c
|
||||
${FREERTOS_KERNEL_PATH}/tasks.c
|
||||
${FREERTOS_KERNEL_PATH}/timers.c
|
||||
)
|
||||
target_include_directories(FreeRTOS-Kernel-Core INTERFACE ${FREERTOS_KERNEL_PATH}/include)
|
||||
|
||||
if (PICO_SDK_VERSION_STRING VERSION_GREATER_EQUAL "1.3.2")
|
||||
target_compile_definitions(FreeRTOS-Kernel-Core INTERFACE
|
||||
PICO_CONFIG_RTOS_ADAPTER_HEADER=${CMAKE_CURRENT_LIST_DIR}/non_secure/freertos_sdk_config.h)
|
||||
endif()
|
||||
|
||||
add_library(FreeRTOS-Kernel INTERFACE)
|
||||
target_sources(FreeRTOS-Kernel INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/non_secure/port.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/non_secure/portasm.c
|
||||
)
|
||||
|
||||
target_include_directories(FreeRTOS-Kernel INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/non_secure
|
||||
${FREERTOS_CONFIG_FILE_DIRECTORY})
|
||||
|
||||
target_link_libraries(FreeRTOS-Kernel INTERFACE
|
||||
FreeRTOS-Kernel-Core
|
||||
pico_base_headers
|
||||
hardware_clocks
|
||||
hardware_exception
|
||||
pico_multicore
|
||||
)
|
||||
|
||||
target_compile_definitions(FreeRTOS-Kernel INTERFACE
|
||||
LIB_FREERTOS_KERNEL=1
|
||||
FREE_RTOS_KERNEL_SMP=1
|
||||
)
|
||||
|
||||
add_library(FreeRTOS-Kernel-Static INTERFACE)
|
||||
target_compile_definitions(FreeRTOS-Kernel-Static INTERFACE
|
||||
configSUPPORT_STATIC_ALLOCATION=1
|
||||
configKERNEL_PROVIDED_STATIC_MEMORY=1
|
||||
)
|
||||
|
||||
target_link_libraries(FreeRTOS-Kernel-Static INTERFACE FreeRTOS-Kernel)
|
||||
|
||||
add_library(FreeRTOS-Kernel-Heap1 INTERFACE)
|
||||
target_sources(FreeRTOS-Kernel-Heap1 INTERFACE ${FREERTOS_KERNEL_PATH}/portable/MemMang/heap_1.c)
|
||||
target_link_libraries(FreeRTOS-Kernel-Heap1 INTERFACE FreeRTOS-Kernel)
|
||||
|
||||
add_library(FreeRTOS-Kernel-Heap2 INTERFACE)
|
||||
target_sources(FreeRTOS-Kernel-Heap2 INTERFACE ${FREERTOS_KERNEL_PATH}/portable/MemMang/heap_2.c)
|
||||
target_link_libraries(FreeRTOS-Kernel-Heap2 INTERFACE FreeRTOS-Kernel)
|
||||
|
||||
add_library(FreeRTOS-Kernel-Heap3 INTERFACE)
|
||||
target_sources(FreeRTOS-Kernel-Heap3 INTERFACE ${FREERTOS_KERNEL_PATH}/portable/MemMang/heap_3.c)
|
||||
target_link_libraries(FreeRTOS-Kernel-Heap3 INTERFACE FreeRTOS-Kernel)
|
||||
|
||||
add_library(FreeRTOS-Kernel-Heap4 INTERFACE)
|
||||
target_sources(FreeRTOS-Kernel-Heap4 INTERFACE ${FREERTOS_KERNEL_PATH}/portable/MemMang/heap_4.c)
|
||||
target_link_libraries(FreeRTOS-Kernel-Heap4 INTERFACE FreeRTOS-Kernel)
|
||||
|
||||
add_library(FreeRTOS-Kernel-Heap5 INTERFACE)
|
||||
target_sources(FreeRTOS-Kernel-Heap5 INTERFACE ${FREERTOS_KERNEL_PATH}/portable/MemMang/heap_5.c)
|
||||
target_link_libraries(FreeRTOS-Kernel-Heap5 INTERFACE FreeRTOS-Kernel)
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_SDK_CONFIG_H
|
||||
#define FREERTOS_SDK_CONFIG_H
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include "FreeRTOSConfig.h"
|
||||
#include "rp2040_config.h"
|
||||
#ifndef PICO_USE_MALLOC_MUTEX
|
||||
/* malloc needs to be made thread safe */
|
||||
#define PICO_USE_MALLOC_MUTEX 1
|
||||
#endif /* PICO_USE_MALLOC_MUTEX */
|
||||
#if ( configSUPPORT_PICO_SYNC_INTEROP == 1 )
|
||||
/* increase the amount of time it may reasonably take to wake us up */
|
||||
#ifndef PICO_TIME_SLEEP_OVERHEAD_ADJUST_US
|
||||
#define PICO_TIME_SLEEP_OVERHEAD_ADJUST_US 150
|
||||
#endif
|
||||
|
||||
#define lock_owner_id_t uint32_t
|
||||
extern uint32_t ulPortLockGetCurrentOwnerId( void );
|
||||
#define lock_get_caller_owner_id() ulPortLockGetCurrentOwnerId()
|
||||
#define LOCK_INVALID_OWNER_ID ( ( uint32_t ) -1 )
|
||||
|
||||
struct lock_core;
|
||||
#ifndef lock_internal_spin_unlock_with_wait
|
||||
extern void vPortLockInternalSpinUnlockWithWait( struct lock_core * pxLock,
|
||||
uint32_t ulSave );
|
||||
#define lock_internal_spin_unlock_with_wait( lock, save ) vPortLockInternalSpinUnlockWithWait( lock, save )
|
||||
#endif
|
||||
|
||||
#ifndef lock_internal_spin_unlock_with_notify
|
||||
extern void vPortLockInternalSpinUnlockWithNotify( struct lock_core * pxLock,
|
||||
uint32_t save );
|
||||
#define lock_internal_spin_unlock_with_notify( lock, save ) vPortLockInternalSpinUnlockWithNotify( lock, save );
|
||||
#endif
|
||||
|
||||
#ifndef lock_internal_spin_unlock_with_best_effort_wait_or_timeout
|
||||
extern bool xPortLockInternalSpinUnlockWithBestEffortWaitOrTimeout( struct lock_core * pxLock,
|
||||
uint32_t ulSave,
|
||||
absolute_time_t uxUntil );
|
||||
#define lock_internal_spin_unlock_with_best_effort_wait_or_timeout( lock, save, until ) \
|
||||
xPortLockInternalSpinUnlockWithBestEffortWaitOrTimeout( lock, save, until )
|
||||
#endif
|
||||
#endif /* configSUPPORT_PICO_SYNC_INTEROP */
|
||||
|
||||
#if ( configSUPPORT_PICO_TIME_INTEROP == 1 )
|
||||
extern void xPortSyncInternalYieldUntilBefore( absolute_time_t t );
|
||||
#define sync_internal_yield_until_before( t ) xPortSyncInternalYieldUntilBefore( t )
|
||||
#endif /* configSUPPORT_PICO_TIME_INTEROP */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* ifndef FREERTOS_SDK_CONFIG_H */
|
||||
+2055
File diff suppressed because it is too large
Load Diff
Vendored
+2744
File diff suppressed because it is too large
Load Diff
Vendored
+526
@@ -0,0 +1,526 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
|
||||
* is defined correctly and privileged functions are placed in correct sections. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Portasm includes. */
|
||||
#include "portasm.h"
|
||||
#include "hardware/address_mapped.h"
|
||||
|
||||
/* System call numbers includes. */
|
||||
#include "mpu_syscall_numbers.h"
|
||||
|
||||
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
|
||||
* header files. */
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
|
||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" program_mpu_first_task: \n"
|
||||
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r0, [r2] \n" /* r0 = pxCurrentTCB. */
|
||||
" \n"
|
||||
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||
" bic r2, #1 \n" /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */
|
||||
" str r2, [r1] \n" /* Disable MPU. */
|
||||
" \n"
|
||||
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||
" ldr r1, [r0] \n" /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||
" ldr r2, =0xe000edc0 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r1, [r2] \n" /* Program MAIR0. */
|
||||
" \n"
|
||||
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||
" ldr r1, =0xe000ed98 \n" /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" \n"
|
||||
" movs r3, #4 \n" /* r3 = 4. */
|
||||
" str r3, [r1] \n" /* Program RNR = 4. */
|
||||
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||
" movs r3, #8 \n" /* r3 = 8. */
|
||||
" str r3, [r1] \n" /* Program RNR = 8. */
|
||||
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" movs r3, #12 \n" /* r3 = 12. */
|
||||
" str r3, [r1] \n" /* Program RNR = 12. */
|
||||
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||
" \n"
|
||||
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||
" orr r2, #1 \n" /* r2 = r2 | 1 i.e. Set the bit 0 in r2. */
|
||||
" str r2, [r1] \n" /* Enable MPU. */
|
||||
" dsb \n" /* Force memory writes before continuing. */
|
||||
" \n"
|
||||
" restore_context_first_task: \n"
|
||||
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r0, [r2] \n" /* r0 = pxCurrentTCB.*/
|
||||
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
|
||||
" \n"
|
||||
" restore_special_regs_first_task: \n"
|
||||
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
|
||||
" msr psp, r2 \n"
|
||||
" msr psplim, r3 \n"
|
||||
" msr control, r4 \n"
|
||||
" \n"
|
||||
" restore_general_regs_first_task: \n"
|
||||
" ldmdb r1!, {r4-r11} \n" /* r4-r11 contain hardware saved context. */
|
||||
" stmia r2!, {r4-r11} \n" /* Copy the hardware saved context on the task stack. */
|
||||
" ldmdb r1!, {r4-r11} \n" /* r4-r11 restored. */
|
||||
" \n"
|
||||
" restore_context_done_first_task: \n"
|
||||
" str r1, [r0] \n" /* Save the location where the context should be saved next as the first member of TCB. */
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n" /* Ensure that interrupts are enabled when the first task starts. */
|
||||
" bx lr \n"
|
||||
);
|
||||
}
|
||||
|
||||
#else /* configENABLE_MPU */
|
||||
|
||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
#if ( configNUMBER_OF_CORES == 1)
|
||||
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
|
||||
#else /* if ( configNUMBER_OF_CORES == 1) */
|
||||
" adr r1, ulAsmLocals \n" /* Get the location of the current TCB for the current core. */
|
||||
" ldmia r1!, {r2, r3} \n"
|
||||
" ldr r2, [r2] \n" /* r2 = Core number */
|
||||
" ldr r1, [r3, r2, LSL #2] \n" /* r1 = pxCurrentTCBs[get_core_num()] */
|
||||
#endif /* if ( configNUMBER_OF_CORES == 1) */
|
||||
" ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
" ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||
" msr psplim, r1 \n" /* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n" /* r1 = 2. */
|
||||
" msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n" /* Discard everything up to r0. */
|
||||
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n" /* Ensure that interrupts are enabled when the first task starts. */
|
||||
" bx r2 \n" /* Finally, branch to EXC_RETURN. */
|
||||
#if ( configNUMBER_OF_CORES != 1 )
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"ulAsmLocals: \n"
|
||||
" .word %c0 \n" /* SIO */
|
||||
" .word pxCurrentTCBs \n"
|
||||
#endif /* if ( configNUMBER_OF_CORES > 1 ) */
|
||||
:: "i" (SIO_BASE)
|
||||
);
|
||||
}
|
||||
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||
" tst r0, #1 \n" /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||
" ite ne \n"
|
||||
" movne r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" moveq r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n" /* Return. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n" /* Read the CONTROL register. */
|
||||
" bic r0, #1 \n" /* Clear the bit 0. */
|
||||
" msr control, r0 \n" /* Write back the new CONTROL value. */
|
||||
" bx lr \n" /* Return to the caller. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n" /* r0 = CONTROL. */
|
||||
" orr r0, #1 \n" /* r0 = r0 | 1. */
|
||||
" msr control, r0 \n" /* CONTROL = r0. */
|
||||
" bx lr \n" /* Return to the caller. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
/* Note this config is not really supported; it breaks running on core 1 */
|
||||
#if configRESET_STACK_POINTER
|
||||
" ldr r0, =0xe000ed08 \n" /* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n" /* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n" /* Set the MSP back to the start of the stack. */
|
||||
#endif
|
||||
" cpsie i \n" /* Globally enable interrupts. */
|
||||
" cpsie f \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n" /* System call to start the first task. */
|
||||
" nop \n"
|
||||
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, basepri \n" /* r0 = basepri. Return original basepri value. */
|
||||
" mov r1, %0 \n" /* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" msr basepri, r1 \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n" /* Return. */
|
||||
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" msr basepri, r0 \n" /* basepri = ulMask. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n" /* Return. */
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
|
||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r0, [r2] \n" /* r0 = pxCurrentTCB. */
|
||||
" ldr r1, [r0] \n" /* r1 = Location in TCB where the context should be saved. */
|
||||
" mrs r2, psp \n" /* r2 = PSP. */
|
||||
" \n"
|
||||
" save_general_regs: \n"
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
" add r2, r2, #0x20 \n" /* Move r2 to location where s0 is saved. */
|
||||
" tst lr, #0x10 \n"
|
||||
" ittt eq \n"
|
||||
" vstmiaeq r1!, {s16-s31} \n" /* Store s16-s31. */
|
||||
" vldmiaeq r2, {s0-s16} \n" /* Copy hardware saved FP context into s0-s16. */
|
||||
" vstmiaeq r1!, {s0-s16} \n" /* Store hardware saved FP context. */
|
||||
" sub r2, r2, #0x20 \n" /* Set r2 back to the location of hardware saved context. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
" \n"
|
||||
" stmia r1!, {r4-r11} \n" /* Store r4-r11. */
|
||||
" ldmia r2, {r4-r11} \n" /* Copy the hardware saved context into r4-r11. */
|
||||
" stmia r1!, {r4-r11} \n" /* Store the hardware saved context. */
|
||||
" \n"
|
||||
" save_special_regs: \n"
|
||||
" mrs r3, psplim \n" /* r3 = PSPLIM. */
|
||||
" mrs r4, control \n" /* r4 = CONTROL. */
|
||||
" stmia r1!, {r2-r4, lr} \n" /* Store original PSP (after hardware has saved context), PSPLIM, CONTROL and LR. */
|
||||
" str r1, [r0] \n" /* Save the location from where the context should be restored as the first member of TCB. */
|
||||
" \n"
|
||||
" select_next_task: \n"
|
||||
" mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
|
||||
" msr basepri, r0 \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" mov r0, #0 \n" /* r0 = 0. */
|
||||
" msr basepri, r0 \n" /* Enable interrupts. */
|
||||
" \n"
|
||||
" program_mpu: \n"
|
||||
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r0, [r2] \n" /* r0 = pxCurrentTCB. */
|
||||
" \n"
|
||||
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||
" bic r2, #1 \n" /* r2 = r2 & ~1 i.e. Clear the bit 0 in r2. */
|
||||
" str r2, [r1] \n" /* Disable MPU. */
|
||||
" \n"
|
||||
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to MAIR0 in TCB. */
|
||||
" ldr r1, [r0] \n" /* r1 = *r0 i.e. r1 = MAIR0. */
|
||||
" ldr r2, =0xe000edc0 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r1, [r2] \n" /* Program MAIR0. */
|
||||
" \n"
|
||||
" adds r0, #4 \n" /* r0 = r0 + 4. r0 now points to first RBAR in TCB. */
|
||||
" ldr r1, =0xe000ed98 \n" /* r1 = 0xe000ed98 [Location of RNR]. */
|
||||
" ldr r2, =0xe000ed9c \n" /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" \n"
|
||||
" movs r3, #4 \n" /* r3 = 4. */
|
||||
" str r3, [r1] \n" /* Program RNR = 4. */
|
||||
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||
" movs r3, #8 \n" /* r3 = 8. */
|
||||
" str r3, [r1] \n" /* Program RNR = 8. */
|
||||
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" movs r3, #12 \n" /* r3 = 12. */
|
||||
" str r3, [r1] \n" /* Program RNR = 12. */
|
||||
" ldmia r0!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||
" \n"
|
||||
" ldr r1, =0xe000ed94 \n" /* r1 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r2, [r1] \n" /* Read the value of MPU_CTRL. */
|
||||
" orr r2, #1 \n" /* r2 = r2 | 1 i.e. Set the bit 0 in r2. */
|
||||
" str r2, [r1] \n" /* Enable MPU. */
|
||||
" dsb \n" /* Force memory writes before continuing. */
|
||||
" \n"
|
||||
" restore_context: \n"
|
||||
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r0, [r2] \n" /* r0 = pxCurrentTCB.*/
|
||||
" ldr r1, [r0] \n" /* r1 = Location of saved context in TCB. */
|
||||
" \n"
|
||||
" restore_special_regs: \n"
|
||||
" ldmdb r1!, {r2-r4, lr} \n" /* r2 = original PSP, r3 = PSPLIM, r4 = CONTROL, LR restored. */
|
||||
" msr psp, r2 \n"
|
||||
" msr psplim, r3 \n"
|
||||
" msr control, r4 \n"
|
||||
" \n"
|
||||
" restore_general_regs: \n"
|
||||
" ldmdb r1!, {r4-r11} \n" /* r4-r11 contain hardware saved context. */
|
||||
" stmia r2!, {r4-r11} \n" /* Copy the hardware saved context on the task stack. */
|
||||
" ldmdb r1!, {r4-r11} \n" /* r4-r11 restored. */
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
" tst lr, #0x10 \n"
|
||||
" ittt eq \n"
|
||||
" vldmdbeq r1!, {s0-s16} \n" /* s0-s16 contain hardware saved FP context. */
|
||||
" vstmiaeq r2!, {s0-s16} \n" /* Copy hardware saved FP context on the task stack. */
|
||||
" vldmdbeq r1!, {s16-s31} \n" /* Restore s16-s31. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
" \n"
|
||||
" restore_context_done: \n"
|
||||
" str r1, [r0] \n" /* Save the location where the context should be saved next as the first member of TCB. */
|
||||
" bx lr \n"
|
||||
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
}
|
||||
|
||||
#else /* configENABLE_MPU */
|
||||
|
||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, psp \n" /* Read PSP in r1. */
|
||||
" \n"
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
" tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
" it eq \n"
|
||||
" vstmdbeq r1!, {s16-s31} \n" /* Store the additional FP context registers which are not saved automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
" \n"
|
||||
" mrs r2, psplim \n" /* r2 = PSPLIM. */
|
||||
" mov r3, lr \n" /* r3 = LR/EXC_RETURN. */
|
||||
" stmdb r1!, {r2-r11} \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
|
||||
" \n"
|
||||
#if portUSE_DCP_SAVE_RESTORE
|
||||
" mrrc2 p4,#0,r4,r5,c8 \n" /* PXMD r4, r5 */
|
||||
" mrrc2 p4,#0,r6,r7,c9 \n" /* PYMD r6, r7 */
|
||||
" mrrc2 p4,#0,r8,r9,c10 \n" /* REFD r8, r9 */
|
||||
" stmdb r1, {r4-r9} \n" /* Store DCP state on the stack; don't update r1 as we want the stack frame to be normal for smart debuggers */
|
||||
#endif /* portUSE_DIVIDER_SAVE_RESTORE */
|
||||
|
||||
#if ( configNUMBER_OF_CORES == 1)
|
||||
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r3, [r2] \n" /* Read pxCurrentTCB. */
|
||||
#else /* if ( configNUMBER_OF_CORES == 1) */
|
||||
" adr r0, ulAsmLocals2 \n" /* Get the location of the current TCB for the current core. */
|
||||
" ldmia r0!, {r2, r3} \n"
|
||||
" ldr r0, [r2] \n" /* r0 = Core number */
|
||||
" ldr r3, [r3, r0, LSL #2] \n" /* r3 = pxCurrentTCBs[get_core_num()] */
|
||||
#endif /* if ( configNUMBER_OF_CORES == 1) */
|
||||
" str r1, [r3] \n" /* Save the new top of stack in TCB. */
|
||||
" \n"
|
||||
" mov r1, %0 \n" /* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
|
||||
" msr basepri, r1 \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
/* Note: in configNUMBER_OF_CORES != 1 r0 holds core number from above */
|
||||
" bl vTaskSwitchContext \n"
|
||||
" mov r0, #0 \n" /* r0 = 0. */
|
||||
" msr basepri, r0 \n" /* Enable interrupts. */
|
||||
" \n"
|
||||
#if ( configNUMBER_OF_CORES == 1)
|
||||
" ldr r2, =pxCurrentTCB \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n" /* Read pxCurrentTCB. */
|
||||
#else /* if ( configNUMBER_OF_CORES == 1) */
|
||||
" adr r1, ulAsmLocals2 \n" /* Get the location of the current TCB for the current core. */
|
||||
" ldmia r1!, {r2, r3} \n"
|
||||
" ldr r2, [r2] \n" /* r2 = Core number */
|
||||
" ldr r1, [r3, r2, LSL #2] \n" /* r1 = pxCurrentTCBs[get_core_num()] */
|
||||
#endif /* if ( configNUMBER_OF_CORES == 1) */
|
||||
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||
" \n"
|
||||
#if portUSE_DCP_SAVE_RESTORE
|
||||
" subs r0, r0, #24 \n" /* the DCP state is below the stored stack pointer */
|
||||
" ldmia r0!, {r4-r9} \n" /* Read DCP state from stack */
|
||||
" mcrr p4,#0,r4,r5,c0 \n" /* WXMD r4, r5 */
|
||||
" mcrr p4,#0,r6,r7,c1 \n" /* WYMD r6, r7 */
|
||||
" mcrr p4,#0,r8,r9,c2 \n" /* WEFD r8, r9 */
|
||||
#endif /* portUSE_DIVIDER_SAVE_RESTORE */
|
||||
|
||||
" ldmia r0!, {r2-r11} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
|
||||
" \n"
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
" tst r3, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
" it eq \n"
|
||||
" vldmiaeq r0!, {s16-s31} \n" /* Restore the additional FP context registers which are not restored automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
" \n"
|
||||
" msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */
|
||||
" msr psp, r0 \n" /* Remember the new top of stack for the task. */
|
||||
" bx r3 \n"
|
||||
#if ( configNUMBER_OF_CORES != 1 )
|
||||
" .align 4 \n"
|
||||
"ulAsmLocals2: \n"
|
||||
" .word %c1 \n" /* SIO */
|
||||
" .word pxCurrentTCBs \n"
|
||||
#endif /* #if ( configNUMBER_OF_CORES > 1 ) */
|
||||
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ), "i" ( SIO_BASE )
|
||||
);
|
||||
}
|
||||
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
|
||||
|
||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
".syntax unified \n"
|
||||
".extern vPortSVCHandler_C \n"
|
||||
".extern vSystemCallEnter \n"
|
||||
".extern vSystemCallExit \n"
|
||||
" \n"
|
||||
"tst lr, #4 \n"
|
||||
"ite eq \n"
|
||||
"mrseq r0, msp \n"
|
||||
"mrsne r0, psp \n"
|
||||
" \n"
|
||||
"ldr r1, [r0, #24] \n"
|
||||
"ldrb r2, [r1, #-2] \n"
|
||||
"cmp r2, %0 \n"
|
||||
"blt syscall_enter \n"
|
||||
"cmp r2, %1 \n"
|
||||
"beq syscall_exit \n"
|
||||
"b vPortSVCHandler_C \n"
|
||||
" \n"
|
||||
"syscall_enter: \n"
|
||||
" mov r1, lr \n"
|
||||
" b vSystemCallEnter \n"
|
||||
" \n"
|
||||
"syscall_exit: \n"
|
||||
" mov r1, lr \n"
|
||||
" b vSystemCallExit \n"
|
||||
" \n"
|
||||
: /* No outputs. */
|
||||
: "i" ( NUM_SYSTEM_CALLS ), "i" ( portSVC_SYSTEM_CALL_EXIT )
|
||||
: "r0", "r1", "r2", "memory"
|
||||
);
|
||||
}
|
||||
|
||||
#else /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
|
||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" tst lr, #4 \n"
|
||||
" ite eq \n"
|
||||
" mrseq r0, msp \n"
|
||||
" mrsne r0, psp \n"
|
||||
" ldr r1, =vPortSVCHandler_C \n"
|
||||
" bx r1 \n"
|
||||
);
|
||||
}
|
||||
|
||||
#endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
Vendored
+114
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PORT_ASM_H__
|
||||
#define __PORT_ASM_H__
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* MPU wrappers includes. */
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/**
|
||||
* @brief Restore the context of the first task so that the first task starts
|
||||
* executing.
|
||||
*/
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* @note This is a privileged function and should only be called from the kenrel
|
||||
* code.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vResetPrivilege( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Starts the first task.
|
||||
*/
|
||||
void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Disables interrupts.
|
||||
*/
|
||||
uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enables interrupts.
|
||||
*/
|
||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief PendSV Exception handler.
|
||||
*/
|
||||
void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SVC Handler.
|
||||
*/
|
||||
void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Allocate a Secure context for the calling task.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the stack to be allocated on the
|
||||
* secure side for the calling task.
|
||||
*/
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Free the task's secure context.
|
||||
*
|
||||
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
|
||||
*/
|
||||
void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* __PORT_ASM_H__ */
|
||||
Vendored
+230
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT AND BSD-3-Clause
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#include "pico.h"
|
||||
#include "hardware/sync.h"
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M33"
|
||||
#define portHAS_ARMV8M_MAIN_EXTENSION 1
|
||||
#define portARMV8M_MINOR_VERSION 0
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* ARMv8-M common port configurations. */
|
||||
#include "portmacrocommon.h"
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifndef configENABLE_MVE
|
||||
#define configENABLE_MVE 0
|
||||
#elif( configENABLE_MVE != 0 )
|
||||
#error configENABLE_MVE must be left undefined, or defined to 0 for the Cortex-M33.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portSET_INTERRUPT_MASK() ulSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK(state) vClearInterruptMask( state )
|
||||
#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK()
|
||||
#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK( 0 )
|
||||
|
||||
#if ( configNUMBER_OF_CORES == 1 )
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#else /* ( configNUMBER_OF_CORES == 1 ) */
|
||||
/* SMP enabled */
|
||||
#undef portENTER_CRITICAL
|
||||
#undef portEXIT_CRITICAL
|
||||
|
||||
extern void vTaskEnterCritical( void );
|
||||
extern void vTaskExitCritical( void );
|
||||
extern UBaseType_t vTaskEnterCriticalFromISR( void );
|
||||
extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
|
||||
|
||||
#define portENTER_CRITICAL() vTaskEnterCritical()
|
||||
#define portEXIT_CRITICAL() vTaskExitCritical()
|
||||
#define portENTER_CRITICAL_FROM_ISR() vTaskEnterCriticalFromISR()
|
||||
#define portEXIT_CRITICAL_FROM_ISR( x ) vTaskExitCriticalFromISR( x )
|
||||
#endif /* if ( configNUMBER_OF_CORES != 1 ) */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configUSE_DCP_SAVE_RESTORE
|
||||
#define portUSE_DCP_SAVE_RESTORE configUSE_DCP_SAVE_RESTORE
|
||||
#elif (LIB_PICO_DOUBLE_PICO/* || LIB_PICO_FLOAT_PICO*/) // todo we don't use DCP in float yet
|
||||
#define portUSE_DCP_SAVE_RESTORE 1
|
||||
#endif
|
||||
|
||||
#if portUSE_DCP_SAVE_RESTORE
|
||||
#define portSTACK_LIMIT_PADDING 6
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Exception handlers */
|
||||
#if ( configUSE_DYNAMIC_EXCEPTION_HANDLERS == 0 )
|
||||
/* We only need to override the SDK's weak functions if we want to replace them at compile time */
|
||||
#define SVC_Handler isr_svcall
|
||||
#define PendSV_Handler isr_pendsv
|
||||
#define SysTick_Handler isr_systick
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Multi-core */
|
||||
#define portMAX_CORE_COUNT 2
|
||||
|
||||
/* Check validity of number of cores specified in config */
|
||||
#if ( configNUMBER_OF_CORES < 1 || portMAX_CORE_COUNT < configNUMBER_OF_CORES )
|
||||
#error "Invalid number of cores specified in config!"
|
||||
#endif
|
||||
|
||||
#if ( configTICK_CORE < 0 || configTICK_CORE > configNUMBER_OF_CORES )
|
||||
#error "Invalid tick core specified in config!"
|
||||
#endif
|
||||
/* FreeRTOS core id is always zero based, so always 0 if we're running on only one core */
|
||||
#if configNUMBER_OF_CORES != 1
|
||||
#define portGET_CORE_ID() get_core_num()
|
||||
#else
|
||||
#define portGET_CORE_ID() 0
|
||||
#endif
|
||||
|
||||
#define portCHECK_IF_IN_ISR() \
|
||||
( { \
|
||||
uint32_t ulIPSR; \
|
||||
__asm volatile ( "mrs %0, IPSR" : "=r" ( ulIPSR )::); \
|
||||
( ( uint8_t ) ulIPSR ) > 0; } )
|
||||
|
||||
void vYieldCore( int xCoreID );
|
||||
#define portYIELD_CORE( a ) vYieldCore( a )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical nesting count management. */
|
||||
#if configNUMBER_OF_CORES == 1
|
||||
#define portGET_CRITICAL_NESTING_COUNT( xCoreID ) ulCriticalNesting
|
||||
#else
|
||||
extern volatile uint32_t ulCriticalNestings[ configNUMBER_OF_CORES ];
|
||||
#define portGET_CRITICAL_NESTING_COUNT( xCoreID ) ( ulCriticalNestings[ ( xCoreID ) ] )
|
||||
#define portSET_CRITICAL_NESTING_COUNT( xCoreID, x ) ( ulCriticalNestings[ ( xCoreID ) ] = ( x ) )
|
||||
#define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID ) ( ulCriticalNestings[ ( xCoreID ) ]++ )
|
||||
#define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ) ( ulCriticalNestings[ ( xCoreID ) ]-- )
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
#define portCRITICAL_NESTING_IN_TCB 0
|
||||
|
||||
#define portRTOS_SPINLOCK_COUNT 2
|
||||
|
||||
/* Note this is a single method with uxAcquire parameter since we have
|
||||
* static vars, the method is always called with a compile time constant for
|
||||
* uxAcquire, and the compiler should do the right thing! */
|
||||
static inline void vPortRecursiveLock( BaseType_t xCoreID,
|
||||
uint32_t ulLockNum,
|
||||
spin_lock_t * pxSpinLock,
|
||||
BaseType_t uxAcquire )
|
||||
{
|
||||
static volatile uint8_t ucOwnedByCore[ portMAX_CORE_COUNT ][portRTOS_SPINLOCK_COUNT];
|
||||
static volatile uint8_t ucRecursionCountByLock[ portRTOS_SPINLOCK_COUNT ];
|
||||
|
||||
configASSERT( ulLockNum < portRTOS_SPINLOCK_COUNT );
|
||||
|
||||
if( uxAcquire )
|
||||
{
|
||||
if (!spin_try_lock_unsafe(pxSpinLock)) {
|
||||
if( ucOwnedByCore[ xCoreID ][ ulLockNum ] )
|
||||
{
|
||||
configASSERT( ucRecursionCountByLock[ ulLockNum ] != 255u );
|
||||
ucRecursionCountByLock[ ulLockNum ]++;
|
||||
return;
|
||||
}
|
||||
spin_lock_unsafe_blocking(pxSpinLock);
|
||||
}
|
||||
configASSERT( ucRecursionCountByLock[ ulLockNum ] == 0 );
|
||||
ucRecursionCountByLock[ ulLockNum ] = 1;
|
||||
ucOwnedByCore[ xCoreID ][ ulLockNum ] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
configASSERT( ( ucOwnedByCore[ xCoreID ] [ulLockNum ] ) != 0 );
|
||||
configASSERT( ucRecursionCountByLock[ ulLockNum ] != 0 );
|
||||
|
||||
if( !--ucRecursionCountByLock[ ulLockNum ] )
|
||||
{
|
||||
ucOwnedByCore[ xCoreID ] [ ulLockNum ] = 0;
|
||||
spin_unlock_unsafe(pxSpinLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if ( configNUMBER_OF_CORES == 1 )
|
||||
#define portGET_ISR_LOCK( xCoreID )
|
||||
#define portRELEASE_ISR_LOCK( xCoreID )
|
||||
#define portGET_TASK_LOCK( xCoreID )
|
||||
#define portRELEASE_TASK_LOCK( xCoreID )
|
||||
#else /* configNUMBER_OF_CORES == 1 */
|
||||
#define portGET_ISR_LOCK( xCoreID ) vPortRecursiveLock( ( xCoreID ), 0, spin_lock_instance( configSMP_SPINLOCK_0 ), pdTRUE )
|
||||
#define portRELEASE_ISR_LOCK( xCoreID ) vPortRecursiveLock( ( xCoreID ), 0, spin_lock_instance( configSMP_SPINLOCK_0 ), pdFALSE )
|
||||
#define portGET_TASK_LOCK( xCoreID ) vPortRecursiveLock( ( xCoreID ), 1, spin_lock_instance( configSMP_SPINLOCK_1 ), pdTRUE )
|
||||
#define portRELEASE_TASK_LOCK( xCoreID ) vPortRecursiveLock( ( xCoreID ), 1, spin_lock_instance( configSMP_SPINLOCK_1 ), pdFALSE )
|
||||
#endif /* configNUMBER_OF_CORES == 1 */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
+516
@@ -0,0 +1,516 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACROCOMMON_H
|
||||
#define PORTMACROCOMMON_H
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef configENABLE_FPU
|
||||
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
#ifndef configENABLE_MPU
|
||||
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#ifndef configENABLE_TRUSTZONE
|
||||
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Type definitions.
|
||||
*/
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 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
|
||||
#else
|
||||
#error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP()
|
||||
#define portINLINE __inline
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__( ( always_inline ) )
|
||||
#endif
|
||||
#define portHAS_STACK_OVERFLOW_CHECKING 1
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Extern declarations.
|
||||
*/
|
||||
extern BaseType_t xPortIsInsideInterrupt( void );
|
||||
|
||||
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
|
||||
#if ( configENABLE_TRUSTZONE == 1 )
|
||||
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
|
||||
extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
|
||||
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief MPU specific constants.
|
||||
*/
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
#else
|
||||
#define portPRIVILEGE_BIT ( 0x0UL )
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* MPU settings that can be overriden in FreeRTOSConfig.h. */
|
||||
#ifndef configTOTAL_MPU_REGIONS
|
||||
/* Define to 8 for backward compatibility. */
|
||||
#define configTOTAL_MPU_REGIONS ( 8UL )
|
||||
#endif
|
||||
|
||||
/* MPU regions. */
|
||||
#define portPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
|
||||
/* Device memory attributes used in MPU_MAIR registers.
|
||||
*
|
||||
* 8-bit values encoded as follows:
|
||||
* Bit[7:4] - 0000 - Device Memory
|
||||
* Bit[3:2] - 00 --> Device-nGnRnE
|
||||
* 01 --> Device-nGnRE
|
||||
* 10 --> Device-nGRE
|
||||
* 11 --> Device-GRE
|
||||
* Bit[1:0] - 00, Reserved.
|
||||
*/
|
||||
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
|
||||
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
|
||||
|
||||
/* Normal memory attributes used in MPU_MAIR registers. */
|
||||
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
|
||||
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
|
||||
|
||||
/* Attributes used in MPU_RBAR registers. */
|
||||
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
|
||||
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
|
||||
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
|
||||
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
|
||||
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
|
||||
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
|
||||
/**
|
||||
* @brief Settings to define an MPU region.
|
||||
*/
|
||||
typedef struct MPURegionSettings
|
||||
{
|
||||
uint32_t ulRBAR; /**< RBAR for the region. */
|
||||
uint32_t ulRLAR; /**< RLAR for the region. */
|
||||
} MPURegionSettings_t;
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
|
||||
#ifndef configSYSTEM_CALL_STACK_SIZE
|
||||
#error configSYSTEM_CALL_STACK_SIZE must be defined to the desired size of the system call stack in words for using MPU wrappers v2.
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief System call stack.
|
||||
*/
|
||||
typedef struct SYSTEM_CALL_STACK_INFO
|
||||
{
|
||||
uint32_t ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE ];
|
||||
uint32_t * pulSystemCallStack;
|
||||
uint32_t * pulSystemCallStackLimit;
|
||||
uint32_t * pulTaskStack;
|
||||
uint32_t ulLinkRegisterAtSystemCallEntry;
|
||||
uint32_t ulStackLimitRegisterAtSystemCallEntry;
|
||||
} xSYSTEM_CALL_STACK_INFO;
|
||||
|
||||
#endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
|
||||
|
||||
/**
|
||||
* @brief MPU settings as stored in the TCB.
|
||||
*/
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
|
||||
#if ( configENABLE_TRUSTZONE == 1 )
|
||||
|
||||
/*
|
||||
* +-----------+---------------+----------+-----------------+------------------------------+-----+
|
||||
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | |
|
||||
* | | | | PC, xPSR | CONTROL, EXC_RETURN | |
|
||||
* +-----------+---------------+----------+-----------------+------------------------------+-----+
|
||||
*
|
||||
* <-----------><--------------><---------><----------------><-----------------------------><---->
|
||||
* 16 16 8 8 5 1
|
||||
*/
|
||||
#define MAX_CONTEXT_SIZE 54
|
||||
|
||||
#else /* #if( configENABLE_TRUSTZONE == 1 ) */
|
||||
|
||||
/*
|
||||
* +-----------+---------------+----------+-----------------+----------------------+-----+
|
||||
* | s16-s31 | s0-s15, FPSCR | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | |
|
||||
* | | | | PC, xPSR | EXC_RETURN | |
|
||||
* +-----------+---------------+----------+-----------------+----------------------+-----+
|
||||
*
|
||||
* <-----------><--------------><---------><----------------><---------------------><---->
|
||||
* 16 16 8 8 4 1
|
||||
*/
|
||||
#define MAX_CONTEXT_SIZE 53
|
||||
|
||||
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */
|
||||
|
||||
#else /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
|
||||
|
||||
#if ( configENABLE_TRUSTZONE == 1 )
|
||||
|
||||
/*
|
||||
* +----------+-----------------+------------------------------+-----+
|
||||
* | r4-r11 | r0-r3, r12, LR, | xSecureContext, PSP, PSPLIM, | |
|
||||
* | | PC, xPSR | CONTROL, EXC_RETURN | |
|
||||
* +----------+-----------------+------------------------------+-----+
|
||||
*
|
||||
* <---------><----------------><------------------------------><---->
|
||||
* 8 8 5 1
|
||||
*/
|
||||
#define MAX_CONTEXT_SIZE 22
|
||||
|
||||
#else /* #if( configENABLE_TRUSTZONE == 1 ) */
|
||||
|
||||
/*
|
||||
* +----------+-----------------+----------------------+-----+
|
||||
* | r4-r11 | r0-r3, r12, LR, | PSP, PSPLIM, CONTROL | |
|
||||
* | | PC, xPSR | EXC_RETURN | |
|
||||
* +----------+-----------------+----------------------+-----+
|
||||
*
|
||||
* <---------><----------------><----------------------><---->
|
||||
* 8 8 4 1
|
||||
*/
|
||||
#define MAX_CONTEXT_SIZE 21
|
||||
|
||||
#endif /* #if( configENABLE_TRUSTZONE == 1 ) */
|
||||
|
||||
#endif /* #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
|
||||
|
||||
/* Flags used for xMPU_SETTINGS.ulTaskFlags member. */
|
||||
#define portSTACK_FRAME_HAS_PADDING_FLAG ( 1UL << 0UL )
|
||||
#define portTASK_IS_PRIVILEGED_FLAG ( 1UL << 1UL )
|
||||
|
||||
/* Size of an Access Control List (ACL) entry in bits. */
|
||||
#define portACL_ENTRY_SIZE_BITS ( 32U )
|
||||
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
|
||||
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
|
||||
uint32_t ulContext[ MAX_CONTEXT_SIZE ];
|
||||
uint32_t ulTaskFlags;
|
||||
|
||||
#if ( configUSE_MPU_WRAPPERS_V1 == 0 )
|
||||
xSYSTEM_CALL_STACK_INFO xSystemCallStackInfo;
|
||||
#if ( configENABLE_ACCESS_CONTROL_LIST == 1 )
|
||||
uint32_t ulAccessControlList[ ( configPROTECTED_KERNEL_OBJECT_POOL_SIZE / portACL_ENTRY_SIZE_BITS ) + 1 ];
|
||||
#endif
|
||||
#endif
|
||||
} xMPU_SETTINGS;
|
||||
|
||||
#endif /* configENABLE_MPU == 1 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Validate priority of ISRs that are allowed to call FreeRTOS
|
||||
* system calls.
|
||||
*/
|
||||
#ifdef configASSERT
|
||||
#if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 )
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief SVC numbers.
|
||||
*/
|
||||
#define portSVC_ALLOCATE_SECURE_CONTEXT 100
|
||||
#define portSVC_FREE_SECURE_CONTEXT 101
|
||||
#define portSVC_START_SCHEDULER 102
|
||||
#define portSVC_RAISE_PRIVILEGE 103
|
||||
#define portSVC_SYSTEM_CALL_EXIT 104
|
||||
#define portSVC_YIELD 105
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Scheduler utilities.
|
||||
*/
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
#define portYIELD() __asm volatile ( "svc %0" ::"i" ( portSVC_YIELD ) : "memory" )
|
||||
#define portYIELD_WITHIN_API() vPortYield()
|
||||
#else
|
||||
#define portYIELD() vPortYield()
|
||||
#define portYIELD_WITHIN_API() vPortYield()
|
||||
#endif
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
|
||||
do \
|
||||
{ \
|
||||
if( xSwitchRequired ) \
|
||||
{ \
|
||||
traceISR_EXIT_TO_SCHEDULER(); \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
traceISR_EXIT(); \
|
||||
} \
|
||||
} while( 0 )
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Tickless idle/low power functionality.
|
||||
*/
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||
*/
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configENABLE_TRUSTZONE == 1 )
|
||||
|
||||
/**
|
||||
* @brief Allocate a secure context for the task.
|
||||
*
|
||||
* Tasks are not created with a secure context. Any task that is going to call
|
||||
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
|
||||
* secure context before it calls any secure function.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
|
||||
*/
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
|
||||
|
||||
/**
|
||||
* @brief Called when a task is deleted to delete the task's secure context,
|
||||
* if it has one.
|
||||
*
|
||||
* @param[in] pxTCB The TCB of the task being deleted.
|
||||
*/
|
||||
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*
|
||||
* The SVC handler checks that the SVC was raised from a system call and only
|
||||
* then it raises the privilege. If this is called from any other place,
|
||||
* the privilege is not raised.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
#else
|
||||
#define portIS_PRIVILEGED()
|
||||
#define portRAISE_PRIVILEGE()
|
||||
#define portRESET_PRIVILEGE()
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
|
||||
extern BaseType_t xPortIsTaskPrivileged( void );
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the calling task is privileged.
|
||||
*
|
||||
* @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
|
||||
*/
|
||||
#define portIS_TASK_PRIVILEGED() xPortIsTaskPrivileged()
|
||||
|
||||
#endif /* configENABLE_MPU == 1 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Barriers.
|
||||
*/
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
* based on whether or not Mainline extension is implemented. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 && !( configNUMBER_OF_CORES > 1 ))
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#else
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
|
||||
#endif
|
||||
#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/**
|
||||
* @brief Port-optimised task selection.
|
||||
*/
|
||||
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
|
||||
|
||||
/**
|
||||
* @brief Count the number of leading zeros in a 32-bit value.
|
||||
*/
|
||||
static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint32_t ulReturn;
|
||||
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" );
|
||||
|
||||
return ulReturn;
|
||||
}
|
||||
|
||||
/* 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 different priorities as tasks that share a priority will time slice.
|
||||
#endif
|
||||
|
||||
#if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 )
|
||||
#error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined.
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 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 ) )
|
||||
|
||||
/**
|
||||
* @brief Get the priority of the highest-priority task that is ready to execute.
|
||||
*/
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* PORTMACROCOMMON_H */
|
||||
FreeRTOS/portable/ThirdParty/Community-Supported-Ports/GCC/RP2350_ARM_NTZ/non_secure/rp2040_config.h
Vendored
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT AND BSD-3-Clause
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef RP2040_CONFIG_H
|
||||
#define RP2040_CONFIG_H
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/* configUSE_DYNAMIC_EXCEPTION_HANDLERS == 1 means set the exception handlers dynamically on cores
|
||||
* that need them in case the user has set up distinct vector table offsets per core
|
||||
*/
|
||||
#ifndef configUSE_DYNAMIC_EXCEPTION_HANDLERS
|
||||
#if defined( PICO_NO_RAM_VECTOR_TABLE ) && ( PICO_NO_RAM_VECTOR_TABLE == 1 )
|
||||
#define configUSE_DYNAMIC_EXCEPTION_HANDLERS 0
|
||||
#else
|
||||
#define configUSE_DYNAMIC_EXCEPTION_HANDLERS 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* configSUPPORT_PICO_SYNC_INTEROP == 1 means that SDK pico_sync
|
||||
* sem/mutex/queue etc. will work correctly when called from FreeRTOS tasks
|
||||
*/
|
||||
#ifndef configSUPPORT_PICO_SYNC_INTEROP
|
||||
#if LIB_PICO_SYNC
|
||||
#define configSUPPORT_PICO_SYNC_INTEROP 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* configSUPPORT_PICO_SYNC_INTEROP == 1 means that SDK pico_time
|
||||
* sleep_ms/sleep_us/sleep_until will work correctly when called from FreeRTOS
|
||||
* tasks, and will actually block at the FreeRTOS level
|
||||
*/
|
||||
#ifndef configSUPPORT_PICO_TIME_INTEROP
|
||||
#if LIB_PICO_TIME
|
||||
#define configSUPPORT_PICO_TIME_INTEROP 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
|
||||
/* configTICK_CORE indicates which core should handle the SysTick
|
||||
* interrupts */
|
||||
#ifndef configTICK_CORE
|
||||
#define configTICK_CORE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (configNUMBER_OF_CORES != 1)
|
||||
/* This SMP port requires two spin locks, which are claimed from the SDK.
|
||||
* the spin lock numbers to be used are defined statically and defaulted here
|
||||
* to the values nominally set aside for RTOS by the SDK */
|
||||
#ifndef configSMP_SPINLOCK_0
|
||||
#define configSMP_SPINLOCK_0 PICO_SPINLOCK_ID_OS1
|
||||
#endif
|
||||
|
||||
#ifndef configSMP_SPINLOCK_1
|
||||
#define configSMP_SPINLOCK_1 PICO_SPINLOCK_ID_OS2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* ifndef RP2040_CONFIG_H */
|
||||
Vendored
+66
@@ -0,0 +1,66 @@
|
||||
# Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
|
||||
|
||||
# This can be dropped into an external project to help locate this SDK
|
||||
# It should be include()ed prior to project()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
|
||||
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
|
||||
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
|
||||
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
|
||||
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
|
||||
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
|
||||
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
|
||||
|
||||
if (NOT PICO_SDK_PATH)
|
||||
if (PICO_SDK_FETCH_FROM_GIT)
|
||||
include(FetchContent)
|
||||
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
|
||||
if (PICO_SDK_FETCH_FROM_GIT_PATH)
|
||||
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||
endif ()
|
||||
FetchContent_Declare(
|
||||
pico_sdk
|
||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||
GIT_TAG master
|
||||
)
|
||||
if (NOT pico_sdk)
|
||||
message("Downloading Raspberry Pi Pico SDK")
|
||||
FetchContent_Populate(pico_sdk)
|
||||
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
|
||||
endif ()
|
||||
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
||||
else ()
|
||||
message(FATAL_ERROR
|
||||
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||
if (NOT EXISTS ${PICO_SDK_PATH})
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
|
||||
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
|
||||
|
||||
include(${PICO_SDK_INIT_CMAKE_FILE})
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
if (NOT TARGET _FreeRTOS_kernel_inclusion_marker)
|
||||
add_library(_FreeRTOS_kernel_inclusion_marker INTERFACE)
|
||||
|
||||
# Pull in PICO SDK (must be before project)
|
||||
include(pico_sdk_import.cmake)
|
||||
if (PICO_SDK_VERSION_STRING VERSION_LESS "2.0.0")
|
||||
message(FATAL_ERROR "Require at least Raspberry Pi Pico SDK version 2.0.0")
|
||||
endif()
|
||||
|
||||
if (NOT FREERTOS_KERNEL_PATH)
|
||||
get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/../../../.. REALPATH)
|
||||
endif ()
|
||||
|
||||
message(DEBUG "FREERTOS_KERNEL_PATH is ${FREERTOS_KERNEL_PATH}")
|
||||
project(FreeRTOS-Kernel C CXX)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
pico_is_top_level_project(FREERTOS_KERNEL_TOP_LEVEL_PROJECT)
|
||||
|
||||
# if the SDK has already been initialized, then just add our libraries now - this allows
|
||||
# this FreeRTOS port to just be added as a sub-directory or include within another project, rather than
|
||||
# having to include it at the top level before pico_sdk_init()
|
||||
if (TARGET _pico_sdk_inclusion_marker)
|
||||
if (PICO_SDK_VERSION_STRING VERSION_LESS "1.3.2")
|
||||
message(FATAL_ERROR "Require at least Raspberry Pi Pico SDK version 1.3.2 to include FreeRTOS after pico_sdk_init()")
|
||||
endif()
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/library.cmake)
|
||||
else()
|
||||
# The real work gets done in library.cmake which is called at the end of pico_sdk_init
|
||||
list(APPEND PICO_SDK_POST_LIST_FILES ${CMAKE_CURRENT_LIST_DIR}/library.cmake)
|
||||
if (PICO_SDK_VERSION_STRING VERSION_LESS "1.3.2")
|
||||
# We need to inject the following header file into ALL SDK files (which we do via the config header)
|
||||
list(APPEND PICO_CONFIG_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/include/freertos_sdk_config.h)
|
||||
endif()
|
||||
|
||||
if (FREERTOS_KERNEL_TOP_LEVEL_PROJECT)
|
||||
message("FreeRTOS: initialize SDK since we're the top-level")
|
||||
# Initialize the SDK
|
||||
pico_sdk_init()
|
||||
else()
|
||||
set(FREERTOS_KERNEL_PATH ${FREERTOS_KERNEL_PATH} PARENT_SCOPE)
|
||||
set(PICO_CONFIG_HEADER_FILES ${PICO_CONFIG_HEADER_FILES} PARENT_SCOPE)
|
||||
set(PICO_SDK_POST_LIST_FILES ${PICO_SDK_POST_LIST_FILES} PARENT_SCOPE)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
[{000214A0-0000-0000-C000-000000000046}]
|
||||
Prop3=19,11
|
||||
[InternetShortcut]
|
||||
IDList=
|
||||
URL=https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
# This is a copy of <FREERTOS_KERNEL_PATH>/portable/ThirdParty/GCC/RP2040/FREERTOS_KERNEL_import.cmake
|
||||
|
||||
# This can be dropped into an external project to help locate the FreeRTOS kernel
|
||||
# It should be include()ed prior to project(). Alternatively this file may
|
||||
# or the CMakeLists.txt in this directory may be included or added via add_subdirectory
|
||||
# respectively.
|
||||
|
||||
if (DEFINED ENV{FREERTOS_KERNEL_PATH} AND (NOT FREERTOS_KERNEL_PATH))
|
||||
set(FREERTOS_KERNEL_PATH $ENV{FREERTOS_KERNEL_PATH})
|
||||
message("Using FREERTOS_KERNEL_PATH from environment ('${FREERTOS_KERNEL_PATH}')")
|
||||
endif ()
|
||||
|
||||
# first pass we look in old tree; second pass we look in new tree
|
||||
foreach(SEARCH_PASS RANGE 0 1)
|
||||
if (SEARCH_PASS)
|
||||
# ports may be moving to submodule in the future
|
||||
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "portable/ThirdParty/Community-Supported-Ports/GCC")
|
||||
set(FREERTOS_KERNEL_RP2040_BACK_PATH "../../../../..")
|
||||
else()
|
||||
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "portable/ThirdParty/GCC")
|
||||
set(FREERTOS_KERNEL_RP2040_BACK_PATH "../../../..")
|
||||
endif()
|
||||
|
||||
if(PICO_PLATFORM STREQUAL "rp2040")
|
||||
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2040")
|
||||
else()
|
||||
if (PICO_PLATFORM STREQUAL "rp2350-riscv")
|
||||
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2350_RISC-V")
|
||||
else()
|
||||
set(FREERTOS_KERNEL_RP2040_RELATIVE_PATH "${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/RP2350_ARM_NTZ")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT FREERTOS_KERNEL_PATH)
|
||||
# check if we are inside the FreeRTOS kernel tree (i.e. this file has been included directly)
|
||||
get_filename_component(_ACTUAL_PATH ${CMAKE_CURRENT_LIST_DIR} REALPATH)
|
||||
get_filename_component(_POSSIBLE_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} REALPATH)
|
||||
if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH)
|
||||
get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH)
|
||||
endif()
|
||||
if (_ACTUAL_PATH STREQUAL _POSSIBLE_PATH)
|
||||
get_filename_component(FREERTOS_KERNEL_PATH ${CMAKE_CURRENT_LIST_DIR}/${FREERTOS_KERNEL_RP2040_BACK_PATH} REALPATH)
|
||||
message("Setting FREERTOS_KERNEL_PATH to ${FREERTOS_KERNEL_PATH} based on location of FreeRTOS-Kernel-import.cmake")
|
||||
break()
|
||||
elseif (PICO_SDK_PATH AND EXISTS "${PICO_SDK_PATH}/../FreeRTOS-Kernel")
|
||||
set(FREERTOS_KERNEL_PATH ${PICO_SDK_PATH}/../FreeRTOS-Kernel)
|
||||
message("Defaulting FREERTOS_KERNEL_PATH as sibling of PICO_SDK_PATH: ${FREERTOS_KERNEL_PATH}")
|
||||
break()
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if (NOT FREERTOS_KERNEL_PATH)
|
||||
foreach(POSSIBLE_SUFFIX Source FreeRTOS-Kernel FreeRTOS/Source)
|
||||
# check if FreeRTOS-Kernel exists under directory that included us
|
||||
set(SEARCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
get_filename_component(_POSSIBLE_PATH ${SEARCH_ROOT}/${POSSIBLE_SUFFIX} REALPATH)
|
||||
if (EXISTS ${_POSSIBLE_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt)
|
||||
get_filename_component(FREERTOS_KERNEL_PATH ${_POSSIBLE_PATH} REALPATH)
|
||||
message("Setting FREERTOS_KERNEL_PATH to '${FREERTOS_KERNEL_PATH}' found relative to enclosing project")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
if (FREERTOS_KERNEL_PATH)
|
||||
break()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# user must have specified
|
||||
if (FREERTOS_KERNEL_PATH)
|
||||
if (EXISTS "${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}")
|
||||
break()
|
||||
endif()
|
||||
endif()
|
||||
endforeach ()
|
||||
|
||||
if (NOT FREERTOS_KERNEL_PATH)
|
||||
message(FATAL_ERROR "FreeRTOS location was not specified. Please set FREERTOS_KERNEL_PATH.")
|
||||
endif()
|
||||
|
||||
set(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" CACHE PATH "Path to the FreeRTOS Kernel")
|
||||
|
||||
get_filename_component(FREERTOS_KERNEL_PATH "${FREERTOS_KERNEL_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||
if (NOT EXISTS ${FREERTOS_KERNEL_PATH})
|
||||
message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' not found")
|
||||
endif()
|
||||
if (NOT EXISTS ${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}/CMakeLists.txt)
|
||||
message(FATAL_ERROR "Directory '${FREERTOS_KERNEL_PATH}' does not contain a '${PICO_PLATFORM}' port here: ${FREERTOS_KERNEL_RP2040_RELATIVE_PATH}")
|
||||
endif()
|
||||
set(FREERTOS_KERNEL_PATH ${FREERTOS_KERNEL_PATH} CACHE PATH "Path to the FreeRTOS_KERNEL" FORCE)
|
||||
|
||||
add_subdirectory(${FREERTOS_KERNEL_PATH}/${FREERTOS_KERNEL_RP2040_RELATIVE_PATH} FREERTOS_KERNEL)
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
BSD-3-Clause License
|
||||
|
||||
Copyright (c) 2020-2021 Raspberry Pi (Trading) Ltd.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
|
||||
2. 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.
|
||||
|
||||
3. Neither the name of the copyright holder 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 HOLDER 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.
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
## Overview
|
||||
|
||||
This directory provides an SMP FreeRTOS-Kernel port that can be used with the Raspberry Pi Pico SDK on RP2350. It supports:
|
||||
|
||||
* Simple CMake INTERFACE libraries, to provide the FreeRTOS-Kernel and also the individual allocator types, without copying code into the user's project.
|
||||
* Running the FreeRTOS-Kernel and tasks on either core 0 or core 1, or both.
|
||||
* Use of SDK synchronization primitives (such as mutexes, semaphores, queues from pico_sync) between FreeRTOS tasks and code executing on a non FreeRTOS core, or in IRQ handlers.
|
||||
|
||||
Note that whilst this SMP version can be run on just a single (either) core, it is probably
|
||||
more efficient to use the non SMP version in the main FreeRTOS-Kernel branch in that case.
|
||||
|
||||
## Using this port
|
||||
|
||||
You can copy [FreeRTOS_Kernel_import.cmake](FreeRTOS_Kernel_import.cmake) into your project, and
|
||||
add the following in your `CMakeLists.txt`:
|
||||
|
||||
```cmake
|
||||
include(FreeRTOS_Kernel_import.cmake)
|
||||
```
|
||||
|
||||
This will locate the FreeRTOS kernel if it is a direct sub-module of your project, or if you provide the
|
||||
`FREERTOS_KERNEL_PATH` variable in your environment or via `-DFREERTOS_KERNEL_PATH=/path/to/FreeRTOS-Kernel` on the CMake command line.
|
||||
|
||||
**NOTE:** If you are using version 1.3.1 or older of the Raspberry Pi Pico SDK then this line must appear before the
|
||||
`pico_sdk_init()` and will cause FreeRTOS to be included/required in all RP2040 targets in your project. After this SDK
|
||||
version, you can include the FreeRTOS-Kernel support later in your CMake build (possibly in a subdirectory) and the
|
||||
FreeRTOS-Kernel support will only apply to those targets which explicitly include FreeRTOS support.
|
||||
|
||||
As an alternative to the `import` statement above, you can just add this directory directly via thw following (with
|
||||
the same placement restrictions related to the Raspberry Pi Pico SDK version above):
|
||||
|
||||
```cmake
|
||||
add_subdirectory(path/to/this/directory FreeRTOS-Kernel)
|
||||
```
|
||||
## FreeRTOS configuration for Armv8-M
|
||||
|
||||
The following standard FreeRTOS ARM options are required for RP2350"
|
||||
|
||||
These three options must be specified as follows, as only RP2040-like FreeRTOS implementation only is supported currently; running in at a single privilege level in the secure statea.
|
||||
|
||||
```c
|
||||
#define configENABLE_MPU 0
|
||||
#define configENABLE_TRUSTZONE 0
|
||||
#define configRUN_FREERTOS_SECURE_ONLY 1
|
||||
```
|
||||
|
||||
You can set the following to enable save/restore of FPU state (you should set this is you are using floating point operations)
|
||||
|
||||
```c
|
||||
#define configENABLE_FPU 1
|
||||
```
|
||||
|
||||
As of right now this is the only value of configMAX_SYSCALL_INTERRUPT_PRIORITY that has been tested
|
||||
|
||||
```c
|
||||
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 16
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
Some additional `config` options are defined [here](include/rp2040_config.h) which control some low level implementation details.
|
||||
|
||||
## Known Limitations
|
||||
|
||||
- Hazard3 IRQ premption is not currently supported on either core even if only one core is running FreeRTOS
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* The FreeRTOS kernel's RISC-V port is split between the the code that is
|
||||
* common across all currently supported RISC-V chips (implementations of the
|
||||
* RISC-V ISA), and code that tailors the port to a specific RISC-V chip:
|
||||
*
|
||||
* + FreeRTOS\Source\portable\GCC\RISC-V\portASM.S contains the code that
|
||||
* is common to all currently supported RISC-V chips. There is only one
|
||||
* portASM.S file because the same file is built for all RISC-V target chips.
|
||||
*
|
||||
* + Header files called freertos_risc_v_chip_specific_extensions.h contain the
|
||||
* code that tailors the FreeRTOS kernel's RISC-V port to a specific RISC-V
|
||||
* chip. There are multiple freertos_risc_v_chip_specific_extensions.h files
|
||||
* as there are multiple RISC-V chip implementations.
|
||||
*
|
||||
* !!!NOTE!!!
|
||||
* TAKE CARE TO INCLUDE THE CORRECT freertos_risc_v_chip_specific_extensions.h
|
||||
* HEADER FILE FOR THE CHIP IN USE. This is done using the assembler's (not the
|
||||
* compiler's!) include path. For example, if the chip in use includes a core
|
||||
* local interrupter (CLINT) and does not include any chip specific register
|
||||
* extensions then add the path below to the assembler's include path:
|
||||
* FreeRTOS\Source\portable\GCC\RISC-V\chip_specific_extensions\RISCV_MTIME_CLINT_no_extensions
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __FREERTOS_RISC_V_EXTENSIONS_H__
|
||||
#define __FREERTOS_RISC_V_EXTENSIONS_H__
|
||||
|
||||
#define portasmHAS_MTIME 1
|
||||
#define portasmADDITIONAL_CONTEXT_SIZE 0
|
||||
|
||||
.macro portasmSAVE_ADDITIONAL_REGISTERS
|
||||
/* No additional registers to save, so this macro does nothing. */
|
||||
.endm
|
||||
|
||||
.macro portasmRESTORE_ADDITIONAL_REGISTERS
|
||||
/* No additional registers to restore, so this macro does nothing. */
|
||||
.endm
|
||||
|
||||
#endif /* __FREERTOS_RISC_V_EXTENSIONS_H__ */
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef FREERTOS_SDK_CONFIG_H
|
||||
#define FREERTOS_SDK_CONFIG_H
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include "FreeRTOSConfig.h"
|
||||
#include "rp2040_config.h"
|
||||
#ifndef PICO_USE_MALLOC_MUTEX
|
||||
/* malloc needs to be made thread safe */
|
||||
#define PICO_USE_MALLOC_MUTEX 1
|
||||
#endif /* PICO_USE_MALLOC_MUTEX */
|
||||
#if ( configSUPPORT_PICO_SYNC_INTEROP == 1 )
|
||||
/* increase the amount of time it may reasonably take to wake us up */
|
||||
#ifndef PICO_TIME_SLEEP_OVERHEAD_ADJUST_US
|
||||
#define PICO_TIME_SLEEP_OVERHEAD_ADJUST_US 150
|
||||
#endif
|
||||
|
||||
#define lock_owner_id_t uint32_t
|
||||
extern uint32_t ulPortLockGetCurrentOwnerId( void );
|
||||
#define lock_get_caller_owner_id() ulPortLockGetCurrentOwnerId()
|
||||
#define LOCK_INVALID_OWNER_ID ( ( uint32_t ) -1 )
|
||||
|
||||
struct lock_core;
|
||||
#ifndef lock_internal_spin_unlock_with_wait
|
||||
extern void vPortLockInternalSpinUnlockWithWait( struct lock_core * pxLock,
|
||||
uint32_t ulSave );
|
||||
#define lock_internal_spin_unlock_with_wait( lock, save ) vPortLockInternalSpinUnlockWithWait( lock, save )
|
||||
#endif
|
||||
|
||||
#ifndef lock_internal_spin_unlock_with_notify
|
||||
extern void vPortLockInternalSpinUnlockWithNotify( struct lock_core * pxLock,
|
||||
uint32_t save );
|
||||
#define lock_internal_spin_unlock_with_notify( lock, save ) vPortLockInternalSpinUnlockWithNotify( lock, save );
|
||||
#endif
|
||||
|
||||
#ifndef lock_internal_spin_unlock_with_best_effort_wait_or_timeout
|
||||
extern bool xPortLockInternalSpinUnlockWithBestEffortWaitOrTimeout( struct lock_core * pxLock,
|
||||
uint32_t ulSave,
|
||||
absolute_time_t uxUntil );
|
||||
#define lock_internal_spin_unlock_with_best_effort_wait_or_timeout( lock, save, until ) \
|
||||
xPortLockInternalSpinUnlockWithBestEffortWaitOrTimeout( lock, save, until )
|
||||
#endif
|
||||
#endif /* configSUPPORT_PICO_SYNC_INTEROP */
|
||||
|
||||
#if ( configSUPPORT_PICO_TIME_INTEROP == 1 )
|
||||
extern void xPortSyncInternalYieldUntilBefore( absolute_time_t t );
|
||||
#define sync_internal_yield_until_before( t ) xPortSyncInternalYieldUntilBefore( t )
|
||||
#endif /* configSUPPORT_PICO_TIME_INTEROP */
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* ifndef FREERTOS_SDK_CONFIG_H */
|
||||
Vendored
+264
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTCONTEXT_H
|
||||
#define PORTCONTEXT_H
|
||||
|
||||
#include "pico.h"
|
||||
#include "hardware/regs/rvcsr.h"
|
||||
#include "hardware/regs/intctrl.h"
|
||||
|
||||
/*
|
||||
* todo this is currently disabled; as it certainly breaks
|
||||
* the RP2 on_core_zero & on_core_one interrupt tests in FreeRTOS
|
||||
*/
|
||||
#ifndef portcontextALLOW_NESTED_IRQs
|
||||
#define portcontextALLOW_NESTED_IRQs 0
|
||||
#endif
|
||||
|
||||
#if __riscv_xlen == 64
|
||||
#define portWORD_SIZE 8
|
||||
#define store_x sd
|
||||
#define load_x ld
|
||||
#elif __riscv_xlen == 32
|
||||
#define store_x sw
|
||||
#define load_x lw
|
||||
#define portWORD_SIZE 4
|
||||
#else
|
||||
#error Assembler did not define __riscv_xlen
|
||||
#endif
|
||||
|
||||
#include "freertos_risc_v_chip_specific_extensions.h"
|
||||
|
||||
/* Only the standard core registers are stored by default. Any additional
|
||||
* registers must be saved by the portasmSAVE_ADDITIONAL_REGISTERS and
|
||||
* portasmRESTORE_ADDITIONAL_REGISTERS macros - which can be defined in a chip
|
||||
* specific version of freertos_risc_v_chip_specific_extensions.h. See the
|
||||
* notes at the top of portASM.S file. */
|
||||
#ifdef __riscv_32e
|
||||
#define portCONTEXT_SIZE ( 15 * portWORD_SIZE )
|
||||
#define portCRITICAL_NESTING_OFFSET 13
|
||||
#define portMSTATUS_OFFSET 14
|
||||
#else
|
||||
#define portCONTEXT_SIZE ( 31 * portWORD_SIZE )
|
||||
#define portCRITICAL_NESTING_OFFSET 29
|
||||
#define portMSTATUS_OFFSET 30
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* OK this is ugly; we cannot use configNUMBER_OF_CORES because FreeRTOSConfig.h is not required to be ASM includable;
|
||||
* So we have a global pointer that is either to a value 0 for configNUMBER_OF_CORES == 1, or points to the SIO
|
||||
* reg on configNUMBER_OF_CORES == 1
|
||||
*/
|
||||
.extern pxCurrentCoreID
|
||||
/*
|
||||
* Note also we must use our own symbol, because pxCurrentTCB is defined by tasks.c for configNUMBER_OF_CORES == 1
|
||||
* vs pCurrentTCBs for configNUMBER_OF_CORES != 1
|
||||
*/
|
||||
.extern pxCurrentTCBArray
|
||||
.extern xCriticalNestingArray
|
||||
|
||||
.extern xISRStackTop
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
.macro portcontextGET_CORE_ID out_reg
|
||||
load_x \out_reg, pxCurrentCoreID
|
||||
load_x \out_reg, 0 ( \out_reg )
|
||||
.endm
|
||||
|
||||
.macro portcontextGET_CURRENT_TCB_FOR_CORE core_reg, out_reg
|
||||
/* todo wasteful indirections here because we don't have configNUMBER_OF_CORES */
|
||||
la \out_reg, pxCurrentTCBArray
|
||||
load_x \out_reg, 0 ( \out_reg )
|
||||
sh2add \out_reg, \core_reg, \out_reg
|
||||
load_x \out_reg, 0 ( \out_reg )
|
||||
.endm
|
||||
|
||||
.macro portcontextGET_CRITICAL_NESTING_PTR_FOR_CORE core_reg, out_reg
|
||||
load_x \out_reg, xCriticalNestingArray
|
||||
sh2add \out_reg, \core_reg, \out_reg
|
||||
.endm
|
||||
|
||||
.macro portcontextSWITCH_TO_ISR_STACK reg_pISRStackTop, reg_ISRStackTop
|
||||
la \reg_pISRStackTop, SIO_BASE
|
||||
load_x \reg_pISRStackTop, 0 ( \reg_pISRStackTop )
|
||||
la \reg_ISRStackTop, xISRStackTops
|
||||
sh2add \reg_pISRStackTop, \reg_pISRStackTop, \reg_ISRStackTop
|
||||
load_x \reg_ISRStackTop, 0 ( \reg_pISRStackTop )
|
||||
beqz \reg_ISRStackTop, no_isr_stack\@
|
||||
mv sp, \reg_ISRStackTop
|
||||
no_isr_stack\@:
|
||||
.endm
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
.macro portcontextSAVE_CONTEXT_INTERNAL
|
||||
addi sp, sp, -portCONTEXT_SIZE
|
||||
store_x x1, 1 * portWORD_SIZE( sp )
|
||||
store_x x5, 2 * portWORD_SIZE( sp )
|
||||
store_x x6, 3 * portWORD_SIZE( sp )
|
||||
store_x x7, 4 * portWORD_SIZE( sp )
|
||||
store_x x8, 5 * portWORD_SIZE( sp )
|
||||
store_x x9, 6 * portWORD_SIZE( sp )
|
||||
store_x x10, 7 * portWORD_SIZE( sp )
|
||||
store_x x11, 8 * portWORD_SIZE( sp )
|
||||
store_x x12, 9 * portWORD_SIZE( sp )
|
||||
store_x x13, 10 * portWORD_SIZE( sp )
|
||||
store_x x14, 11 * portWORD_SIZE( sp )
|
||||
store_x x15, 12 * portWORD_SIZE( sp )
|
||||
#ifndef __riscv_32e
|
||||
store_x x16, 13 * portWORD_SIZE( sp )
|
||||
store_x x17, 14 * portWORD_SIZE( sp )
|
||||
store_x x18, 15 * portWORD_SIZE( sp )
|
||||
store_x x19, 16 * portWORD_SIZE( sp )
|
||||
store_x x20, 17 * portWORD_SIZE( sp )
|
||||
store_x x21, 18 * portWORD_SIZE( sp )
|
||||
store_x x22, 19 * portWORD_SIZE( sp )
|
||||
store_x x23, 20 * portWORD_SIZE( sp )
|
||||
store_x x24, 21 * portWORD_SIZE( sp )
|
||||
store_x x25, 22 * portWORD_SIZE( sp )
|
||||
store_x x26, 23 * portWORD_SIZE( sp )
|
||||
store_x x27, 24 * portWORD_SIZE( sp )
|
||||
store_x x28, 25 * portWORD_SIZE( sp )
|
||||
store_x x29, 26 * portWORD_SIZE( sp )
|
||||
store_x x30, 27 * portWORD_SIZE( sp )
|
||||
store_x x31, 28 * portWORD_SIZE( sp )
|
||||
#endif /* ifndef __riscv_32e */
|
||||
|
||||
portcontextGET_CORE_ID t1
|
||||
portcontextGET_CRITICAL_NESTING_PTR_FOR_CORE t1, t0
|
||||
load_x t0, 0 ( t0 )
|
||||
store_x t0, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Store the critical nesting value to the stack. */
|
||||
|
||||
|
||||
csrr t0, mstatus /* Required for MPIE bit. */
|
||||
store_x t0, portMSTATUS_OFFSET * portWORD_SIZE( sp )
|
||||
|
||||
|
||||
portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */
|
||||
|
||||
portcontextGET_CORE_ID t1
|
||||
portcontextGET_CURRENT_TCB_FOR_CORE t1, t0
|
||||
store_x sp, 0 ( t0 ) /* Write sp to first TCB member. */
|
||||
|
||||
.endm
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
.macro portcontextSAVE_EXCEPTION_CONTEXT
|
||||
portcontextSAVE_CONTEXT_INTERNAL
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
addi a1, a1, 4 /* Synchronous so update exception return address to the instruction after the instruction that generated the exception. */
|
||||
store_x a1, 0 ( sp ) /* Save updated exception return address. */
|
||||
portcontextSWITCH_TO_ISR_STACK t0, t1
|
||||
.endm
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
.macro portcontextSAVE_INTERRUPT_CONTEXT
|
||||
portcontextSAVE_CONTEXT_INTERNAL
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
store_x a1, 0 ( sp ) /* Asynchronous interrupt so save unmodified exception return address. */
|
||||
portcontextSWITCH_TO_ISR_STACK s10, s11
|
||||
/*
|
||||
* s10 is now pISRStackTop for the current core
|
||||
* s11 is the old value of ISRStackTop
|
||||
* we expect them to remain saved, and we overwrite the
|
||||
* pISRStackTop with zero, so we don't overwrite again if nesting is enabled
|
||||
*/
|
||||
sw zero, 0 (s10)
|
||||
.endm
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
.macro portcontextRESTORE_CONTEXT
|
||||
portcontextGET_CORE_ID t0
|
||||
portcontextGET_CURRENT_TCB_FOR_CORE t0, t1
|
||||
load_x sp, 0 ( t1 ) /* Read sp from first TCB member. */
|
||||
|
||||
/* Load mepc with the address of the instruction in the task to run next. */
|
||||
load_x t0, 0 ( sp )
|
||||
csrw mepc, t0
|
||||
|
||||
/* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
|
||||
portasmRESTORE_ADDITIONAL_REGISTERS
|
||||
|
||||
/* Load mstatus with the interrupt enable bits used by the task. */
|
||||
load_x t0, portMSTATUS_OFFSET * portWORD_SIZE( sp )
|
||||
csrw mstatus, t0 /* Required for MPIE bit. */
|
||||
|
||||
/* Load the address of xCriticalNesting into t1. */
|
||||
portcontextGET_CORE_ID t0
|
||||
portcontextGET_CRITICAL_NESTING_PTR_FOR_CORE t0, t1
|
||||
|
||||
load_x t0, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Obtain xCriticalNesting value for this task from task's stack. */
|
||||
store_x t0, 0 ( t1 ) /* Restore the critical nesting value for this task. */
|
||||
|
||||
load_x x1, 1 * portWORD_SIZE( sp )
|
||||
load_x x5, 2 * portWORD_SIZE( sp )
|
||||
load_x x6, 3 * portWORD_SIZE( sp )
|
||||
load_x x7, 4 * portWORD_SIZE( sp )
|
||||
load_x x8, 5 * portWORD_SIZE( sp )
|
||||
load_x x9, 6 * portWORD_SIZE( sp )
|
||||
load_x x10, 7 * portWORD_SIZE( sp )
|
||||
load_x x11, 8 * portWORD_SIZE( sp )
|
||||
load_x x12, 9 * portWORD_SIZE( sp )
|
||||
load_x x13, 10 * portWORD_SIZE( sp )
|
||||
load_x x14, 11 * portWORD_SIZE( sp )
|
||||
load_x x15, 12 * portWORD_SIZE( sp )
|
||||
#ifndef __riscv_32e
|
||||
load_x x16, 13 * portWORD_SIZE( sp )
|
||||
load_x x17, 14 * portWORD_SIZE( sp )
|
||||
load_x x18, 15 * portWORD_SIZE( sp )
|
||||
load_x x19, 16 * portWORD_SIZE( sp )
|
||||
load_x x20, 17 * portWORD_SIZE( sp )
|
||||
load_x x21, 18 * portWORD_SIZE( sp )
|
||||
load_x x22, 19 * portWORD_SIZE( sp )
|
||||
load_x x23, 20 * portWORD_SIZE( sp )
|
||||
load_x x24, 21 * portWORD_SIZE( sp )
|
||||
load_x x25, 22 * portWORD_SIZE( sp )
|
||||
load_x x26, 23 * portWORD_SIZE( sp )
|
||||
load_x x27, 24 * portWORD_SIZE( sp )
|
||||
load_x x28, 25 * portWORD_SIZE( sp )
|
||||
load_x x29, 26 * portWORD_SIZE( sp )
|
||||
load_x x30, 27 * portWORD_SIZE( sp )
|
||||
load_x x31, 28 * portWORD_SIZE( sp )
|
||||
#endif /* ifndef __riscv_32e */
|
||||
addi sp, sp, portCONTEXT_SIZE
|
||||
|
||||
mret
|
||||
.endm
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
.macro portcontextRESTORE_INTERUUPT_CONTEXT
|
||||
/* restore old ISRStackTop */
|
||||
sw s11, 0 (s10)
|
||||
portcontextRESTORE_CONTEXT
|
||||
.endm
|
||||
|
||||
#endif /* PORTCONTEXT_H */
|
||||
Vendored
+314
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT AND BSD-3-Clause
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#include "pico.h"
|
||||
#include "hardware/sync.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. */
|
||||
#if __riscv_xlen == 64
|
||||
#define portSTACK_TYPE uint64_t
|
||||
#define portBASE_TYPE int64_t
|
||||
#define portUBASE_TYPE uint64_t
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffffffffffUL
|
||||
#define portPOINTER_SIZE_TYPE uint64_t
|
||||
#elif __riscv_xlen == 32
|
||||
#define portSTACK_TYPE uint32_t
|
||||
// todo amy; these cause compilation failure in the RP2040 FreeRTOS examples; need to go look what the "full" tests do on RISC-V
|
||||
//#define portBASE_TYPE int32_t
|
||||
//#define portUBASE_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
#define portUBASE_TYPE unsigned long
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#else /* if __riscv_xlen == 64 */
|
||||
#error "Assembler did not define __riscv_xlen"
|
||||
#endif /* if __riscv_xlen == 64 */
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef portBASE_TYPE BaseType_t;
|
||||
typedef portUBASE_TYPE UBaseType_t;
|
||||
typedef portUBASE_TYPE TickType_t;
|
||||
|
||||
/* Legacy type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
|
||||
/* 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
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#ifdef __riscv_32e
|
||||
#define portBYTE_ALIGNMENT 8 /* RV32E uses RISC-V EABI with reduced stack alignment requirements */
|
||||
#else
|
||||
#define portBYTE_ALIGNMENT 16
|
||||
#endif
|
||||
|
||||
/* Multi-core */
|
||||
#define portMAX_CORE_COUNT 2
|
||||
|
||||
/* Check validity of number of cores specified in config */
|
||||
#if ( configNUMBER_OF_CORES < 1 || portMAX_CORE_COUNT < configNUMBER_OF_CORES )
|
||||
#error "Invalid number of cores specified in config!"
|
||||
#endif
|
||||
|
||||
#if ( configTICK_CORE < 0 || configTICK_CORE > configNUMBER_OF_CORES )
|
||||
#error "Invalid tick core specified in config!"
|
||||
#endif
|
||||
/* FreeRTOS core id is always zero based, so always 0 if we're running on only one core */
|
||||
#if configNUMBER_OF_CORES != 1
|
||||
#define portGET_CORE_ID() get_core_num()
|
||||
#else
|
||||
#define portGET_CORE_ID() 0
|
||||
#endif
|
||||
|
||||
#define portCHECK_IF_IN_ISR() \
|
||||
( { \
|
||||
uint32_t meicontext; \
|
||||
__asm volatile ( "csrr %0, %1" : "=r" ( meicontext ): "i" ( RVCSR_MEICONTEXT_OFFSET ):); \
|
||||
!( meicontext & RVCSR_MEICONTEXT_NOIRQ_BITS ); } )
|
||||
|
||||
void vYieldCore( int xCoreID );
|
||||
#define portYIELD_CORE( a ) vYieldCore( a )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler utilities. */
|
||||
#if configNUMBER_OF_CORES == 1
|
||||
#define portTASK_SWITCH_CONTEXT() vTaskSwitchContext()
|
||||
#else
|
||||
#define portTASK_SWITCH_CONTEXT() vTaskSwitchContext(portGET_CORE_ID())
|
||||
#endif
|
||||
|
||||
#if ( configSUPPORT_PICO_SYNC_INTEROP == 1 )
|
||||
/* extra assertion */
|
||||
extern void vPortYield(void);
|
||||
#define portYIELD() vPortYield();
|
||||
#else
|
||||
#define portYIELD() __asm volatile ( "ecall" );
|
||||
#endif /* configSUPPORT_PICO_SYNC_INTEROP */
|
||||
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
|
||||
do \
|
||||
{ \
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
traceISR_EXIT_TO_SCHEDULER(); \
|
||||
portTASK_SWITCH_CONTEXT(); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
traceISR_EXIT(); \
|
||||
} \
|
||||
} while( 0 )
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portSET_INTERRUPT_MASK() save_and_disable_interrupts()
|
||||
#define portCLEAR_INTERRUPT_MASK(state) restore_interrupts( state )
|
||||
#define portDISABLE_INTERRUPTS() save_and_disable_interrupts()
|
||||
#define portENABLE_INTERRUPTS() restore_interrupts( RVCSR_MIE_MSIE_BITS )
|
||||
|
||||
#if ( configNUMBER_OF_CORES == 1 )
|
||||
extern size_t xCriticalNesting;
|
||||
#define portGET_CRITICAL_NESTING_COUNT( xCoreID ) xCriticalNesting
|
||||
#define portENTER_CRITICAL() \
|
||||
{ \
|
||||
portDISABLE_INTERRUPTS(); \
|
||||
xCriticalNesting++; \
|
||||
}
|
||||
|
||||
#define portEXIT_CRITICAL() \
|
||||
{ \
|
||||
xCriticalNesting--; \
|
||||
if( xCriticalNesting == 0 ) \
|
||||
{ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
}
|
||||
#else /* ( configNUMBER_OF_CORES == 1 ) */
|
||||
extern size_t xCriticalNestings[ configNUMBER_OF_CORES ];
|
||||
/*
|
||||
* SMP enabled
|
||||
*/
|
||||
extern void vTaskEnterCritical( void );
|
||||
extern void vTaskExitCritical( void );
|
||||
extern UBaseType_t vTaskEnterCriticalFromISR( void );
|
||||
extern void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
|
||||
#define portENTER_CRITICAL() vTaskEnterCritical()
|
||||
#define portEXIT_CRITICAL() vTaskExitCritical()
|
||||
#define portENTER_CRITICAL_FROM_ISR() vTaskEnterCriticalFromISR()
|
||||
#define portEXIT_CRITICAL_FROM_ISR( x ) vTaskExitCriticalFromISR( x )
|
||||
|
||||
#define portGET_CRITICAL_NESTING_COUNT( xCoreID ) ( xCriticalNestings[ ( xCoreID ) ] )
|
||||
#define portSET_CRITICAL_NESTING_COUNT( xCoreID, x ) ( xCriticalNestings[ ( xCoreID ) ] = ( x ) )
|
||||
#define portINCREMENT_CRITICAL_NESTING_COUNT( xCoreID ) ( xCriticalNestings[ ( xCoreID ) ]++ )
|
||||
#define portDECREMENT_CRITICAL_NESTING_COUNT( xCoreID ) ( xCriticalNestings[ ( xCoreID ) ]-- )
|
||||
|
||||
#endif /* if ( configNUMBER_OF_CORES == 1 ) */
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
/* Not supported on SMP */
|
||||
#if ( configNUMBER_OF_CORES == 1 )
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
/* 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 = ( 31UL - __builtin_clz( uxReadyPriorities ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
* not necessary for to use this port. They are defined so the common demo
|
||||
* files (which build with all the ports) will build. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portNOP() __asm volatile ( " nop " )
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__( ( always_inline ) )
|
||||
#endif
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
|
||||
#define portCRITICAL_NESTING_IN_TCB 0
|
||||
|
||||
#define portRTOS_SPINLOCK_COUNT 2
|
||||
|
||||
/* Note this is a single method with uxAcquire parameter since we have
|
||||
* static vars, the method is always called with a compile time constant for
|
||||
* uxAcquire, and the compiler should do the right thing! */
|
||||
static inline void vPortRecursiveLock( BaseType_t xCoreID,
|
||||
uint32_t ulLockNum,
|
||||
spin_lock_t * pxSpinLock,
|
||||
BaseType_t uxAcquire )
|
||||
{
|
||||
static volatile uint8_t ucOwnedByCore[ portMAX_CORE_COUNT ][portRTOS_SPINLOCK_COUNT];
|
||||
static volatile uint8_t ucRecursionCountByLock[ portRTOS_SPINLOCK_COUNT ];
|
||||
|
||||
configASSERT( ulLockNum < portRTOS_SPINLOCK_COUNT );
|
||||
|
||||
if( uxAcquire )
|
||||
{
|
||||
if (!spin_try_lock_unsafe(pxSpinLock)) {
|
||||
if( ucOwnedByCore[ xCoreID ][ ulLockNum ] )
|
||||
{
|
||||
configASSERT( ucRecursionCountByLock[ ulLockNum ] != 255u );
|
||||
ucRecursionCountByLock[ ulLockNum ]++;
|
||||
return;
|
||||
}
|
||||
spin_lock_unsafe_blocking(pxSpinLock);
|
||||
}
|
||||
configASSERT( ucRecursionCountByLock[ ulLockNum ] == 0 );
|
||||
ucRecursionCountByLock[ ulLockNum ] = 1;
|
||||
ucOwnedByCore[ xCoreID ][ ulLockNum ] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
configASSERT( ( ucOwnedByCore[ xCoreID ] [ulLockNum ] ) != 0 );
|
||||
configASSERT( ucRecursionCountByLock[ ulLockNum ] != 0 );
|
||||
|
||||
if( !--ucRecursionCountByLock[ ulLockNum ] )
|
||||
{
|
||||
ucOwnedByCore[ xCoreID ] [ ulLockNum ] = 0;
|
||||
spin_unlock_unsafe(pxSpinLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if ( configNUMBER_OF_CORES == 1 )
|
||||
#define portGET_ISR_LOCK( xCoreID )
|
||||
#define portRELEASE_ISR_LOCK( xCoreID )
|
||||
#define portGET_TASK_LOCK( xCoreID )
|
||||
#define portRELEASE_TASK_LOCK( xCoreID )
|
||||
#else /* configNUMBER_OF_CORES == 1 */
|
||||
#define portGET_ISR_LOCK( xCoreID ) vPortRecursiveLock( ( xCoreID ), 0, spin_lock_instance( configSMP_SPINLOCK_0 ), pdTRUE )
|
||||
#define portRELEASE_ISR_LOCK( xCoreID ) vPortRecursiveLock( ( xCoreID ), 0, spin_lock_instance( configSMP_SPINLOCK_0 ), pdFALSE )
|
||||
#define portGET_TASK_LOCK( xCoreID ) vPortRecursiveLock( ( xCoreID ), 1, spin_lock_instance( configSMP_SPINLOCK_1 ), pdTRUE )
|
||||
#define portRELEASE_TASK_LOCK( xCoreID ) vPortRecursiveLock( ( xCoreID ), 1, spin_lock_instance( configSMP_SPINLOCK_1 ), pdFALSE )
|
||||
#endif /* configNUMBER_OF_CORES == 1 */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
Vendored
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT AND BSD-3-Clause
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef RP2040_CONFIG_H
|
||||
#define RP2040_CONFIG_H
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/* configUSE_DYNAMIC_EXCEPTION_HANDLERS == 1 means set the exception handlers dynamically on cores
|
||||
* that need them in case the user has set up distinct vector table offsets per core
|
||||
*/
|
||||
#ifndef configUSE_DYNAMIC_EXCEPTION_HANDLERS
|
||||
#if defined( PICO_NO_RAM_VECTOR_TABLE ) && ( PICO_NO_RAM_VECTOR_TABLE == 1 )
|
||||
#define configUSE_DYNAMIC_EXCEPTION_HANDLERS 0
|
||||
#else
|
||||
#define configUSE_DYNAMIC_EXCEPTION_HANDLERS 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* configSUPPORT_PICO_SYNC_INTEROP == 1 means that SDK pico_sync
|
||||
* sem/mutex/queue etc. will work correctly when called from FreeRTOS tasks
|
||||
*/
|
||||
#ifndef configSUPPORT_PICO_SYNC_INTEROP
|
||||
#if LIB_PICO_SYNC
|
||||
#define configSUPPORT_PICO_SYNC_INTEROP 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* configSUPPORT_PICO_SYNC_INTEROP == 1 means that SDK pico_time
|
||||
* sleep_ms/sleep_us/sleep_until will work correctly when called from FreeRTOS
|
||||
* tasks, and will actually block at the FreeRTOS level
|
||||
*/
|
||||
#ifndef configSUPPORT_PICO_TIME_INTEROP
|
||||
#if LIB_PICO_TIME
|
||||
#define configSUPPORT_PICO_TIME_INTEROP 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
|
||||
/* configTICK_CORE indicates which core should handle the SysTick
|
||||
* interrupts */
|
||||
#ifndef configTICK_CORE
|
||||
#define configTICK_CORE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (configNUMBER_OF_CORES != 1)
|
||||
/* This SMP port requires two spin locks, which are claimed from the SDK.
|
||||
* the spin lock numbers to be used are defined statically and defaulted here
|
||||
* to the values nominally set aside for RTOS by the SDK */
|
||||
#ifndef configSMP_SPINLOCK_0
|
||||
#define configSMP_SPINLOCK_0 PICO_SPINLOCK_ID_OS1
|
||||
#endif
|
||||
|
||||
#ifndef configSMP_SPINLOCK_1
|
||||
#define configSMP_SPINLOCK_1 PICO_SPINLOCK_ID_OS2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* ifndef RP2040_CONFIG_H */
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
# Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
# Called after the Raspberry Pi Pico SDK has been initialized to add our libraries
|
||||
|
||||
add_library(FreeRTOS-Kernel-Core INTERFACE)
|
||||
target_sources(FreeRTOS-Kernel-Core INTERFACE
|
||||
${FREERTOS_KERNEL_PATH}/croutine.c
|
||||
${FREERTOS_KERNEL_PATH}/event_groups.c
|
||||
${FREERTOS_KERNEL_PATH}/list.c
|
||||
${FREERTOS_KERNEL_PATH}/queue.c
|
||||
${FREERTOS_KERNEL_PATH}/stream_buffer.c
|
||||
${FREERTOS_KERNEL_PATH}/tasks.c
|
||||
${FREERTOS_KERNEL_PATH}/timers.c
|
||||
)
|
||||
target_include_directories(FreeRTOS-Kernel-Core INTERFACE ${FREERTOS_KERNEL_PATH}/include)
|
||||
|
||||
if (PICO_SDK_VERSION_STRING VERSION_GREATER_EQUAL "1.3.2")
|
||||
target_compile_definitions(FreeRTOS-Kernel-Core INTERFACE
|
||||
PICO_CONFIG_RTOS_ADAPTER_HEADER=${CMAKE_CURRENT_LIST_DIR}/include/freertos_sdk_config.h)
|
||||
endif()
|
||||
|
||||
add_library(FreeRTOS-Kernel INTERFACE)
|
||||
target_sources(FreeRTOS-Kernel INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/port.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/portASM.S
|
||||
)
|
||||
|
||||
target_include_directories(FreeRTOS-Kernel INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/include
|
||||
${FREERTOS_CONFIG_FILE_DIRECTORY})
|
||||
|
||||
target_link_libraries(FreeRTOS-Kernel INTERFACE
|
||||
FreeRTOS-Kernel-Core
|
||||
pico_base_headers
|
||||
hardware_clocks
|
||||
hardware_exception
|
||||
hardware_riscv_platform_timer
|
||||
pico_multicore
|
||||
)
|
||||
|
||||
target_compile_definitions(FreeRTOS-Kernel INTERFACE
|
||||
LIB_FREERTOS_KERNEL=1
|
||||
FREE_RTOS_KERNEL_SMP=1
|
||||
)
|
||||
|
||||
add_library(FreeRTOS-Kernel-Static INTERFACE)
|
||||
target_compile_definitions(FreeRTOS-Kernel-Static INTERFACE
|
||||
configSUPPORT_STATIC_ALLOCATION=1
|
||||
configKERNEL_PROVIDED_STATIC_MEMORY=1
|
||||
)
|
||||
|
||||
target_link_libraries(FreeRTOS-Kernel-Static INTERFACE FreeRTOS-Kernel)
|
||||
|
||||
add_library(FreeRTOS-Kernel-Heap1 INTERFACE)
|
||||
target_sources(FreeRTOS-Kernel-Heap1 INTERFACE ${FREERTOS_KERNEL_PATH}/portable/MemMang/heap_1.c)
|
||||
target_link_libraries(FreeRTOS-Kernel-Heap1 INTERFACE FreeRTOS-Kernel)
|
||||
|
||||
add_library(FreeRTOS-Kernel-Heap2 INTERFACE)
|
||||
target_sources(FreeRTOS-Kernel-Heap2 INTERFACE ${FREERTOS_KERNEL_PATH}/portable/MemMang/heap_2.c)
|
||||
target_link_libraries(FreeRTOS-Kernel-Heap2 INTERFACE FreeRTOS-Kernel)
|
||||
|
||||
add_library(FreeRTOS-Kernel-Heap3 INTERFACE)
|
||||
target_sources(FreeRTOS-Kernel-Heap3 INTERFACE ${FREERTOS_KERNEL_PATH}/portable/MemMang/heap_3.c)
|
||||
target_link_libraries(FreeRTOS-Kernel-Heap3 INTERFACE FreeRTOS-Kernel)
|
||||
|
||||
add_library(FreeRTOS-Kernel-Heap4 INTERFACE)
|
||||
target_sources(FreeRTOS-Kernel-Heap4 INTERFACE ${FREERTOS_KERNEL_PATH}/portable/MemMang/heap_4.c)
|
||||
target_link_libraries(FreeRTOS-Kernel-Heap4 INTERFACE FreeRTOS-Kernel)
|
||||
|
||||
add_library(FreeRTOS-Kernel-Heap5 INTERFACE)
|
||||
target_sources(FreeRTOS-Kernel-Heap5 INTERFACE ${FREERTOS_KERNEL_PATH}/portable/MemMang/heap_5.c)
|
||||
target_link_libraries(FreeRTOS-Kernel-Heap5 INTERFACE FreeRTOS-Kernel)
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
- IRQ premption is currently disabled; this might be easy enough to fix by stacking the core local ISRStackTop, and using 0
|
||||
for recursing, since that just uses the current one - of course the whole code may not be happy with nested IRQs
|
||||
- Right now mtvec table and irq handlers are installed on both cores, since the SDK doesn't currently treat them separately.
|
||||
- Q: Why is critical_nestings stored in TCB on RISC-V?
|
||||
Vendored
+66
@@ -0,0 +1,66 @@
|
||||
# Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
|
||||
|
||||
# This can be dropped into an external project to help locate this SDK
|
||||
# It should be include()ed prior to project()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
|
||||
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
|
||||
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
|
||||
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
|
||||
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
|
||||
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
|
||||
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
|
||||
|
||||
if (NOT PICO_SDK_PATH)
|
||||
if (PICO_SDK_FETCH_FROM_GIT)
|
||||
include(FetchContent)
|
||||
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
|
||||
if (PICO_SDK_FETCH_FROM_GIT_PATH)
|
||||
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||
endif ()
|
||||
FetchContent_Declare(
|
||||
pico_sdk
|
||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||
GIT_TAG master
|
||||
)
|
||||
if (NOT pico_sdk)
|
||||
message("Downloading Raspberry Pi Pico SDK")
|
||||
FetchContent_Populate(pico_sdk)
|
||||
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
|
||||
endif ()
|
||||
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
||||
else ()
|
||||
message(FATAL_ERROR
|
||||
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||
if (NOT EXISTS ${PICO_SDK_PATH})
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
|
||||
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
|
||||
|
||||
include(${PICO_SDK_INIT_CMAKE_FILE})
|
||||
+714
@@ -0,0 +1,714 @@
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* Copyright (c) 2024 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT AND BSD-3-Clause
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the RISC-V port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "rp2040_config.h"
|
||||
#include "hardware/clocks.h"
|
||||
#include "hardware/exception.h"
|
||||
#include "hardware/irq.h"
|
||||
#include "portmacro.h"
|
||||
|
||||
/* Standard includes. */
|
||||
#include "string.h"
|
||||
|
||||
|
||||
/* Let the user override the pre-loading of the initial RA. */
|
||||
#ifdef configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#else
|
||||
#define portTASK_RETURN_ADDRESS 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* LIB_PICO_MULTICORE == 1, if we are linked with pico_multicore (note that
|
||||
* the non SMP FreeRTOS_Kernel is not linked with pico_multicore itself). We
|
||||
* use this flag to determine if we need multi-core functionality.
|
||||
*/
|
||||
#if ( LIB_PICO_MULTICORE == 1 )
|
||||
#include "pico/multicore.h"
|
||||
#endif /* LIB_PICO_MULTICORE */
|
||||
|
||||
#ifndef configUSE_ISR_STACK
|
||||
#define configUSE_ISR_STACK 1
|
||||
#endif
|
||||
|
||||
/* The stack used by interrupt service routines. Set configISR_STACK_SIZE_WORDS
|
||||
* to use a statically allocated array as the interrupt stack. Alternative leave
|
||||
* configISR_STACK_SIZE_WORDS undefined and update the linker script so that a
|
||||
* linker variable names __freertos_irq_stack_top has the same value as the top
|
||||
* of the stack used by main. Using the linker script method will repurpose the
|
||||
* stack that was used by main before the scheduler was started for use as the
|
||||
* interrupt stack after the scheduler has started. */
|
||||
#ifdef configISR_STACK_SIZE_WORDS
|
||||
#error configISR_STACK_SIZE_WORDS not yet supported; we need per core ones
|
||||
static __attribute__( ( aligned( 16 ) ) ) StackType_t xISRStack[ configISR_STACK_SIZE_WORDS ] = { 0 };
|
||||
const StackType_t xISRStackTop = ( StackType_t ) &( xISRStack[ configISR_STACK_SIZE_WORDS & ~portBYTE_ALIGNMENT_MASK ] );
|
||||
|
||||
/* Don't use 0xa5 as the stack fill bytes as that is used by the kernel for
|
||||
* the task stacks, and so will legitimately appear in many positions within
|
||||
* the ISR stack. */
|
||||
#define portISR_STACK_FILL_BYTE 0xee
|
||||
#else
|
||||
/*
|
||||
* If these are 0, then no stack switch is performed.
|
||||
*
|
||||
* Note: if configUSE_ISR_STACK == 0, then this is never initialized,
|
||||
* but we keep this array around, because portASM.S / portContext.h does not
|
||||
* have access to config variables
|
||||
*/
|
||||
StackType_t xISRStackTops[NUM_CORES] = {0};
|
||||
#endif
|
||||
|
||||
#if ( configSUPPORT_PICO_SYNC_INTEROP == 1 || configNUMBER_OF_CORES > 1 )
|
||||
#include "hardware/irq.h"
|
||||
#endif /* ( configSUPPORT_PICO_SYNC_INTEROP == 1 || configNUMBER_OF_CORES > 1 ) */
|
||||
#if ( configSUPPORT_PICO_SYNC_INTEROP == 1 )
|
||||
#include "pico/lock_core.h"
|
||||
#include "event_groups.h"
|
||||
#if configSUPPORT_STATIC_ALLOCATION
|
||||
static StaticEventGroup_t xStaticEventGroup;
|
||||
#define pEventGroup ( &xStaticEventGroup )
|
||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
static EventGroupHandle_t xEventGroup;
|
||||
#if ( configNUMBER_OF_CORES == 1 )
|
||||
static EventBits_t uxCrossCoreEventBits;
|
||||
static spin_lock_t * pxCrossCoreSpinLock; /* protects uxCrossCoreEventBits */
|
||||
#endif
|
||||
#endif /* configSUPPORT_PICO_SYNC_INTEROP */
|
||||
|
||||
/* Note this is an SDK IRQ priority which use the ARM convention */
|
||||
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||
|
||||
/*
|
||||
* Setup the timer to generate the tick interrupts. The implementation in this
|
||||
* file is weak to allow application writers to change the timer used to
|
||||
* generate the tick interrupt.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void ) __attribute__( ( weak ) );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Used to program the machine timer compare register. */
|
||||
uint64_t ullNextTime = 0ULL;
|
||||
const uint64_t * pullNextTime = &ullNextTime; /* used by ASM code */
|
||||
size_t uxTimerIncrementsForOneTick;
|
||||
volatile uint64_t * pullMachineTimerCompareRegister = NULL;
|
||||
|
||||
/* Holds the critical nesting value - deliberately non-zero at start up to
|
||||
* ensure interrupts are not accidentally enabled before the scheduler starts. */
|
||||
typedef struct tskTaskControlBlock TCB_t;
|
||||
#if configNUMBER_OF_CORES == 1
|
||||
size_t xCriticalNesting = ( size_t ) 0xaaaaaaaa;
|
||||
size_t *xCriticalNestingArray = &xCriticalNesting;
|
||||
extern portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB;
|
||||
TCB_t * volatile * pxCurrentTCBArray = &pxCurrentTCB;
|
||||
static uint32_t zero; /* todo we could use a pre-existing zero elsewhere! */
|
||||
uint32_t * pxCurrentCoreID = &zero;
|
||||
#else
|
||||
size_t xCriticalNestings[ configNUMBER_OF_CORES ] = { 0 };
|
||||
size_t *xCriticalNestingArray = &xCriticalNestings[0];
|
||||
extern portDONT_DISCARD PRIVILEGED_DATA TCB_t * volatile pxCurrentTCBs[ configNUMBER_OF_CORES ];
|
||||
TCB_t * volatile * pxCurrentTCBArray = pxCurrentTCBs;
|
||||
const volatile uint32_t * pxCurrentCoreID = &sio_hw->cpuid;
|
||||
#endif
|
||||
|
||||
/* Used to catch tasks that attempt to return from their implementing function. */
|
||||
size_t xTaskReturnAddress = ( size_t ) portTASK_RETURN_ADDRESS;
|
||||
|
||||
/* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task
|
||||
* stack checking. A problem in the ISR stack will trigger an assert, not call
|
||||
* the stack overflow hook function (because the stack overflow hook is specific
|
||||
* to a task stack, not the ISR stack). */
|
||||
#if defined( configISR_STACK_SIZE_WORDS ) && ( configCHECK_FOR_STACK_OVERFLOW > 2 )
|
||||
#warning "This path not tested, or even compiled yet."
|
||||
|
||||
static const uint8_t ucExpectedStackBytes[] =
|
||||
{
|
||||
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
|
||||
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
|
||||
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
|
||||
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
|
||||
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE
|
||||
}; \
|
||||
|
||||
#define portCHECK_ISR_STACK() configASSERT( ( memcmp( ( void * ) xISRStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) == 0 ) )
|
||||
#else /* if defined( configISR_STACK_SIZE_WORDS ) && ( configCHECK_FOR_STACK_OVERFLOW > 2 ) */
|
||||
/* Define the function away. */
|
||||
#define portCHECK_ISR_STACK()
|
||||
#endif /* configCHECK_FOR_STACK_OVERFLOW > 2 */
|
||||
|
||||
#define INVALID_PRIMARY_CORE_NUM 0xffu
|
||||
/* The primary core number (the own which has the SysTick handler) */
|
||||
static uint8_t ucPrimaryCoreNum = INVALID_PRIMARY_CORE_NUM;
|
||||
/* Initialize to -1 so that when using INTEROP with SDK and running on one core only, we can tell if this is initialized yet */
|
||||
static int8_t cDoorbellNum = -1;
|
||||
|
||||
/* Note: portIS_FREE_RTOS_CORE() also returns false until the scheduler is started */
|
||||
#if ( configNUMBER_OF_CORES != 1 )
|
||||
#define portIS_FREE_RTOS_CORE() ( ucPrimaryCoreNum != INVALID_PRIMARY_CORE_NUM )
|
||||
#else
|
||||
#define portIS_FREE_RTOS_CORE() ( ucPrimaryCoreNum == get_core_num() )
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#include "hardware/riscv_platform_timer.h"
|
||||
|
||||
void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
riscv_timer_set_fullspeed(true);
|
||||
uint64_t ullCurrentTime = riscv_timer_get_mtime();
|
||||
uxTimerIncrementsForOneTick = ( size_t ) ( ( clock_get_hz( clk_sys ) ) / ( configTICK_RATE_HZ ) ); /* Assumes increment won't go over 32-bits. */
|
||||
|
||||
pullMachineTimerCompareRegister = ( volatile uint64_t * ) &sio_hw->mtimecmp;
|
||||
|
||||
ullNextTime = ullCurrentTime + uxTimerIncrementsForOneTick;
|
||||
*pullMachineTimerCompareRegister = ullNextTime;
|
||||
|
||||
/* Prepare the time to use after the next tick interrupt. */
|
||||
ullNextTime += uxTimerIncrementsForOneTick;
|
||||
|
||||
extern void freertos_risc_v_mtimer_interrupt_handler(void);
|
||||
#if 1
|
||||
irq_set_exclusive_handler(SIO_IRQ_MTIMECMP, freertos_risc_v_mtimer_interrupt_handler);
|
||||
irq_set_enabled(SIO_IRQ_MTIMECMP, true);
|
||||
#else
|
||||
riscv_set_csr(mie, RVCSR_MIE_MTIE_BITS);
|
||||
#endif
|
||||
}
|
||||
|
||||
void vPortInstallVectorTableHandlers(void) {
|
||||
extern void freertos_risc_v_trap_handler(void);
|
||||
extern void freertos_risc_v_interrupt_handler(void);
|
||||
irq_set_riscv_vector_handler(RISCV_VEC_MACHINE_EXCEPTION, freertos_risc_v_trap_handler);
|
||||
irq_set_riscv_vector_handler(RISCV_VEC_MACHINE_EXTERNAL_IRQ, freertos_risc_v_interrupt_handler);
|
||||
}
|
||||
|
||||
StackType_t xPortInitISRStack(void) {
|
||||
StackType_t xISRStackTop;
|
||||
//( StackType_t ) /*__freertos_irq_stack_top*/__StackTop;
|
||||
// todo fixup for allocated stacks
|
||||
if (get_core_num())
|
||||
{
|
||||
extern const uint32_t __StackOneTop[];
|
||||
xISRStackTop = ( StackType_t ) __StackOneTop;
|
||||
}
|
||||
else
|
||||
{
|
||||
extern const uint32_t __StackTop[];
|
||||
xISRStackTop = ( StackType_t ) __StackTop;
|
||||
}
|
||||
xISRStackTops[get_core_num()] = xISRStackTop;
|
||||
return xISRStackTop;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( LIB_PICO_MULTICORE == 1 ) && ( configSUPPORT_PICO_SYNC_INTEROP == 1 || configNUMBER_OF_CORES > 1)
|
||||
static void prvDoorbellInterruptHandler()
|
||||
{
|
||||
if (cDoorbellNum >= 0 && multicore_doorbell_is_set_current_core(cDoorbellNum))
|
||||
{
|
||||
multicore_doorbell_clear_current_core(cDoorbellNum);
|
||||
#if ( configNUMBER_OF_CORES != 1 )
|
||||
portYIELD_FROM_ISR( pdTRUE );
|
||||
#elif ( configSUPPORT_PICO_SYNC_INTEROP == 1 )
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
uint32_t ulSave = spin_lock_blocking( pxCrossCoreSpinLock );
|
||||
EventBits_t ulBits = uxCrossCoreEventBits;
|
||||
uxCrossCoreEventBits &= ~ulBits;
|
||||
spin_unlock( pxCrossCoreSpinLock, ulSave );
|
||||
xEventGroupSetBitsFromISR( xEventGroup, ulBits, &xHigherPriorityTaskWoken );
|
||||
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||
#endif /* configNUMBER_OF_CORES != 1 */
|
||||
}
|
||||
}
|
||||
#endif /* ( LIB_PICO_MULTICORE == 1 ) && ( configSUPPORT_PICO_SYNC_INTEROP == 1 || configNUMBER_OF_CORES > 1) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configNUMBER_OF_CORES != 1 )
|
||||
static BaseType_t xPortStartSchedulerOnCore( void )
|
||||
{
|
||||
extern void xPortStartFirstTask( void );
|
||||
#if ( configUSE_ISR_STACK == 1)
|
||||
StackType_t xISRStackTop = xPortInitISRStack();
|
||||
|
||||
#if ( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
/* Check alignment of the interrupt stack - which is the same as the
|
||||
* stack that was being used by main() prior to the scheduler being
|
||||
* started. */
|
||||
configASSERT( ( xISRStackTop & portBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
|
||||
#ifdef configISR_STACK_SIZE_WORDS
|
||||
{
|
||||
memset( ( void * ) xISRStack, portISR_STACK_FILL_BYTE, sizeof( xISRStack ) );
|
||||
}
|
||||
#endif /* configISR_STACK_SIZE_WORDS */
|
||||
}
|
||||
#endif /* configASSERT_DEFINED */
|
||||
#endif /* configUSE_ISR_STACK */
|
||||
|
||||
if( ucPrimaryCoreNum == get_core_num() ) {
|
||||
/* If there is a CLINT then it is ok to use the default implementation
|
||||
* in this file, otherwise vPortSetupTimerInterrupt() must be implemented to
|
||||
* configure whichever clock is to be used to generate the tick interrupt. */
|
||||
vPortSetupTimerInterrupt();
|
||||
|
||||
// extern void freertos_risc_v_trap_handler(void);
|
||||
// exception_set_exclusive_handler(0, freertos_risc_v_trap_handler);
|
||||
#if ((configMTIME_BASE_ADDRESS != 0) && (configMTIMECMP_BASE_ADDRESS != 0))
|
||||
{
|
||||
/* Enable mtime and external interrupts. 1<<7 for timer interrupt,
|
||||
* 1<<11 for external interrupt. _RB_ What happens here when mtime is
|
||||
* not present as with pulpino? */
|
||||
__asm volatile ( "csrs mie, %0" ::"r" ( 0x880 ) );
|
||||
}
|
||||
#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) */
|
||||
}
|
||||
|
||||
/* Install Doorbell handler to receive interrupt from other core */
|
||||
uint32_t irq_num = multicore_doorbell_irq_num(cDoorbellNum);
|
||||
irq_set_priority( irq_num, portMIN_INTERRUPT_PRIORITY );
|
||||
irq_set_exclusive_handler( irq_num, prvDoorbellInterruptHandler );
|
||||
irq_set_enabled( irq_num, 1 );
|
||||
|
||||
xPortStartFirstTask();
|
||||
|
||||
/* Should not get here as after calling xPortStartFirstTask() only tasks
|
||||
* should be executing. */
|
||||
return pdFAIL;
|
||||
}
|
||||
|
||||
static void prvDisableInterruptsAndPortStartSchedulerOnCore( void )
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
xPortStartSchedulerOnCore();
|
||||
}
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
configASSERT( ucPrimaryCoreNum == INVALID_PRIMARY_CORE_NUM );
|
||||
|
||||
vPortInstallVectorTableHandlers();
|
||||
|
||||
/* No one else should use these! */
|
||||
spin_lock_claim( configSMP_SPINLOCK_0 );
|
||||
spin_lock_claim( configSMP_SPINLOCK_1 );
|
||||
|
||||
// claim same number of both cores for simplicity
|
||||
cDoorbellNum = (int8_t)multicore_doorbell_claim_unused(0b11, true);
|
||||
multicore_doorbell_clear_current_core(cDoorbellNum);
|
||||
multicore_doorbell_clear_other_core(cDoorbellNum);
|
||||
|
||||
ucPrimaryCoreNum = configTICK_CORE;
|
||||
configASSERT( get_core_num() == 0 ); /* we must be started on core 0 */
|
||||
multicore_reset_core1();
|
||||
multicore_launch_core1( prvDisableInterruptsAndPortStartSchedulerOnCore );
|
||||
xPortStartSchedulerOnCore();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
#else /* if ( configNUMBER_OF_CORES != 1 ) */
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
extern void xPortStartFirstTask( void );
|
||||
|
||||
vPortInstallVectorTableHandlers();
|
||||
|
||||
#if ( configUSE_ISR_STACK == 1)
|
||||
StackType_t xISRStackTop = xPortInitISRStack();
|
||||
|
||||
#if ( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
/* Check alignment of the interrupt stack - which is the same as the
|
||||
* stack that was being used by main() prior to the scheduler being
|
||||
* started. */
|
||||
configASSERT( ( xISRStackTop & portBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
|
||||
#ifdef configISR_STACK_SIZE_WORDS
|
||||
{
|
||||
memset( ( void * ) xISRStack, portISR_STACK_FILL_BYTE, sizeof( xISRStack ) );
|
||||
}
|
||||
#endif /* configISR_STACK_SIZE_WORDS */
|
||||
}
|
||||
#endif /* configASSERT_DEFINED */
|
||||
#endif /* configUSE_ISR_STACK */
|
||||
|
||||
/* If there is a CLINT then it is ok to use the default implementation
|
||||
* in this file, otherwise vPortSetupTimerInterrupt() must be implemented to
|
||||
* configure whichever clock is to be used to generate the tick interrupt. */
|
||||
vPortSetupTimerInterrupt();
|
||||
|
||||
// extern void freertos_risc_v_trap_handler(void);
|
||||
// exception_set_exclusive_handler(0, freertos_risc_v_trap_handler);
|
||||
#if ( ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) )
|
||||
{
|
||||
/* Enable mtime and external interrupts. 1<<7 for timer interrupt,
|
||||
* 1<<11 for external interrupt. _RB_ What happens here when mtime is
|
||||
* not present as with pulpino? */
|
||||
__asm volatile ( "csrs mie, %0" ::"r" ( 0x880 ) );
|
||||
}
|
||||
#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) */
|
||||
|
||||
ucPrimaryCoreNum = get_core_num();
|
||||
#if ( LIB_PICO_MULTICORE == 1 )
|
||||
#if ( configSUPPORT_PICO_SYNC_INTEROP == 1 )
|
||||
// claim same number of both cores for simplicity
|
||||
cDoorbellNum = (int8_t) multicore_doorbell_claim_unused(0b11, true);
|
||||
multicore_doorbell_clear_current_core(cDoorbellNum);
|
||||
multicore_doorbell_clear_other_core(cDoorbellNum);
|
||||
uint32_t irq_num = multicore_doorbell_irq_num(cDoorbellNum);
|
||||
irq_set_priority( irq_num, portMIN_INTERRUPT_PRIORITY );
|
||||
irq_set_exclusive_handler( irq_num, prvDoorbellInterruptHandler );
|
||||
irq_set_enabled( irq_num, 1 );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
xPortStartFirstTask();
|
||||
|
||||
/* Should not get here as after calling xPortStartFirstTask() only tasks
|
||||
* should be executing. */
|
||||
return pdFAIL;
|
||||
}
|
||||
#endif /* ( configNUMBER_OF_CORES != 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented. */
|
||||
for( ; ; )
|
||||
{
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configSUPPORT_PICO_SYNC_INTEROP == 1 )
|
||||
void vPortYield( void )
|
||||
{
|
||||
__asm volatile ( "ecall" );
|
||||
}
|
||||
#endif /* configSUPPORT_PICO_SYNC_INTEROP */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
#if ( configSUPPORT_PICO_SYNC_INTEROP == 1 ) || ( configSUPPORT_PICO_TIME_INTEROP == 1 )
|
||||
static TickType_t prvGetTicksToWaitBefore( absolute_time_t t )
|
||||
{
|
||||
int64_t xDelay = absolute_time_diff_us( get_absolute_time(), t );
|
||||
const uint32_t ulTickPeriod = 1000000 / configTICK_RATE_HZ;
|
||||
|
||||
xDelay += ulTickPeriod - 1;
|
||||
|
||||
if( xDelay >= ulTickPeriod )
|
||||
{
|
||||
return xDelay / ulTickPeriod;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* if ( configSUPPORT_PICO_SYNC_INTEROP == 1 ) || ( configSUPPORT_PICO_TIME_INTEROP == 1 ) */
|
||||
|
||||
#if ( configSUPPORT_PICO_SYNC_INTEROP == 1 )
|
||||
uint32_t ulPortLockGetCurrentOwnerId()
|
||||
{
|
||||
if( portIS_FREE_RTOS_CORE() )
|
||||
{
|
||||
uint32_t exception = __get_current_exception();
|
||||
|
||||
if( !exception )
|
||||
{
|
||||
return ( uintptr_t ) xTaskGetCurrentTaskHandle();
|
||||
}
|
||||
|
||||
/* Note: since ROM as at 0x00000000, these can't be confused with
|
||||
* valid task handles (pointers) in RAM */
|
||||
/* We make all exception handler/core combinations distinct owners */
|
||||
return get_core_num() + exception * 2;
|
||||
}
|
||||
|
||||
/* Note: since ROM as at 0x00000000, this can't be confused with
|
||||
* valid task handles (pointers) in RAM */
|
||||
return get_core_num();
|
||||
}
|
||||
|
||||
static inline EventBits_t prvGetEventGroupBit( spin_lock_t * spinLock )
|
||||
{
|
||||
uint32_t ulBit;
|
||||
|
||||
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
|
||||
ulBit = 1u << ( spin_lock_get_num( spinLock ) & 0x7u );
|
||||
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
|
||||
ulBit = 1u << ( spin_lock_get_num( spinLock ) % 24 );
|
||||
#endif /* configTICK_TYPE_WIDTH_IN_BITS */
|
||||
return ( EventBits_t ) ulBit;
|
||||
}
|
||||
|
||||
static inline EventBits_t prvGetAllEventGroupBits()
|
||||
{
|
||||
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
|
||||
return ( EventBits_t ) 0xffu;
|
||||
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
|
||||
return ( EventBits_t ) 0xffffffu;
|
||||
#endif /* configTICK_TYPE_WIDTH_IN_BITS */
|
||||
}
|
||||
|
||||
void vPortLockInternalSpinUnlockWithWait( struct lock_core * pxLock,
|
||||
uint32_t ulSave )
|
||||
{
|
||||
configASSERT( !portCHECK_IF_IN_ISR() );
|
||||
configASSERT( pxLock->spin_lock );
|
||||
|
||||
if( !portIS_FREE_RTOS_CORE() )
|
||||
{
|
||||
spin_unlock( pxLock->spin_lock, ulSave );
|
||||
__wfe();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The requirement (from the SDK) on this implementation is that this method
|
||||
* should always wake up from a corresponding call to vPortLockInternalSpinUnlockWithNotify
|
||||
* that happens after this method is called.
|
||||
*
|
||||
* The moment that we unlock the spin lock, we need to be sure that
|
||||
* there is no way that we end up blocking in xEventGroupWaitBits,
|
||||
* despite the fact that other tasks can now run, if the corresponding
|
||||
* unlock has occurred.
|
||||
*
|
||||
* Previously the RP2xxx ports used to attempt to disable IRQs until the
|
||||
* task actually (potentially) became blocked by hooking the IRQ re-enable
|
||||
* when xEventGroupWaitBits completes (or switches tasks), but this
|
||||
* was a broken hack, in that IRQs are re-enabled at other points during
|
||||
* that call.
|
||||
*
|
||||
* This deferred IRQ enable is not actually needed, because all we
|
||||
* care about is that:
|
||||
*
|
||||
* Even in the presence of other tasks acquiring then releasing
|
||||
* the lock, between the interrupt_enable and the xEventGroupWaitBits,
|
||||
* the corresponding bit will still be set.
|
||||
*
|
||||
* This is the case, even any intervening blocked lock (which
|
||||
* clears the event bit) will need to unlock it before we proceed,
|
||||
* which will set the event bit again.
|
||||
*
|
||||
* The multiplexing down of multiple spin lock numbers to fewer
|
||||
* event bits does not cause a possible race condition,
|
||||
* but it does mean that a task waiting for lock A can be
|
||||
* blocked by a task B which owns another lock.
|
||||
*
|
||||
* This could be fixed by using an array of event groups, however
|
||||
* since the SDK spin locks are generally intended for very short
|
||||
* term usage anyway, and rarely nested except in exotic cases
|
||||
* like video output, we'll leave it as one event group for now
|
||||
*/
|
||||
spin_unlock( pxLock->spin_lock, ulSave);
|
||||
xEventGroupWaitBits( xEventGroup, prvGetEventGroupBit( pxLock->spin_lock ),
|
||||
pdTRUE, pdFALSE, portMAX_DELAY );
|
||||
}
|
||||
}
|
||||
|
||||
void vPortLockInternalSpinUnlockWithNotify( struct lock_core * pxLock,
|
||||
uint32_t ulSave )
|
||||
{
|
||||
EventBits_t uxBits = prvGetEventGroupBit( pxLock->spin_lock );
|
||||
|
||||
if( portIS_FREE_RTOS_CORE() )
|
||||
{
|
||||
#if LIB_PICO_MULTICORE
|
||||
/* signal an event in case a regular core is waiting */
|
||||
__sev();
|
||||
#endif
|
||||
spin_unlock( pxLock->spin_lock, ulSave );
|
||||
|
||||
if( !portCHECK_IF_IN_ISR() )
|
||||
{
|
||||
xEventGroupSetBits( xEventGroup, uxBits );
|
||||
}
|
||||
else
|
||||
{
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
xEventGroupSetBitsFromISR( xEventGroup, uxBits, &xHigherPriorityTaskWoken );
|
||||
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__sev();
|
||||
#if ( configNUMBER_OF_CORES == 1 )
|
||||
if( pxCrossCoreSpinLock != pxLock->spin_lock )
|
||||
{
|
||||
spin_lock_unsafe_blocking( pxCrossCoreSpinLock );
|
||||
uxCrossCoreEventBits |= uxBits;
|
||||
spin_unlock_unsafe( pxCrossCoreSpinLock );
|
||||
}
|
||||
else
|
||||
{
|
||||
uxCrossCoreEventBits |= uxBits;
|
||||
}
|
||||
|
||||
/* This causes doorbell irq on the other (FreeRTOS) core which will do the set the event bits */
|
||||
if ( cDoorbellNum >= 0 )
|
||||
{
|
||||
multicore_doorbell_set_other_core(cDoorbellNum);
|
||||
}
|
||||
#endif /* configNUMBER_OF_CORES == 1 */
|
||||
spin_unlock( pxLock->spin_lock, ulSave );
|
||||
}
|
||||
}
|
||||
|
||||
bool xPortLockInternalSpinUnlockWithBestEffortWaitOrTimeout( struct lock_core * pxLock,
|
||||
uint32_t ulSave,
|
||||
absolute_time_t uxUntil )
|
||||
{
|
||||
configASSERT( !portCHECK_IF_IN_ISR() );
|
||||
configASSERT( pxLock->spin_lock );
|
||||
|
||||
/* note no need to check LIB_PICO_MULTICORE, as this is always returns true if that is not defined */
|
||||
if( !portIS_FREE_RTOS_CORE() )
|
||||
{
|
||||
spin_unlock( pxLock->spin_lock, ulSave );
|
||||
return best_effort_wfe_or_timeout( uxUntil );
|
||||
}
|
||||
else
|
||||
{
|
||||
configASSERT( portIS_FREE_RTOS_CORE() );
|
||||
|
||||
TickType_t uxTicksToWait = prvGetTicksToWaitBefore( uxUntil );
|
||||
|
||||
if( uxTicksToWait )
|
||||
{
|
||||
/* See comment in vPortLockInternalSpinUnlockWithWait for detail
|
||||
* about possible race conditions */
|
||||
spin_unlock( pxLock->spin_lock, ulSave );
|
||||
xEventGroupWaitBits( xEventGroup,
|
||||
prvGetEventGroupBit( pxLock->spin_lock ), pdTRUE,
|
||||
pdFALSE, uxTicksToWait );
|
||||
}
|
||||
else
|
||||
{
|
||||
spin_unlock( pxLock->spin_lock, ulSave );
|
||||
}
|
||||
|
||||
if( time_reached( uxUntil ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We do not want to hog the core */
|
||||
portYIELD();
|
||||
/* We aren't sure if we've reached the timeout yet; the caller will check */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if ( configSUPPORT_PICO_SYNC_INTEROP == 1 )
|
||||
/* runs before main */
|
||||
static void __attribute__( ( constructor ) ) prvRuntimeInitializer( void )
|
||||
{
|
||||
/* This must be done even before the scheduler is started, as the spin lock
|
||||
* is used by the overrides of the SDK wait/notify primitives */
|
||||
#if ( configNUMBER_OF_CORES == 1 )
|
||||
pxCrossCoreSpinLock = spin_lock_instance( next_striped_spin_lock_num() );
|
||||
#endif /* configNUMBER_OF_CORES == 1 */
|
||||
|
||||
/* The event group is not used prior to scheduler init, but is initialized
|
||||
* here to since it logically belongs with the spin lock */
|
||||
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
xEventGroup = xEventGroupCreateStatic( &xStaticEventGroup );
|
||||
#else
|
||||
|
||||
/* Note that it is slightly dubious calling this here before the scheduler is initialized,
|
||||
* however the only thing it touches is the allocator which then calls vPortEnterCritical
|
||||
* and vPortExitCritical, and allocating here saves us checking the one time initialized variable in
|
||||
* some rather critical code paths */
|
||||
xEventGroup = xEventGroupCreate();
|
||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
}
|
||||
#endif /* if ( configSUPPORT_PICO_SYNC_INTEROP == 1 ) */
|
||||
#endif /* configSUPPORT_PICO_SYNC_INTEROP */
|
||||
|
||||
#if ( configSUPPORT_PICO_TIME_INTEROP == 1 )
|
||||
void xPortSyncInternalYieldUntilBefore( absolute_time_t t )
|
||||
{
|
||||
TickType_t uxTicksToWait = prvGetTicksToWaitBefore( t );
|
||||
|
||||
if( uxTicksToWait )
|
||||
{
|
||||
vTaskDelay( uxTicksToWait );
|
||||
}
|
||||
}
|
||||
#endif /* configSUPPORT_PICO_TIME_INTEROP */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configNUMBER_OF_CORES != 1 )
|
||||
void vYieldCore( int xCoreID )
|
||||
{
|
||||
/* Remove warning if configASSERT is not defined.
|
||||
* xCoreID is not used in this function due to this is a dual-core system. The yielding core must be different from the current core. */
|
||||
( void ) xCoreID;
|
||||
|
||||
configASSERT( xCoreID != ( int ) portGET_CORE_ID() );
|
||||
|
||||
#if ( configNUMBER_OF_CORES != 1 )
|
||||
|
||||
/* will cause interrupt on other core if not already pending */
|
||||
configASSERT( cDoorbellNum >= 0);
|
||||
multicore_doorbell_set_other_core(cDoorbellNum);
|
||||
#endif
|
||||
}
|
||||
#endif // ( configNUMBER_OF_CORES != 1 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* todo need to move portASM.s back into portasm.c so we can inline this */
|
||||
UBaseType_t callTaskEnterCriticalFromISR(void) {
|
||||
/** todo note on ARM port we call this anyway for single core, but it seems unnecessary */
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
return taskENTER_CRITICAL_FROM_ISR();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* todo need to move portASM.s back into portasm.c so we can inline this */
|
||||
void callTaskExitCriticalFromISR(UBaseType_t uxSavedInterruptStatus) {
|
||||
/** todo note on ARM port we call this anyway for single core, but it seems unnecessary */
|
||||
#if ( configNUMBER_OF_CORES > 1 )
|
||||
taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
|
||||
#endif
|
||||
}
|
||||
+461
@@ -0,0 +1,461 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* The FreeRTOS kernel's RISC-V port is split between the the code that is
|
||||
* common across all currently supported RISC-V chips (implementations of the
|
||||
* RISC-V ISA), and code which tailors the port to a specific RISC-V chip:
|
||||
*
|
||||
* + The code that is common to all RISC-V chips is implemented in
|
||||
* FreeRTOS\Source\portable\GCC\RISC-V-RV32\portASM.S. There is only one
|
||||
* portASM.S file because the same file is used no matter which RISC-V chip is
|
||||
* in use.
|
||||
*
|
||||
* + The code that tailors the kernel's RISC-V port to a specific RISC-V
|
||||
* chip is implemented in freertos_risc_v_chip_specific_extensions.h. There
|
||||
* is one freertos_risc_v_chip_specific_extensions.h that can be used with any
|
||||
* RISC-V chip that both includes a standard CLINT and does not add to the
|
||||
* base set of RISC-V registers. There are additional
|
||||
* freertos_risc_v_chip_specific_extensions.h files for RISC-V implementations
|
||||
* that do not include a standard CLINT or do add to the base set of RISC-V
|
||||
* registers.
|
||||
*
|
||||
* CARE MUST BE TAKEN TO INCLDUE THE CORRECT
|
||||
* freertos_risc_v_chip_specific_extensions.h HEADER FILE FOR THE CHIP
|
||||
* IN USE. To include the correct freertos_risc_v_chip_specific_extensions.h
|
||||
* header file ensure the path to the correct header file is in the assembler's
|
||||
* include path.
|
||||
*
|
||||
* This freertos_risc_v_chip_specific_extensions.h is for use on RISC-V chips
|
||||
* that include a standard CLINT and do not add to the base set of RISC-V
|
||||
* registers.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "portContext.h"
|
||||
|
||||
/* Check the freertos_risc_v_chip_specific_extensions.h and/or command line
|
||||
definitions. */
|
||||
#if defined( portasmHAS_CLINT ) && defined( portasmHAS_MTIME )
|
||||
#error The portasmHAS_CLINT constant has been deprecated. Please replace it with portasmHAS_MTIME. portasmHAS_CLINT and portasmHAS_MTIME cannot both be defined at once. See https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html
|
||||
#endif
|
||||
|
||||
#ifdef portasmHAS_CLINT
|
||||
#warning The portasmHAS_CLINT constant has been deprecated. Please replace it with portasmHAS_MTIME and portasmHAS_SIFIVE_CLINT. For now portasmHAS_MTIME and portasmHAS_SIFIVE_CLINT are derived from portasmHAS_CLINT. See https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html
|
||||
#define portasmHAS_MTIME portasmHAS_CLINT
|
||||
#define portasmHAS_SIFIVE_CLINT portasmHAS_CLINT
|
||||
#endif
|
||||
|
||||
#ifndef portasmHAS_MTIME
|
||||
#error freertos_risc_v_chip_specific_extensions.h must define portasmHAS_MTIME to either 1 (MTIME clock present) or 0 (MTIME clock not present). See https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html
|
||||
#endif
|
||||
|
||||
#ifndef portasmHAS_SIFIVE_CLINT
|
||||
#define portasmHAS_SIFIVE_CLINT 0
|
||||
#endif
|
||||
|
||||
.global xPortStartFirstTask
|
||||
.global pxPortInitialiseStack
|
||||
.global freertos_risc_v_trap_handler
|
||||
.global freertos_risc_v_exception_handler
|
||||
.global freertos_risc_v_interrupt_handler
|
||||
.global freertos_risc_v_mtimer_interrupt_handler
|
||||
|
||||
.extern vTaskSwitchContext
|
||||
.extern xTaskIncrementTick
|
||||
.extern pullMachineTimerCompareRegister
|
||||
.extern pullNextTime
|
||||
.extern uxTimerIncrementsForOneTick /* size_t type so 32-bit on 32-bit core and 64-bits on 64-bit core. */
|
||||
.extern xTaskReturnAddress
|
||||
|
||||
.weak freertos_risc_v_application_exception_handler
|
||||
.weak freertos_risc_v_application_interrupt_handler
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
.macro portUPDATE_MTIMER_COMPARE_REGISTER
|
||||
load_x a0, pullMachineTimerCompareRegister /* Load address of compare register into a0. */
|
||||
load_x a1, pullNextTime /* Load the address of ullNextTime into a1. */
|
||||
|
||||
#if( __riscv_xlen == 32 )
|
||||
|
||||
/* Update the 64-bit mtimer compare match value in two 32-bit writes. */
|
||||
li a4, -1
|
||||
lw a2, 0(a1) /* Load the low word of ullNextTime into a2. */
|
||||
lw a3, 4(a1) /* Load the high word of ullNextTime into a3. */
|
||||
sw a4, 0(a0) /* Low word no smaller than old value to start with - will be overwritten below. */
|
||||
sw a3, 4(a0) /* Store high word of ullNextTime into compare register. No smaller than new value. */
|
||||
sw a2, 0(a0) /* Store low word of ullNextTime into compare register. */
|
||||
lw t0, uxTimerIncrementsForOneTick /* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */
|
||||
add a4, t0, a2 /* Add the low word of ullNextTime to the timer increments for one tick (assumes timer increment for one tick fits in 32-bits). */
|
||||
sltu t1, a4, a2 /* See if the sum of low words overflowed (what about the zero case?). */
|
||||
add t2, a3, t1 /* Add overflow to high word of ullNextTime. */
|
||||
sw a4, 0(a1) /* Store new low word of ullNextTime. */
|
||||
sw t2, 4(a1) /* Store new high word of ullNextTime. */
|
||||
|
||||
#endif /* __riscv_xlen == 32 */
|
||||
|
||||
#if( __riscv_xlen == 64 )
|
||||
|
||||
/* Update the 64-bit mtimer compare match value. */
|
||||
ld t2, 0(a1) /* Load ullNextTime into t2. */
|
||||
sd t2, 0(a0) /* Store ullNextTime into compare register. */
|
||||
ld t0, uxTimerIncrementsForOneTick /* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */
|
||||
add t4, t0, t2 /* Add ullNextTime to the timer increments for one tick. */
|
||||
sd t4, 0(a1) /* Store ullNextTime. */
|
||||
|
||||
#endif /* __riscv_xlen == 64 */
|
||||
.endm
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Unlike other ports pxPortInitialiseStack() is written in assembly code as it
|
||||
* needs access to the portasmADDITIONAL_CONTEXT_SIZE constant. The prototype
|
||||
* for the function is as per the other ports:
|
||||
* StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters );
|
||||
*
|
||||
* As per the standard RISC-V ABI pxTopOfStack is passed in in a0, pxCode in
|
||||
* a1, and pvParameters in a2. The new top of stack is passed out in a0.
|
||||
*
|
||||
* RISC-V maps registers to ABI names as follows (X1 to X31 integer registers
|
||||
* for the 'I' profile, X1 to X15 for the 'E' profile, currently I assumed).
|
||||
*
|
||||
* Register ABI Name Description Saver
|
||||
* x0 zero Hard-wired zero -
|
||||
* x1 ra Return address Caller
|
||||
* x2 sp Stack pointer Callee
|
||||
* x3 gp Global pointer -
|
||||
* x4 tp Thread pointer -
|
||||
* x5-7 t0-2 Temporaries Caller
|
||||
* x8 s0/fp Saved register/Frame pointer Callee
|
||||
* x9 s1 Saved register Callee
|
||||
* x10-11 a0-1 Function Arguments/return values Caller
|
||||
* x12-17 a2-7 Function arguments Caller
|
||||
* x18-27 s2-11 Saved registers Callee
|
||||
* x28-31 t3-6 Temporaries Caller
|
||||
*
|
||||
* The RISC-V context is saved to FreeRTOS tasks in the following stack frame,
|
||||
* where the global and thread pointers are currently assumed to be constant so
|
||||
* are not saved:
|
||||
*
|
||||
* mstatus
|
||||
* xCriticalNesting
|
||||
* x31
|
||||
* x30
|
||||
* x29
|
||||
* x28
|
||||
* x27
|
||||
* x26
|
||||
* x25
|
||||
* x24
|
||||
* x23
|
||||
* x22
|
||||
* x21
|
||||
* x20
|
||||
* x19
|
||||
* x18
|
||||
* x17
|
||||
* x16
|
||||
* x15
|
||||
* x14
|
||||
* x13
|
||||
* x12
|
||||
* x11
|
||||
* pvParameters
|
||||
* x9
|
||||
* x8
|
||||
* x7
|
||||
* x6
|
||||
* x5
|
||||
* portTASK_RETURN_ADDRESS
|
||||
* [chip specific registers go here]
|
||||
* pxCode
|
||||
*/
|
||||
pxPortInitialiseStack:
|
||||
csrr t0, mstatus /* Obtain current mstatus value. */
|
||||
andi t0, t0, ~0x8 /* Ensure interrupts are disabled when the stack is restored within an ISR. Required when a task is created after the schedulre has been started, otherwise interrupts would be disabled anyway. */
|
||||
addi t1, x0, 0x188 /* Generate the value 0x1880, which are the MPIE and MPP bits to set in mstatus. */
|
||||
slli t1, t1, 4
|
||||
or t0, t0, t1 /* Set MPIE and MPP bits in mstatus value. */
|
||||
|
||||
addi a0, a0, -portWORD_SIZE
|
||||
store_x t0, 0(a0) /* mstatus onto the stack. */
|
||||
addi a0, a0, -portWORD_SIZE /* Space for critical nesting count. */
|
||||
store_x x0, 0(a0) /* Critical nesting count starts at 0 for every task. */
|
||||
|
||||
#ifdef __riscv_32e
|
||||
addi a0, a0, -(6 * portWORD_SIZE) /* Space for registers x10-x15. */
|
||||
#else
|
||||
addi a0, a0, -(22 * portWORD_SIZE) /* Space for registers x10-x31. */
|
||||
#endif
|
||||
store_x a2, 0(a0) /* Task parameters (pvParameters parameter) goes into register X10/a0 on the stack. */
|
||||
addi a0, a0, -(6 * portWORD_SIZE) /* Space for registers x5-x9 + taskReturnAddress. */
|
||||
load_x t0, xTaskReturnAddress
|
||||
store_x t0, 0(a0) /* Return address onto the stack. */
|
||||
addi t0, x0, portasmADDITIONAL_CONTEXT_SIZE /* The number of chip specific additional registers. */
|
||||
chip_specific_stack_frame: /* First add any chip specific registers to the stack frame being created. */
|
||||
beq t0, x0, 1f /* No more chip specific registers to save. */
|
||||
addi a0, a0, -portWORD_SIZE /* Make space for chip specific register. */
|
||||
store_x x0, 0(a0) /* Give the chip specific register an initial value of zero. */
|
||||
addi t0, t0, -1 /* Decrement the count of chip specific registers remaining. */
|
||||
j chip_specific_stack_frame /* Until no more chip specific registers. */
|
||||
1:
|
||||
addi a0, a0, -portWORD_SIZE
|
||||
store_x a1, 0(a0) /* mret value (pxCode parameter) onto the stack. */
|
||||
ret
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xPortStartFirstTask:
|
||||
portcontextGET_CORE_ID x7
|
||||
portcontextGET_CURRENT_TCB_FOR_CORE x7, sp
|
||||
load_x sp, 0( sp ) /* Read sp from first TCB member. */
|
||||
load_x x1, 0( sp ) /* Note for starting the scheduler the exception return address is used as the function return address. */
|
||||
|
||||
portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
|
||||
|
||||
load_x x7, 4 * portWORD_SIZE( sp ) /* t2 */
|
||||
load_x x8, 5 * portWORD_SIZE( sp ) /* s0/fp */
|
||||
load_x x9, 6 * portWORD_SIZE( sp ) /* s1 */
|
||||
load_x x10, 7 * portWORD_SIZE( sp ) /* a0 */
|
||||
load_x x11, 8 * portWORD_SIZE( sp ) /* a1 */
|
||||
load_x x12, 9 * portWORD_SIZE( sp ) /* a2 */
|
||||
load_x x13, 10 * portWORD_SIZE( sp ) /* a3 */
|
||||
load_x x14, 11 * portWORD_SIZE( sp ) /* a4 */
|
||||
load_x x15, 12 * portWORD_SIZE( sp ) /* a5 */
|
||||
#ifndef __riscv_32e
|
||||
load_x x16, 13 * portWORD_SIZE( sp ) /* a6 */
|
||||
load_x x17, 14 * portWORD_SIZE( sp ) /* a7 */
|
||||
load_x x18, 15 * portWORD_SIZE( sp ) /* s2 */
|
||||
load_x x19, 16 * portWORD_SIZE( sp ) /* s3 */
|
||||
load_x x20, 17 * portWORD_SIZE( sp ) /* s4 */
|
||||
load_x x21, 18 * portWORD_SIZE( sp ) /* s5 */
|
||||
load_x x22, 19 * portWORD_SIZE( sp ) /* s6 */
|
||||
load_x x23, 20 * portWORD_SIZE( sp ) /* s7 */
|
||||
load_x x24, 21 * portWORD_SIZE( sp ) /* s8 */
|
||||
load_x x25, 22 * portWORD_SIZE( sp ) /* s9 */
|
||||
load_x x26, 23 * portWORD_SIZE( sp ) /* s10 */
|
||||
load_x x27, 24 * portWORD_SIZE( sp ) /* s11 */
|
||||
load_x x28, 25 * portWORD_SIZE( sp ) /* t3 */
|
||||
load_x x29, 26 * portWORD_SIZE( sp ) /* t4 */
|
||||
load_x x30, 27 * portWORD_SIZE( sp ) /* t5 */
|
||||
load_x x31, 28 * portWORD_SIZE( sp ) /* t6 */
|
||||
#endif
|
||||
|
||||
/* Load the address of xCriticalNesting into x6. */
|
||||
portcontextGET_CORE_ID x5
|
||||
portcontextGET_CRITICAL_NESTING_PTR_FOR_CORE x5, x6
|
||||
|
||||
load_x x5, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Obtain xCriticalNesting value for this task from task's stack. */
|
||||
store_x x5, 0( x6 ) /* Restore the critical nesting value for this task. */
|
||||
|
||||
load_x x5, portMSTATUS_OFFSET * portWORD_SIZE( sp ) /* Initial mstatus into x5 (t0). */
|
||||
addi x5, x5, 0x08 /* Set MIE bit so the first task starts with interrupts enabled - required as returns with ret not eret. */
|
||||
csrrw x0, mstatus, x5 /* Interrupts enabled from here! */
|
||||
|
||||
load_x x5, 2 * portWORD_SIZE( sp ) /* Initial x5 (t0) value. */
|
||||
load_x x6, 3 * portWORD_SIZE( sp ) /* Initial x6 (t1) value. */
|
||||
|
||||
addi sp, sp, portCONTEXT_SIZE
|
||||
ret
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
freertos_risc_v_application_exception_handler:
|
||||
csrr t0, mcause /* For viewing in the debugger only. */
|
||||
csrr t1, mepc /* For viewing in the debugger only */
|
||||
csrr t2, mstatus /* For viewing in the debugger only */
|
||||
j .
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
freertos_risc_v_application_interrupt_handler:
|
||||
csrr t0, mcause /* For viewing in the debugger only. */
|
||||
csrr t1, mepc /* For viewing in the debugger only */
|
||||
csrr t2, mstatus /* For viewing in the debugger only */
|
||||
j .
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
.section .text.freertos_risc_v_exception_handler
|
||||
freertos_risc_v_exception_handler:
|
||||
portcontextSAVE_EXCEPTION_CONTEXT
|
||||
/* a0 now contains mcause. */
|
||||
li t0, 11 /* 11 == environment call. */
|
||||
bne a0, t0, other_exception /* Not an M environment call, so some other exception. */
|
||||
#if configNUMBER_OF_CORES != 1
|
||||
portcontextGET_CORE_ID a0
|
||||
#endif
|
||||
call vTaskSwitchContext
|
||||
portcontextRESTORE_CONTEXT
|
||||
|
||||
other_exception:
|
||||
call freertos_risc_v_application_exception_handler
|
||||
portcontextRESTORE_CONTEXT
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
.section .time_critical.freertos_risc_v_interrupt_handler
|
||||
freertos_risc_v_interrupt_handler:
|
||||
portcontextSAVE_INTERRUPT_CONTEXT // note this macro requires s10, s11 to be preserved here
|
||||
// note we replace/recreate the SDK's IRQ mechansim here, since we want to control the exception stacking
|
||||
save_meicontext:
|
||||
// Make sure to set meicontext.clearts to clear+save mie.msie/mtie along
|
||||
// with ext IRQ context. We don't let these preempt ext IRQs because they
|
||||
// clear meicontext.mreteirq, which breaks __get_current_exception().
|
||||
csrrsi s2, RVCSR_MEICONTEXT_OFFSET, RVCSR_MEICONTEXT_CLEARTS_BITS
|
||||
|
||||
get_first_irq:
|
||||
// Sample the current highest-priority active IRQ (left-shifted by 2) from
|
||||
// meinext, and write 1 to meinext.update to update meicontext with the
|
||||
// preemption priority and IRQ number of this IRQ
|
||||
csrrsi a0, RVCSR_MEINEXT_OFFSET, RVCSR_MEINEXT_UPDATE_BITS
|
||||
// MSB will be set if there is no active IRQ at the current priority level
|
||||
bltz a0, no_more_irqs
|
||||
dispatch_irq:
|
||||
#if portcontextALLOW_NESTED_IRQs
|
||||
// Preemption priority was configured by meinext update, so enable preemption:
|
||||
csrsi mstatus, 0x8
|
||||
#endif
|
||||
// <- from this point we can be preempted by a higher-priority interrupt.
|
||||
// meinext is pre-shifted by 2, so only an add is required to index table
|
||||
lui a1, %hi(__soft_vector_table)
|
||||
add a1, a1, a0
|
||||
lw a1, %lo(__soft_vector_table)(a1)
|
||||
jalr ra, a1
|
||||
// note: beware: freertos_risc_v_mtimer_interrupt_handler trashes s0 and s1, but
|
||||
// we require s2, s10, s11 saved.
|
||||
|
||||
#if portcontextALLOW_NESTED_IRQs
|
||||
// Disable IRQs on returning so we can sample the next IRQ
|
||||
csrci mstatus, 0x8
|
||||
#endif
|
||||
get_next_irq:
|
||||
// Get the next-highest-priority IRQ that is active at this level. If
|
||||
// there is such an IRQ, update meicontext with new preemption priority.
|
||||
csrrsi a0, RVCSR_MEINEXT_OFFSET, RVCSR_MEINEXT_UPDATE_BITS
|
||||
// MSB will be set if there is no active IRQ at the current priority level
|
||||
bgez a0, dispatch_irq
|
||||
|
||||
no_more_irqs:
|
||||
csrw RVCSR_MEICONTEXT_OFFSET, s2
|
||||
portcontextRESTORE_INTERUUPT_CONTEXT
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
.section .time_critical.freertos_risc_v_mtimer_interrupt_handler
|
||||
freertos_risc_v_mtimer_interrupt_handler:
|
||||
// we know we are called from freertos_risc_v_interrupt_handler which saves ALL registers
|
||||
// already, and doesn't care about us trashing s0, so we used it instead of stack
|
||||
// to save ra across the calls in this function
|
||||
|
||||
mv s0, ra
|
||||
|
||||
// Clear the interrupt force array bit for the timer IRQ, in case this IRQ
|
||||
// was forced locally rather than actually coming from the timer.
|
||||
//li a0, (1 << ((SIO_IRQ_MTIMECMP % 16) + 16) | (SIO_IRQ_MTIMECMP / 16)
|
||||
//csrc 0xbe2, a0 // 0xbe2: meifa (external interrupt force array)
|
||||
// TODO Graham: the above code is probably unnecessary because the meifa
|
||||
// bit should already have been cleared when we sampled the timer IRQ
|
||||
// from meinext. Suggest to delete it once confirmed to work without.
|
||||
|
||||
portUPDATE_MTIMER_COMPARE_REGISTER
|
||||
|
||||
call callTaskEnterCriticalFromISR
|
||||
|
||||
// we are also allowed to trash s1 by the caller
|
||||
mv s1, a0
|
||||
call xTaskIncrementTick
|
||||
mv a0, s1
|
||||
call callTaskExitCriticalFromISR
|
||||
beqz a0, exit_without_context_switch /* Don't switch context if incrementing tick didn't unblock a task. */
|
||||
|
||||
#if configNUMBER_OF_CORES != 1
|
||||
portcontextGET_CORE_ID a0 // vtTaskSwitch context takes coreID in SMP
|
||||
#endif
|
||||
call vTaskSwitchContext
|
||||
exit_without_context_switch:
|
||||
jr s0
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
.section .time_critical.freertos_risc_v_trap_handler
|
||||
.align 8
|
||||
freertos_risc_v_trap_handler:
|
||||
portcontextSAVE_CONTEXT_INTERNAL
|
||||
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
|
||||
bge a0, x0, synchronous_exception
|
||||
|
||||
asynchronous_interrupt:
|
||||
store_x a1, 0( sp ) /* Asynchronous interrupt so save unmodified exception return address. */
|
||||
portcontextSWITCH_TO_ISR_STACK t0, t1
|
||||
j handle_interrupt
|
||||
|
||||
synchronous_exception:
|
||||
addi a1, a1, 4 /* Synchronous so update exception return address to the instruction after the instruction that generated the exeption. */
|
||||
store_x a1, 0( sp ) /* Save updated exception return address. */
|
||||
portcontextSWITCH_TO_ISR_STACK t0, t1
|
||||
j handle_exception
|
||||
|
||||
handle_interrupt:
|
||||
#if( portasmHAS_MTIME != 0 )
|
||||
|
||||
test_if_mtimer: /* If there is a CLINT then the mtimer is used to generate the tick interrupt. */
|
||||
addi t0, x0, 1
|
||||
slli t0, t0, __riscv_xlen - 1 /* LSB is already set, shift into MSB. Shift 31 on 32-bit or 63 on 64-bit cores. */
|
||||
addi t1, t0, 7 /* 0x8000[]0007 == machine timer interrupt. */
|
||||
bne a0, t1, application_interrupt_handler
|
||||
|
||||
portUPDATE_MTIMER_COMPARE_REGISTER
|
||||
call xTaskIncrementTick
|
||||
beqz a0, processed_source /* Don't switch context if incrementing tick didn't unblock a task. */
|
||||
#if configNUMBER_OF_CORES != 1
|
||||
portcontextGET_CORE_ID a0
|
||||
#endif
|
||||
call vTaskSwitchContext
|
||||
j processed_source
|
||||
|
||||
#endif /* portasmHAS_MTIME */
|
||||
|
||||
application_interrupt_handler:
|
||||
call freertos_risc_v_application_interrupt_handler
|
||||
j processed_source
|
||||
|
||||
handle_exception:
|
||||
/* a0 contains mcause. */
|
||||
li t0, 11 /* 11 == environment call. */
|
||||
bne a0, t0, application_exception_handler /* Not an M environment call, so some other exception. */
|
||||
#if configNUMBER_OF_CORES != 1
|
||||
portcontextGET_CORE_ID a0
|
||||
#endif
|
||||
call vTaskSwitchContext
|
||||
j processed_source
|
||||
|
||||
application_exception_handler:
|
||||
call freertos_risc_v_application_exception_handler
|
||||
j processed_source /* No other exceptions handled yet. */
|
||||
|
||||
processed_source:
|
||||
portcontextRESTORE_CONTEXT
|
||||
/*-----------------------------------------------------------*/
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* The FreeRTOS kernel's RISC-V port is split between the the code that is
|
||||
* common across all currently supported RISC-V chips (implementations of the
|
||||
* RISC-V ISA), and code that tailors the port to a specific RISC-V chip:
|
||||
*
|
||||
* + FreeRTOS\Source\portable\GCC\RISC-V-RV32\portASM.S contains the code that
|
||||
* is common to all currently supported RISC-V chips. There is only one
|
||||
* portASM.S file because the same file is built for all RISC-V target chips.
|
||||
*
|
||||
* + Header files called freertos_risc_v_chip_specific_extensions.h contain the
|
||||
* code that tailors the FreeRTOS kernel's RISC-V port to a specific RISC-V
|
||||
* chip. There are multiple freertos_risc_v_chip_specific_extensions.h files
|
||||
* as there are multiple RISC-V chip implementations.
|
||||
*
|
||||
* !!!NOTE!!!
|
||||
* TAKE CARE TO INCLUDE THE CORRECT freertos_risc_v_chip_specific_extensions.h
|
||||
* HEADER FILE FOR THE CHIP IN USE. This is done using the assembler's (not the
|
||||
* compiler's!) include path. For example, if the chip in use includes a core
|
||||
* local interrupter (CLINT) and does not include any chip specific register
|
||||
* extensions then add the path below to the assembler's include path:
|
||||
* FreeRTOS\Source\portable\GCC\RISC-V-RV32\chip_specific_extensions\RV32I_CLINT_no_extensions
|
||||
*
|
||||
*/
|
||||
+573
@@ -0,0 +1,573 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.4.1
|
||||
* 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!
|
||||
*/
|
||||
|
||||
#include "port.h"
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* TriCore specific includes. */
|
||||
#include <machine/intrinsics.h>
|
||||
#include <machine/cint.h>
|
||||
#include <machine/wdtcon.h>
|
||||
#include <tc38xa/Ifx_reg.h>
|
||||
#include <tc38xa/IfxScu_reg.h>
|
||||
#include "interrupts.h"
|
||||
|
||||
/* Kernel includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "list.h"
|
||||
|
||||
#if configCHECK_FOR_STACK_OVERFLOW > 0
|
||||
#error "Stack checking cannot be used with this port, as, unlike most ports, the pxTopOfStack member of the TCB is consumed CSA. CSA starvation, loosely equivalent to stack overflow, will result in a trap exception."
|
||||
/* The stack pointer is accessible using portCSA_TO_ADDRESS( portCSA_TO_ADDRESS( pxCurrentTCB->pxTopOfStack )[ 0 ] )[ 2 ]; */
|
||||
#endif /* configCHECK_FOR_STACK_OVERFLOW */
|
||||
|
||||
#define CPU_ID (_mfcr(CPU_CORE_ID) & 0x0f)
|
||||
|
||||
static volatile Ifx_STM* STMs[4] = {&MODULE_STM0, &MODULE_STM1, &MODULE_STM2, &MODULE_STM3};
|
||||
static const unsigned short STM_SRCs[4] = {SRC_ID_STM0SR0, SRC_ID_STM1SR0, SRC_ID_STM2SR0, SRC_ID_STM3SR0};
|
||||
static volatile Ifx_INT_SRB* SRBs[4] = {&INT_SRB0, &INT_SRB1, &INT_SRB2, &INT_SRB3};
|
||||
static const unsigned short GPSRs[4] = {SRC_ID_GPSR00, SRC_ID_GPSR10, SRC_ID_GPSR20, SRC_ID_GPSR30};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int PCXI, PSW, A10, A11, D8, D9, D10, D11, A12, A13, A14, A15, D12, D13, D14, D15;
|
||||
} UPPER_CONTEXT;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* System register Definitions. */
|
||||
#define portSYSTEM_PROGRAM_STATUS_WORD ( 0x000008FFUL ) /* Supervisor Mode, MPU Register Set 0 and Call Depth Counting disabled. */
|
||||
#define portINITIAL_PRIVILEGED_PROGRAM_STATUS_WORD ( 0x000014FFUL ) /* IO Level 1, MPU Register Set 1 and Call Depth Counting disabled. */
|
||||
#define portINITIAL_UNPRIVILEGED_PROGRAM_STATUS_WORD ( 0x000010FFUL ) /* IO Level 0, MPU Register Set 1 and Call Depth Counting disabled. */
|
||||
//#define portINITIAL_PCXI_UPPER_CONTEXT_WORD ( 0x00C00000UL ) /* The lower 20 bits identify the CSA address. */
|
||||
//#define portINITIAL_PCXI_UPPER_CONTEXT_WORD ( 0x10300000UL ) // ATENlower 20 bits identify the CSA address. */
|
||||
#define portINITIAL_PCXI_UPPER_CONTEXT_WORD ( 0x00300000UL ) // ATEN, default value as read from the CPU after init
|
||||
#define portINITIAL_SYSCON ( 0x00000000UL ) /* MPU Disable. */
|
||||
|
||||
/* CSA manipulation macros. */
|
||||
#define portCSA_FCX_MASK ( 0x000FFFFFUL )
|
||||
|
||||
/* OS Interrupt and Trap mechanisms. */
|
||||
#define portRESTORE_PSW_MASK ( ~( 0x000000FFUL ) )
|
||||
#define portSYSCALL_TRAP ( 6 )
|
||||
|
||||
/* Each CSA contains 16 words of data. */
|
||||
#define portNUM_WORDS_IN_CSA ( 16 )
|
||||
|
||||
/* The interrupt enable bit in the PCP_SRC register. */
|
||||
#define portENABLE_CPU_INTERRUPT ( 1U << 12U )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Perform any hardware configuration necessary to generate the tick interrupt.
|
||||
*/
|
||||
static void prvSystemTickHandler( int ) __attribute__((longcall));
|
||||
static void prvERUISRHandler( int ) __attribute__((longcall));
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
#define ERUInterruptCoreID 0
|
||||
static void prvSetupERUInterrupt(void);
|
||||
|
||||
/*
|
||||
* Priority 1 interrupt handler for yields pended from an interrupt.
|
||||
*/
|
||||
static void prvInterruptYield( int iTrapIdentification );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* This reference is required by the save/restore context macros. */
|
||||
extern volatile uint32_t *pxCurrentTCB;
|
||||
|
||||
extern TaskHandle_t xTaskHandle0[E_TASKS_CPU0_SIZE];
|
||||
|
||||
/* Precalculate the compare match value at compile time. */
|
||||
static const uint32_t ulCompareMatchValue = ( configPERIPHERAL_CLOCK_HZ / configTICK_RATE_HZ );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
uint32_t *pulUpperCSA = NULL;
|
||||
uint32_t *pulLowerCSA = NULL;
|
||||
|
||||
/* 16 Address Registers (4 Address registers are global), 16 Data
|
||||
Registers, and 3 System Registers.
|
||||
|
||||
There are 3 registers that track the CSAs.
|
||||
FCX points to the head of globally free set of CSAs.
|
||||
PCX for the task needs to point to Lower->Upper->NULL arrangement.
|
||||
LCX points to the last free CSA so that corrective action can be taken.
|
||||
|
||||
Need two CSAs to store the context of a task.
|
||||
The upper context contains D8-D15, A10-A15, PSW and PCXI->NULL.
|
||||
The lower context contains D0-D7, A2-A7, A11 and PCXI->UpperContext.
|
||||
The pxCurrentTCB->pxTopOfStack points to the Lower Context RSLCX matching the initial BISR.
|
||||
The Lower Context points to the Upper Context ready for the return from the interrupt handler.
|
||||
|
||||
The Real stack pointer for the task is stored in the A10 which is restored
|
||||
with the upper context. */
|
||||
|
||||
/* Have to disable interrupts here because the CSAs are going to be
|
||||
manipulated. */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
/* DSync to ensure that buffering is not a problem. */
|
||||
_dsync();
|
||||
|
||||
/* Consume two free CSAs. */
|
||||
pulLowerCSA = portCSA_TO_ADDRESS( __MFCR( $FCX ) );
|
||||
if( NULL != pulLowerCSA )
|
||||
{
|
||||
/* The Lower Links to the Upper. */
|
||||
pulUpperCSA = portCSA_TO_ADDRESS( pulLowerCSA[ 0 ] );
|
||||
}
|
||||
|
||||
/* Check that we have successfully reserved two CSAs. */
|
||||
if( ( NULL != pulLowerCSA ) && ( NULL != pulUpperCSA ) )
|
||||
{
|
||||
/* Remove the two consumed CSAs from the free CSA list. */
|
||||
_disable();
|
||||
_dsync();
|
||||
_mtcr( $FCX, pulUpperCSA[ 0 ] );
|
||||
_isync();
|
||||
_enable();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Simply trigger a context list depletion trap. */
|
||||
_svlcx();
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
/* Clear the upper CSA. */
|
||||
memset( pulUpperCSA, 0, portNUM_WORDS_IN_CSA * sizeof( uint32_t ) );
|
||||
|
||||
/* Upper Context. */
|
||||
pulUpperCSA[ 2 ] = ( uint32_t )pxTopOfStack; /* A10; Stack Return aka Stack Pointer */
|
||||
pulUpperCSA[ 1 ] = portSYSTEM_PROGRAM_STATUS_WORD; /* PSW */
|
||||
|
||||
/* Clear the lower CSA. */
|
||||
memset( pulLowerCSA, 0, portNUM_WORDS_IN_CSA * sizeof( uint32_t ) );
|
||||
|
||||
/* Lower Context. */
|
||||
pulLowerCSA[ 8 ] = ( uint32_t ) pvParameters; /* A4; Address Type Parameter Register */
|
||||
pulLowerCSA[ 1 ] = ( uint32_t ) pxCode; /* A11; Return Address aka RA */
|
||||
|
||||
/* PCXI pointing to the Upper context. */
|
||||
pulLowerCSA[ 0 ] = ( portINITIAL_PCXI_UPPER_CONTEXT_WORD | ( uint32_t ) portADDRESS_TO_CSA( pulUpperCSA ) );
|
||||
|
||||
/* Save the link to the CSA in the top of stack. */
|
||||
pxTopOfStack = (uint32_t * ) portADDRESS_TO_CSA( pulLowerCSA );
|
||||
|
||||
/* DSync to ensure that buffering is not a problem. */
|
||||
_dsync();
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
int32_t xPortStartScheduler( void )
|
||||
{
|
||||
extern void vTrapInstallHandlers( void );
|
||||
uint32_t ulMFCR = 0UL;
|
||||
uint32_t *pulUpperCSA = NULL;
|
||||
uint32_t *pulLowerCSA = NULL;
|
||||
|
||||
/* prevent compiler warnings */
|
||||
(void)pulUpperCSA;
|
||||
|
||||
/* Interrupts at or below configMAX_SYSCALL_INTERRUPT_PRIORITY are disable
|
||||
when this function is called. */
|
||||
|
||||
/* Set-up the ERU interrupt. */
|
||||
prvSetupERUInterrupt();
|
||||
|
||||
/* Set-up the timer interrupt. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Install the Trap Handlers. */
|
||||
// vTrapInstallHandlers();
|
||||
|
||||
/* Install the Syscall Handler for yield calls. */
|
||||
// if( 0 == _install_trap_handler( portSYSCALL_TRAP, prvTrapYield ) )
|
||||
// {
|
||||
// /* Failed to install the yield handler, force an assert. */
|
||||
// configASSERT( ( ( volatile void * ) NULL ) );
|
||||
// }
|
||||
|
||||
/* Enable and install the priority 1 interrupt for pending context switches from an ISR. */
|
||||
InterruptInstall(GPSRs[CPU_ID], prvInterruptYield, configKERNEL_YIELD_PRIORITY, 0); //ATEN
|
||||
|
||||
_disable();
|
||||
|
||||
/* Load the initial SYSCON. */
|
||||
_mtcr( $SYSCON, portINITIAL_SYSCON );
|
||||
_isync();
|
||||
|
||||
/* ENDINIT has already been applied in the 'cstart.c' code. */
|
||||
|
||||
/* Clear the PSW.CDC to enable the use of an RFE without it generating an
|
||||
exception because this code is not genuinely in an exception. */
|
||||
ulMFCR = __MFCR( $PSW );
|
||||
ulMFCR &= portRESTORE_PSW_MASK;
|
||||
_dsync();
|
||||
_mtcr( $PSW, ulMFCR );
|
||||
_isync();
|
||||
|
||||
/* Finally, perform the equivalent of a portRESTORE_CONTEXT() */
|
||||
pulLowerCSA = portCSA_TO_ADDRESS( ( *pxCurrentTCB ) );
|
||||
pulUpperCSA = portCSA_TO_ADDRESS( pulLowerCSA[0] );
|
||||
|
||||
_dsync();
|
||||
_mtcr( $PCXI, *pxCurrentTCB );
|
||||
_isync();
|
||||
_nop();
|
||||
_rslcx();
|
||||
_nop();
|
||||
|
||||
|
||||
/* Return to the first task selected to execute. */
|
||||
__asm volatile( "rfe" );
|
||||
|
||||
/* Will not get here. */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
unsigned short cpuid = CPU_ID;
|
||||
|
||||
// Install handler for timer interrupt & reset interrupt flag
|
||||
STMs[cpuid]->ISCR.U = 1;
|
||||
InterruptInstall(STM_SRCs[cpuid], prvSystemTickHandler, configKERNEL_INTERRUPT_PRIORITY, 0);
|
||||
|
||||
// prepare compare register for first interrupt
|
||||
STMs[cpuid]->CMP[0].U = STMs[cpuid]->TIM0.U + ulCompareMatchValue;
|
||||
STMs[cpuid]->CMCON.U = 31;
|
||||
STMs[cpuid]->OCS.B.SUS = 2;
|
||||
STMs[cpuid]->ICR.B.CMP0EN = 1;
|
||||
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*****************************************************************/
|
||||
static void prvSetupERUInterrupt(void)
|
||||
{
|
||||
unsigned short cpuid = CPU_ID;
|
||||
|
||||
if(cpuid == ERUInterruptCoreID)
|
||||
{
|
||||
SCU_FMR.B.FC0 = 1; //Clear the interrupt flag
|
||||
InterruptInstall(SRC_ID_SCUERU0, prvERUISRHandler, 3, 0); //Load the interrupt routine and priortiy
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
|
||||
static void prvSystemTickHandler( int iArg )
|
||||
{
|
||||
uint32_t ulSavedInterruptMask;
|
||||
uint32_t *pxUpperCSA = NULL;
|
||||
uint32_t xUpperCSA = 0UL;
|
||||
extern volatile uint32_t *pxCurrentTCB;
|
||||
int32_t lYieldRequired;
|
||||
unsigned short cpuid = CPU_ID;
|
||||
|
||||
/* Just to avoid compiler warnings about unused parameters. */
|
||||
( void ) iArg;
|
||||
|
||||
/* Clear the interrupt source. */
|
||||
//STM_ISRR.reg = 1UL; //ATEN
|
||||
|
||||
/* Reload the Compare Match register for X ticks into the future.
|
||||
|
||||
If critical section or interrupt nesting budgets are exceeded, then
|
||||
it is possible that the calculated next compare match value is in the
|
||||
past. If this occurs (unlikely), it is possible that the resulting
|
||||
time slippage will exceed a single tick period. Any adverse effect of
|
||||
this is time bounded by the fact that only the first n bits of the 56 bit
|
||||
STM timer are being used for a compare match, so another compare match
|
||||
will occur after an overflow in just those n bits (not the entire 56 bits).
|
||||
As an example, if the peripheral clock is 75MHz, and the tick rate is 1KHz,
|
||||
a missed tick could result in the next tick interrupt occurring within a
|
||||
time that is 1.7 times the desired period. The fact that this is greater
|
||||
than a single tick period is an effect of using a timer that cannot be
|
||||
automatically reset, in hardware, by the occurrence of a tick interrupt.
|
||||
Changing the tick source to a timer that has an automatic reset on compare
|
||||
match (such as a GPTA timer) will reduce the maximum possible additional
|
||||
period to exactly 1 times the desired period. */
|
||||
|
||||
STMs[cpuid]->CMP[0].U = STMs[cpuid]->TIM0.U + ulCompareMatchValue; //ATEN
|
||||
STMs[cpuid]->ISCR.B.CMP0IRR = 1;
|
||||
//STM_CMP0.reg += ulCompareMatchValue;
|
||||
|
||||
/* Kernel API calls require Critical Sections. */
|
||||
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
/* Increment the Tick. */
|
||||
lYieldRequired = xTaskIncrementTick();
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
|
||||
|
||||
if( lYieldRequired != pdFALSE )
|
||||
{
|
||||
/* Save the context of a task.
|
||||
The upper context is automatically saved when entering a trap or interrupt.
|
||||
Need to save the lower context as well and copy the PCXI CSA ID into
|
||||
pxCurrentTCB->pxTopOfStack. Only Lower Context CSA IDs may be saved to the
|
||||
TCB of a task.
|
||||
|
||||
Call vTaskSwitchContext to select the next task, note that this changes the
|
||||
value of pxCurrentTCB so that it needs to be reloaded.
|
||||
|
||||
Call vPortSetMPURegisterSetOne to change the MPU mapping for the task
|
||||
that has just been switched in.
|
||||
|
||||
Load the context of the task.
|
||||
Need to restore the lower context by loading the CSA from
|
||||
pxCurrentTCB->pxTopOfStack into PCXI (effectively changing the call stack).
|
||||
In the Interrupt handler post-amble, RSLCX will restore the lower context
|
||||
of the task. RFE will restore the upper context of the task, jump to the
|
||||
return address and restore the previous state of interrupts being
|
||||
enabled/disabled. */
|
||||
_disable();
|
||||
_dsync();
|
||||
xUpperCSA = __MFCR( $PCXI );
|
||||
pxUpperCSA = portCSA_TO_ADDRESS( xUpperCSA );
|
||||
*pxCurrentTCB = pxUpperCSA[ 0 ];
|
||||
vTaskSwitchContext();
|
||||
pxUpperCSA[ 0 ] = *pxCurrentTCB;
|
||||
SRBs[cpuid]->B.TRIG0 = 0; //ATEN
|
||||
//CPU_SRC0.bits.SETR = 0;
|
||||
_isync();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvERUISRHandler( int iArg )
|
||||
{
|
||||
BaseType_t checkIfYieldRequired;
|
||||
/* Just to avoid compiler warnings about unused parameters. */
|
||||
( void ) iArg;
|
||||
|
||||
SCU_FMR.B.FC0 = 1; //Clear the interrupt flag
|
||||
|
||||
checkIfYieldRequired = xTaskResumeFromISR(xTaskHandle0[E_FPGA_TASK]); //Check the state of the FPGA task
|
||||
portYIELD_FROM_ISR(checkIfYieldRequired); //Yield the FPGA task if it was suspended
|
||||
}
|
||||
|
||||
/*
|
||||
* When a task is deleted, it is yielded permanently until the IDLE task
|
||||
* has an opportunity to reclaim the memory that that task was using.
|
||||
* Typically, the memory used by a task is the TCB and Stack but in the
|
||||
* TriCore this includes the CSAs that were consumed as part of the Call
|
||||
* Stack. These CSAs can only be returned to the Globally Free Pool when
|
||||
* they are not part of the current Call Stack, hence, delaying the
|
||||
* reclamation until the IDLE task is freeing the task's other resources.
|
||||
* This function uses the head of the linked list of CSAs (from when the
|
||||
* task yielded for the last time) and finds the tail (the very bottom of
|
||||
* the call stack) and inserts this list at the head of the Free list,
|
||||
* attaching the existing Free List to the tail of the reclaimed call stack.
|
||||
*
|
||||
* NOTE: the IDLE task needs processing time to complete this function
|
||||
* and in heavily loaded systems, the Free CSAs may be consumed faster
|
||||
* than they can be freed assuming that tasks are being spawned and
|
||||
* deleted frequently.
|
||||
*/
|
||||
void vPortReclaimCSA( uint32_t *pxTCB )
|
||||
{
|
||||
uint32_t pxHeadCSA, pxTailCSA, pxFreeCSA;
|
||||
uint32_t *pulNextCSA;
|
||||
|
||||
/* A pointer to the first CSA in the list of CSAs consumed by the task is
|
||||
stored in the first element of the tasks TCB structure (where the stack
|
||||
pointer would be on a traditional stack based architecture). */
|
||||
pxHeadCSA = ( *pxTCB ) & portCSA_FCX_MASK;
|
||||
|
||||
/* Mask off everything in the CSA link field other than the address. If
|
||||
the address is NULL, then the CSA is not linking anywhere and there is
|
||||
nothing to do. */
|
||||
pxTailCSA = pxHeadCSA;
|
||||
|
||||
/* Convert the link value to contain just a raw address and store this
|
||||
in a local variable. */
|
||||
pulNextCSA = portCSA_TO_ADDRESS( pxTailCSA );
|
||||
|
||||
/* Iterate over the CSAs that were consumed as part of the task. The
|
||||
first field in the CSA is the pointer to then next CSA. Mask off
|
||||
everything in the pointer to the next CSA, other than the link address.
|
||||
If this is NULL, then the CSA currently being pointed to is the last in
|
||||
the chain. */
|
||||
while( 0UL != ( pulNextCSA[ 0 ] & portCSA_FCX_MASK ) )
|
||||
{
|
||||
/* Clear all bits of the pointer to the next in the chain, other
|
||||
than the address bits themselves. */
|
||||
pulNextCSA[ 0 ] = pulNextCSA[ 0 ] & portCSA_FCX_MASK;
|
||||
|
||||
/* Move the pointer to point to the next CSA in the list. */
|
||||
pxTailCSA = pulNextCSA[ 0 ];
|
||||
|
||||
/* Update the local pointer to the CSA. */
|
||||
pulNextCSA = portCSA_TO_ADDRESS( pxTailCSA );
|
||||
}
|
||||
|
||||
_disable();
|
||||
{
|
||||
/* Look up the current free CSA head. */
|
||||
_dsync();
|
||||
pxFreeCSA = __MFCR( $FCX );
|
||||
|
||||
/* Join the current Free onto the Tail of what is being reclaimed. */
|
||||
portCSA_TO_ADDRESS( pxTailCSA )[ 0 ] = pxFreeCSA;
|
||||
|
||||
/* Move the head of the reclaimed into the Free. */
|
||||
_dsync();
|
||||
_mtcr( $FCX, pxHeadCSA );
|
||||
_isync();
|
||||
}
|
||||
_enable();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Nothing to do. Unlikely to want to end. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vTrapSysCallYield( int iTrapIdentification )
|
||||
{
|
||||
uint32_t *pxUpperCSA = NULL;
|
||||
uint32_t xUpperCSA = 0UL;
|
||||
|
||||
extern volatile uint32_t *pxCurrentTCB;
|
||||
|
||||
switch( iTrapIdentification )
|
||||
{
|
||||
case portSYSCALL_TASK_YIELD:
|
||||
/* Save the context of a task.
|
||||
The upper context is automatically saved when entering a trap or interrupt.
|
||||
Need to save the lower context as well and copy the PCXI CSA ID into
|
||||
pxCurrentTCB->pxTopOfStack. Only Lower Context CSA IDs may be saved to the
|
||||
TCB of a task.
|
||||
|
||||
Call vTaskSwitchContext to select the next task, note that this changes the
|
||||
value of pxCurrentTCB so that it needs to be reloaded.
|
||||
|
||||
Call vPortSetMPURegisterSetOne to change the MPU mapping for the task
|
||||
that has just been switched in.
|
||||
|
||||
Load the context of the task.
|
||||
Need to restore the lower context by loading the CSA from
|
||||
pxCurrentTCB->pxTopOfStack into PCXI (effectively changing the call stack).
|
||||
In the Interrupt handler post-amble, RSLCX will restore the lower context
|
||||
of the task. RFE will restore the upper context of the task, jump to the
|
||||
return address and restore the previous state of interrupts being
|
||||
enabled/disabled. */
|
||||
_disable();
|
||||
_dsync();
|
||||
xUpperCSA = __MFCR( $PCXI );
|
||||
pxUpperCSA = portCSA_TO_ADDRESS( xUpperCSA );
|
||||
*pxCurrentTCB = pxUpperCSA[ 0 ];
|
||||
vTaskSwitchContext();
|
||||
pxUpperCSA[ 0 ] = *pxCurrentTCB;
|
||||
SRBs[CPU_ID]->B.TRIG0 = 0; //ATEN
|
||||
// CPU_SRC0.bits.SETR = 0;
|
||||
_isync();
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unimplemented trap called. */
|
||||
configASSERT( ( ( volatile void * ) NULL ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInterruptYield( int iId )
|
||||
{
|
||||
uint32_t *pxUpperCSA = NULL;
|
||||
uint32_t xUpperCSA = 0UL;
|
||||
extern volatile uint32_t *pxCurrentTCB;
|
||||
|
||||
/* Just to remove compiler warnings. */
|
||||
( void ) iId;
|
||||
|
||||
/* Save the context of a task.
|
||||
The upper context is automatically saved when entering a trap or interrupt.
|
||||
Need to save the lower context as well and copy the PCXI CSA ID into
|
||||
pxCurrentTCB->pxTopOfStack. Only Lower Context CSA IDs may be saved to the
|
||||
TCB of a task.
|
||||
|
||||
Call vTaskSwitchContext to select the next task, note that this changes the
|
||||
value of pxCurrentTCB so that it needs to be reloaded.
|
||||
|
||||
Call vPortSetMPURegisterSetOne to change the MPU mapping for the task
|
||||
that has just been switched in.
|
||||
|
||||
Load the context of the task.
|
||||
Need to restore the lower context by loading the CSA from
|
||||
pxCurrentTCB->pxTopOfStack into PCXI (effectively changing the call stack).
|
||||
In the Interrupt handler post-amble, RSLCX will restore the lower context
|
||||
of the task. RFE will restore the upper context of the task, jump to the
|
||||
return address and restore the previous state of interrupts being
|
||||
enabled/disabled. */
|
||||
_disable();
|
||||
_dsync();
|
||||
xUpperCSA = __MFCR( $PCXI );
|
||||
pxUpperCSA = portCSA_TO_ADDRESS( xUpperCSA );
|
||||
*pxCurrentTCB = pxUpperCSA[ 0 ];
|
||||
vTaskSwitchContext();
|
||||
pxUpperCSA[ 0 ] = *pxCurrentTCB;
|
||||
SRBs[CPU_ID]->B.TRIG0 = 0; //ATEN
|
||||
//CPU_SRC0.bits.SETR = 0;
|
||||
_isync();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t uxPortSetInterruptMaskFromISR( void )
|
||||
{
|
||||
uint32_t uxReturn = 0UL;
|
||||
|
||||
_disable();
|
||||
uxReturn = __MFCR( $ICR );
|
||||
_mtcr( $ICR, ( ( uxReturn & ~portCCPN_MASK ) | configMAX_SYSCALL_INTERRUPT_PRIORITY ) );
|
||||
_isync();
|
||||
_enable();
|
||||
|
||||
/* Return just the interrupt mask bits. */
|
||||
return ( uxReturn & portCCPN_MASK );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.4.1
|
||||
* 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!
|
||||
*/
|
||||
|
||||
#ifndef _PORTABLE_GCC_TRICORE_PORT_H_
|
||||
#define _PORTABLE_GCC_TRICORE_PORT_H_
|
||||
|
||||
//These definitions seem to be missing within the TC3xx include files
|
||||
//Compile the project with the "-fdollars-in-identifiers" option!!
|
||||
|
||||
#define $FCX 0xFE38
|
||||
#define $ICR 0xFE2C
|
||||
#define $PCXI 0xFE00
|
||||
#define $PSW 0xFE04
|
||||
#define $SYSCON 0xFE14
|
||||
|
||||
extern void vTrapSysCallYield( int iTrapIdentification );
|
||||
|
||||
#endif /* _PORTABLE_GCC_TRICORE_PORT_H_ */
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.4.1
|
||||
* 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!
|
||||
*/
|
||||
|
||||
#ifndef _PORTABLE_GCC_TRICORE_PORTMACRO_H_
|
||||
#define _PORTABLE_GCC_TRICORE_PORTMACRO_H_
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#include "port.h"
|
||||
|
||||
/* System Includes. */
|
||||
#include <machine/intrinsics.h>
|
||||
#include <tc38xaIfx_reg.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 uint32_t
|
||||
#define portBASE_TYPE unsigned long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 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
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portNOP() __asm volatile( " nop " )
|
||||
#define portCRITICAL_NESTING_IN_TCB 1
|
||||
#define portRESTORE_FIRST_TASK_PRIORITY_LEVEL 1
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
typedef struct MPU_SETTINGS { uint32_t ulNotUsed; } xMPU_SETTINGS;
|
||||
|
||||
/* Define away the instruction from the Restore Context Macro. */
|
||||
#define portPRIVILEGE_BIT 0x0UL
|
||||
|
||||
#define portCCPN_MASK ( 0x000000FFUL )
|
||||
|
||||
extern void vTaskEnterCritical( void );
|
||||
extern void vTaskExitCritical( void );
|
||||
#define portENTER_CRITICAL() vTaskEnterCritical()
|
||||
#define portEXIT_CRITICAL() vTaskExitCritical()
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* CSA Manipulation. */
|
||||
#define portCSA_TO_ADDRESS( pCSA ) ( ( uint32_t * )( ( ( ( pCSA ) & 0x000F0000 ) << 12 ) | ( ( ( pCSA ) & 0x0000FFFF ) << 6 ) ) )
|
||||
#define portADDRESS_TO_CSA( pAddress ) ( ( uint32_t )( ( ( ( (uint32_t)( pAddress ) ) & 0xF0000000 ) >> 12 ) | ( ( ( uint32_t )( pAddress ) & 0x003FFFC0 ) >> 6 ) ) )
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#define portYIELD() _syscall( 0 )
|
||||
/* Port Restore is implicit in the platform when the function is returned from the original PSW is automatically replaced. */
|
||||
#define portSYSCALL_TASK_YIELD 0
|
||||
#define portSYSCALL_RAISE_PRIORITY 1
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
|
||||
/* Set ICR.CCPN to configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
#define portDISABLE_INTERRUPTS() { \
|
||||
uint32_t ulICR; \
|
||||
_disable(); \
|
||||
ulICR = __MFCR( $ICR ); /* Get current ICR value. */ \
|
||||
ulICR &= ~portCCPN_MASK; /* Clear down mask bits. */ \
|
||||
ulICR |= configMAX_SYSCALL_INTERRUPT_PRIORITY; /* Set mask bits to required priority mask. */ \
|
||||
_mtcr( $ICR, ulICR ); /* Write back updated ICR. */ \
|
||||
_isync(); \
|
||||
_enable(); \
|
||||
}
|
||||
|
||||
/* Clear ICR.CCPN to allow all interrupt priorities. */
|
||||
#define portENABLE_INTERRUPTS() { \
|
||||
uint32_t ulICR; \
|
||||
_disable(); \
|
||||
ulICR = __MFCR( $ICR ); /* Get current ICR value. */ \
|
||||
ulICR &= ~portCCPN_MASK; /* Clear down mask bits. */ \
|
||||
_mtcr( $ICR, ulICR ); /* Write back updated ICR. */ \
|
||||
_isync(); \
|
||||
_enable(); \
|
||||
}
|
||||
|
||||
/* Set ICR.CCPN to uxSavedMaskValue. */
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedMaskValue ) { \
|
||||
uint32_t ulICR; \
|
||||
_disable(); \
|
||||
ulICR = __MFCR( $ICR ); /* Get current ICR value. */ \
|
||||
ulICR &= ~portCCPN_MASK; /* Clear down mask bits. */ \
|
||||
ulICR |= uxSavedMaskValue; /* Set mask bits to previously saved mask value. */ \
|
||||
_mtcr( $ICR, ulICR ); /* Write back updated ICR. */ \
|
||||
_isync(); \
|
||||
_enable(); \
|
||||
}
|
||||
|
||||
|
||||
/* Set ICR.CCPN to configMAX_SYSCALL_INTERRUPT_PRIORITY */
|
||||
extern uint32_t uxPortSetInterruptMaskFromISR( void );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMaskFromISR()
|
||||
|
||||
/* Pend a priority 1 interrupt, which will take care of the context switch. */
|
||||
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken != pdFALSE ) { _isync(); }
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Port specific clean up macro required to free the CSAs that were consumed by
|
||||
* a task that has since been deleted.
|
||||
*/
|
||||
void vPortReclaimCSA( uint32_t *pxTCB );
|
||||
#define portCLEAN_UP_TCB( pxTCB ) vPortReclaimCSA( ( uint32_t * ) ( pxTCB ) )
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* _PORTABLE_GCC_TRICORE_PORTMACRO_H_ */
|
||||
+281
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.4.1
|
||||
* 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!
|
||||
*/
|
||||
|
||||
/* Kernel includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* Machine includes */
|
||||
#include <machine/intrinsics.h>
|
||||
#include <machine/cint.h>
|
||||
#include <tc38xa/Ifx_reg.h>
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* This reference is required by the Save/Restore Context Macros.
|
||||
*/
|
||||
extern volatile uint32_t *pxCurrentTCB;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* This file contains base definitions for all of the possible traps in the system.
|
||||
* It is suggested to provide implementations for all of the traps but for
|
||||
* the time being they simply trigger a DEBUG instruction so that it is easy
|
||||
* to see what caused a particular trap.
|
||||
*
|
||||
* Trap Class 6, the SYSCALL, is used exclusively by the operating system.
|
||||
*/
|
||||
|
||||
/* The Trap Classes. */
|
||||
#define portMMU_TRAP 0
|
||||
#define portIPT_TRAP 1
|
||||
#define portIE_TRAP 2
|
||||
#define portCM_TRAP 3
|
||||
#define portSBP_TRAP 4
|
||||
#define portASSERT_TRAP 5
|
||||
#define portNMI_TRAP 7
|
||||
|
||||
/* MMU Trap Identifications. */
|
||||
#define portTIN_MMU_VIRTUAL_ADDRESS_FILL 0
|
||||
#define portTIN_MMU_VIRTUAL_ADDRESS_PROTECTION 1
|
||||
|
||||
/* Internal Protection Trap Identifications. */
|
||||
#define portTIN_IPT_PRIVILIGED_INSTRUCTION 1
|
||||
#define portTIN_IPT_MEMORY_PROTECTION_READ 2
|
||||
#define portTIN_IPT_MEMORY_PROTECTION_WRITE 3
|
||||
#define portTIN_IPT_MEMORY_PROTECTION_EXECUTION 4
|
||||
#define portTIN_IPT_MEMORY_PROTECTION_PERIPHERAL_ACCESS 5
|
||||
#define portTIN_IPT_MEMORY_PROTECTION_NULL_ADDRESS 6
|
||||
#define portTIN_IPT_MEMORY_PROTECTION_GLOBAL_REGISTER_WRITE_PROTECTION 7
|
||||
|
||||
/* Instruction Error Trap Identifications. */
|
||||
#define portTIN_IE_ILLEGAL_OPCODE 1
|
||||
#define portTIN_IE_UNIMPLEMENTED_OPCODE 2
|
||||
#define portTIN_IE_INVALID_OPERAND 3
|
||||
#define portTIN_IE_DATA_ADDRESS_ALIGNMENT 4
|
||||
#define portTIN_IE_INVALID_LOCAL_MEMORY_ADDRESS 5
|
||||
|
||||
/* Context Management Trap Identifications. */
|
||||
#define portTIN_CM_FREE_CONTEXT_LIST_DEPLETION 1
|
||||
#define portTIN_CM_CALL_DEPTH_OVERFLOW 2
|
||||
#define portTIN_CM_CALL_DEPTH_UNDEFLOW 3
|
||||
#define portTIN_CM_FREE_CONTEXT_LIST_UNDERFLOW 4
|
||||
#define portTIN_CM_CALL_STACK_UNDERFLOW 5
|
||||
#define portTIN_CM_CONTEXT_TYPE 6
|
||||
#define portTIN_CM_NESTING_ERROR 7
|
||||
|
||||
/* System Bus and Peripherals Trap Identifications. */
|
||||
#define portTIN_SBP_PROGRAM_FETCH_SYNCHRONOUS_ERROR 1
|
||||
#define portTIN_SBP_DATA_ACCESS_SYNCHRONOUS_ERROR 2
|
||||
#define portTIN_SBP_DATA_ACCESS_ASYNCHRONOUS_ERROR 3
|
||||
#define portTIN_SBP_COPROCESSOR_TRAP_ASYNCHRONOUS_ERROR 4
|
||||
#define portTIN_SBP_PROGRAM_MEMORY_INTEGRITY_ERROR 5
|
||||
#define portTIN_SBP_DATA_MEMORY_INTEGRITY_ERROR 6
|
||||
|
||||
/* Assertion Trap Identifications. */
|
||||
#define portTIN_ASSERT_ARITHMETIC_OVERFLOW 1
|
||||
#define portTIN_ASSERT_STICKY_ARITHMETIC_OVERFLOW 2
|
||||
|
||||
/* Non-maskable Interrupt Trap Identifications. */
|
||||
#define portTIN_NMI_NON_MASKABLE_INTERRUPT 0
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void vMMUTrap( int iTrapIdentification ) __attribute__( ( longcall, weak ) );
|
||||
void vInternalProtectionTrap( int iTrapIdentification ) __attribute__( ( longcall, weak ) );
|
||||
void vInstructionErrorTrap( int iTrapIdentification ) __attribute__( ( longcall, weak ) );
|
||||
void vContextManagementTrap( int iTrapIdentification ) __attribute__( ( longcall, weak ) );
|
||||
void vSystemBusAndPeripheralsTrap( int iTrapIdentification ) __attribute__( ( longcall, weak ) );
|
||||
void vAssertionTrap( int iTrapIdentification ) __attribute__( ( longcall, weak ) );
|
||||
void vNonMaskableInterruptTrap( int iTrapIdentification ) __attribute__( ( longcall, weak ) );
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void vTrapInstallHandlers( void )
|
||||
{
|
||||
if( 0 == _install_trap_handler ( portMMU_TRAP, vMMUTrap ) )
|
||||
{
|
||||
_debug();
|
||||
}
|
||||
|
||||
if( 0 == _install_trap_handler ( portIPT_TRAP, vInternalProtectionTrap ) )
|
||||
{
|
||||
_debug();
|
||||
}
|
||||
|
||||
if( 0 == _install_trap_handler ( portIE_TRAP, vInstructionErrorTrap ) )
|
||||
{
|
||||
_debug();
|
||||
}
|
||||
|
||||
if( 0 == _install_trap_handler ( portCM_TRAP, vContextManagementTrap ) )
|
||||
{
|
||||
_debug();
|
||||
}
|
||||
|
||||
if( 0 == _install_trap_handler ( portSBP_TRAP, vSystemBusAndPeripheralsTrap ) )
|
||||
{
|
||||
_debug();
|
||||
}
|
||||
|
||||
if( 0 == _install_trap_handler ( portASSERT_TRAP, vAssertionTrap ) )
|
||||
{
|
||||
_debug();
|
||||
}
|
||||
|
||||
if( 0 == _install_trap_handler ( portNMI_TRAP, vNonMaskableInterruptTrap ) )
|
||||
{
|
||||
_debug();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vMMUTrap( int iTrapIdentification )
|
||||
{
|
||||
switch( iTrapIdentification )
|
||||
{
|
||||
case portTIN_MMU_VIRTUAL_ADDRESS_FILL:
|
||||
case portTIN_MMU_VIRTUAL_ADDRESS_PROTECTION:
|
||||
default:
|
||||
_debug();
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void vInternalProtectionTrap( int iTrapIdentification )
|
||||
{
|
||||
/* Deliberate fall through to default. */
|
||||
switch( iTrapIdentification )
|
||||
{
|
||||
case portTIN_IPT_PRIVILIGED_INSTRUCTION:
|
||||
/* Instruction is not allowed at current execution level, eg DISABLE at User-0. */
|
||||
|
||||
case portTIN_IPT_MEMORY_PROTECTION_READ:
|
||||
/* Load word using invalid address. */
|
||||
|
||||
case portTIN_IPT_MEMORY_PROTECTION_WRITE:
|
||||
/* Store Word using invalid address. */
|
||||
|
||||
case portTIN_IPT_MEMORY_PROTECTION_EXECUTION:
|
||||
/* PC jumped to an address outside of the valid range. */
|
||||
|
||||
case portTIN_IPT_MEMORY_PROTECTION_PERIPHERAL_ACCESS:
|
||||
/* Access to a peripheral denied at current execution level. */
|
||||
|
||||
case portTIN_IPT_MEMORY_PROTECTION_NULL_ADDRESS:
|
||||
/* NULL Pointer. */
|
||||
|
||||
case portTIN_IPT_MEMORY_PROTECTION_GLOBAL_REGISTER_WRITE_PROTECTION:
|
||||
/* Tried to modify a global address pointer register. */
|
||||
|
||||
default:
|
||||
|
||||
pxCurrentTCB[ 0 ] = __MFCR( $PCXI );
|
||||
_debug();
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void vInstructionErrorTrap( int iTrapIdentification )
|
||||
{
|
||||
/* Deliberate fall through to default. */
|
||||
switch( iTrapIdentification )
|
||||
{
|
||||
case portTIN_IE_ILLEGAL_OPCODE:
|
||||
case portTIN_IE_UNIMPLEMENTED_OPCODE:
|
||||
case portTIN_IE_INVALID_OPERAND:
|
||||
case portTIN_IE_DATA_ADDRESS_ALIGNMENT:
|
||||
case portTIN_IE_INVALID_LOCAL_MEMORY_ADDRESS:
|
||||
default:
|
||||
_debug();
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void vContextManagementTrap( int iTrapIdentification )
|
||||
{
|
||||
/* Deliberate fall through to default. */
|
||||
switch( iTrapIdentification )
|
||||
{
|
||||
case portTIN_CM_FREE_CONTEXT_LIST_DEPLETION:
|
||||
case portTIN_CM_CALL_DEPTH_OVERFLOW:
|
||||
case portTIN_CM_CALL_DEPTH_UNDEFLOW:
|
||||
case portTIN_CM_FREE_CONTEXT_LIST_UNDERFLOW:
|
||||
case portTIN_CM_CALL_STACK_UNDERFLOW:
|
||||
case portTIN_CM_CONTEXT_TYPE:
|
||||
case portTIN_CM_NESTING_ERROR:
|
||||
default:
|
||||
_debug();
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void vSystemBusAndPeripheralsTrap( int iTrapIdentification )
|
||||
{
|
||||
/* Deliberate fall through to default. */
|
||||
switch( iTrapIdentification )
|
||||
{
|
||||
case portTIN_SBP_PROGRAM_FETCH_SYNCHRONOUS_ERROR:
|
||||
case portTIN_SBP_DATA_ACCESS_SYNCHRONOUS_ERROR:
|
||||
case portTIN_SBP_DATA_ACCESS_ASYNCHRONOUS_ERROR:
|
||||
case portTIN_SBP_COPROCESSOR_TRAP_ASYNCHRONOUS_ERROR:
|
||||
case portTIN_SBP_PROGRAM_MEMORY_INTEGRITY_ERROR:
|
||||
case portTIN_SBP_DATA_MEMORY_INTEGRITY_ERROR:
|
||||
default:
|
||||
_debug();
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void vAssertionTrap( int iTrapIdentification )
|
||||
{
|
||||
/* Deliberate fall through to default. */
|
||||
switch( iTrapIdentification )
|
||||
{
|
||||
case portTIN_ASSERT_ARITHMETIC_OVERFLOW:
|
||||
case portTIN_ASSERT_STICKY_ARITHMETIC_OVERFLOW:
|
||||
default:
|
||||
_debug();
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void vNonMaskableInterruptTrap( int iTrapIdentification )
|
||||
{
|
||||
/* Deliberate fall through to default. */
|
||||
switch( iTrapIdentification )
|
||||
{
|
||||
case portTIN_NMI_NON_MASKABLE_INTERRUPT:
|
||||
default:
|
||||
_debug();
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
+1
@@ -0,0 +1 @@
|
||||
Compile the project with the "-fdollars-in-identifiers" option!!
|
||||
@@ -0,0 +1 @@
|
||||
This repository contains multiple directories, each individually licensed. Please see the LICENSE file in each directory.
|
||||
@@ -0,0 +1,26 @@
|
||||
## FreeRTOS Community Supported Ports
|
||||
|
||||
This repository contains FreeRTOS ports supported by FreeRTOS community members.
|
||||
For a community supported FreeRTOS port:
|
||||
|
||||
* The code has not been reviewed by the FreeRTOS team.
|
||||
* Tests may or may not exist for the FreeRTOS port.
|
||||
* Customer queries as well as bugs are addressed by the community.
|
||||
|
||||
A new FreeRTOS port can be directly contributed by anyone. Follow the steps
|
||||
below to contribute a FreeRTOS port to this repository:
|
||||
|
||||
1. Write FreeRTOS port for your Compiler and Architecture.
|
||||
2. *[Optional]* Create a project in the [FreeRTOS Community Supported Demos Repository](https://github.com/FreeRTOS/FreeRTOS-Community-Supported-Demos/tree/main)
|
||||
for your hardware for running tests as mentioned [here](https://github.com/FreeRTOS/FreeRTOS/blob/main/FreeRTOS/Demo/ThirdParty/Template/README.md).
|
||||
3. *[Optional]* Make sure all the tests pass. Add the test results in the Pull Request description.
|
||||
4. Add a README file with the following information:
|
||||
1. How to use this port?
|
||||
2. *[Optional]* Link to the test project created in Step 2.
|
||||
3. Any other relevant information.
|
||||
5. Raise a pull request to merge the port.
|
||||
6. *[Optional]* Raise another PR to merge the test project in the [FreeRTOS Partner Supported Demos Repository](https://github.com/FreeRTOS/FreeRTOS-Partner-Supported-Demos/tree/main).
|
||||
|
||||
## License
|
||||
|
||||
This repository contains multiple directories, each individually licensed. Please see the LICENSE file in each directory.
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.5.1+
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "include/FreeRTOS.h"
|
||||
|
||||
#if __SDCC
|
||||
#include "include/sdcc/task.h"
|
||||
#elif __SCCZ80
|
||||
#include "include/sccz80/task.h"
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Macros to set up, restart (reload), and stop the PRT1 Timer used for
|
||||
* the System Tick.
|
||||
*/
|
||||
|
||||
#define configTICK_RATE_HZ (256) /* Timer configured */
|
||||
#define configISR_ORG ASMPC /* ISR relocation */
|
||||
#define configISR_IVT 0xFFE6 /* PRT1 address */
|
||||
|
||||
#define configSETUP_TIMER_INTERRUPT() \
|
||||
do{ \
|
||||
__asm__( \
|
||||
"EXTERN __CPU_CLOCK \n" \
|
||||
"EXTERN RLDR1L, RLDR1H \n" \
|
||||
"EXTERN TCR, TCR_TIE1, TCR_TDE1 \n" \
|
||||
"ld de,_timer_isr \n" \
|
||||
"ld hl,"string(configISR_IVT)" ; PRT1 address \n" \
|
||||
"ld (hl),e \n" \
|
||||
"inc hl \n" \
|
||||
"ld (hl),d \n" \
|
||||
"; we do configTICK_RATE_HZ ticks per second \n" \
|
||||
"ld hl,__CPU_CLOCK/"string(configTICK_RATE_HZ)"/20-1 \n" \
|
||||
"out0(RLDR1L),l \n" \
|
||||
"out0(RLDR1H),h \n" \
|
||||
"in0 a,(TCR) \n" \
|
||||
"or TCR_TIE1|TCR_TDE1 \n" \
|
||||
"out0 (TCR),a \n" \
|
||||
); \
|
||||
}while(0)
|
||||
|
||||
#define configRESET_TIMER_INTERRUPT() \
|
||||
do{ \
|
||||
__asm__( \
|
||||
"EXTERN TCR, TMDR1L \n" \
|
||||
"in0 a,(TCR) \n" \
|
||||
"in0 a,(TMDR1L) \n" \
|
||||
); \
|
||||
}while(0)
|
||||
|
||||
#define configSTOP_TIMER_INTERRUPT() \
|
||||
do{ \
|
||||
__asm__( \
|
||||
"EXTERN TCR, TCR_TIE1, TCR_TDE1 \n" \
|
||||
"; disable down counting and interrupts for PRT1\n" \
|
||||
"in0 a,(TCR) \n" \
|
||||
"xor TCR_TIE1|TCR_TDE1 \n" \
|
||||
"out0 (TCR),a \n" \
|
||||
); \
|
||||
}while(0)
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Perform hardware setup to enable ticks from Timer.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void ) __preserves_regs(iyh,iyl);
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
/* Place the parameter on the stack in the expected location. */
|
||||
*pxTopOfStack-- = ( StackType_t ) pvParameters;
|
||||
|
||||
/* Place the task return address on stack. Not used */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0;
|
||||
|
||||
/* The start of the task code will be popped off the stack last, so place
|
||||
it on first. */
|
||||
*pxTopOfStack-- = ( StackType_t ) pxCode;
|
||||
|
||||
/* Now the registers. */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0xAFAF; /* AF */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x0404; /* IF */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0xBCBC; /* BC */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0xDEDE; /* DE */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0xEFEF; /* HL */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0xFAFA; /* AF' */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0xCBCB; /* BC' */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0xEDED; /* DE' */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0xFEFE; /* HL' */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0xCEFA; /* IX */
|
||||
*pxTopOfStack = ( StackType_t ) 0xADDE; /* IY */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void ) __preserves_regs(a,b,c,d,e,iyh,iyl) __naked
|
||||
{
|
||||
/* Setup the relevant timer hardware to generate the tick. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Restore the context of the first task that is going to run. */
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
/* Should not get here. */
|
||||
return pdFALSE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void ) __preserves_regs(b,c,d,e,h,l,iyh,iyl)
|
||||
{
|
||||
/*
|
||||
* It is unlikely that the Z80 port will get stopped.
|
||||
* If required simply disable the tick interrupt here.
|
||||
*/
|
||||
configSTOP_TIMER_INTERRUPT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Manual context switch. The first thing we do is save the registers so we
|
||||
* can use a naked attribute. This is called by the application, so we don't have
|
||||
* to check which bank is loaded.
|
||||
*/
|
||||
void vPortYield( void ) __preserves_regs(a,b,c,d,e,h,l,iyh,iyl) __naked
|
||||
{
|
||||
portSAVE_CONTEXT();
|
||||
vTaskSwitchContext();
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Manual context switch callable from ISRs. The first thing we do is save
|
||||
* the registers so we can use a naked attribute.
|
||||
*/
|
||||
void vPortYieldFromISR(void) __preserves_regs(a,b,c,d,e,h,l,iyh,iyl) __naked
|
||||
void vPortYieldFromISR(void)
|
||||
{
|
||||
portSAVE_CONTEXT_IN_ISR();
|
||||
vTaskSwitchContext();
|
||||
portRESTORE_CONTEXT_IN_ISR();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialize Timer (PRT1 for YAZ180, and SCZ180 HBIOS).
|
||||
*/
|
||||
void prvSetupTimerInterrupt( void ) __preserves_regs(iyh,iyl)
|
||||
{
|
||||
configSETUP_TIMER_INTERRUPT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void timer_isr(void) __preserves_regs(a,b,c,d,e,h,l,iyh,iyl) __naked
|
||||
{
|
||||
#if configUSE_PREEMPTION == 1
|
||||
/*
|
||||
* Tick ISR for preemptive scheduler. We can use a naked attribute as
|
||||
* the context is saved at the start of timer_isr(). The tick
|
||||
* count is incremented after the context is saved.
|
||||
*
|
||||
* Context switch function used by the tick. This must be identical to
|
||||
* vPortYield() from the call to vTaskSwitchContext() onwards. The only
|
||||
* difference from vPortYield() is the tick count is incremented as the
|
||||
* call comes from the tick ISR.
|
||||
*/
|
||||
portSAVE_CONTEXT_IN_ISR();
|
||||
configRESET_TIMER_INTERRUPT();
|
||||
xTaskIncrementTick();
|
||||
vTaskSwitchContext();
|
||||
portRESTORE_CONTEXT_IN_ISR();
|
||||
#else
|
||||
/*
|
||||
* Tick ISR for the cooperative scheduler. All this does is increment the
|
||||
* tick count. We don't need to switch context, this can only be done by
|
||||
* manual calls to taskYIELD();
|
||||
*/
|
||||
portSAVE_CONTEXT_IN_ISR();
|
||||
configRESET_TIMER_INTERRUPT();
|
||||
xTaskIncrementTick();
|
||||
portRESTORE_CONTEXT_IN_ISR();
|
||||
#endif
|
||||
} // configUSE_PREEMPTION
|
||||
+276
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* FreeRTOS Kernel V10.5.1+
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given Z80 (Z180, Z80N) hardware and SCCZ80 or SDCC compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT int
|
||||
|
||||
typedef uint16_t StackType_t;
|
||||
typedef int8_t BaseType_t;
|
||||
typedef uint8_t UBaseType_t;
|
||||
|
||||
#if configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#else
|
||||
#error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width.
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* General purpose stringify macros. */
|
||||
|
||||
#define string(a) __string(a)
|
||||
#define __string(a) #a
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 1
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
|
||||
#define portENTER_CRITICAL() \
|
||||
do{ \
|
||||
__asm__( \
|
||||
"ld a,i \n" \
|
||||
"di \n" \
|
||||
"push af \n" \
|
||||
); \
|
||||
}while(0)
|
||||
|
||||
#define portEXIT_CRITICAL() \
|
||||
do{ \
|
||||
__asm__( \
|
||||
"pop af \n" \
|
||||
"; di ; unneeded \n" \
|
||||
"jp PO,ASMPC+4 \n" \
|
||||
"ei \n" \
|
||||
); \
|
||||
}while(0)
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
do{ \
|
||||
__asm__( \
|
||||
"di \n" \
|
||||
); \
|
||||
}while(0)
|
||||
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
do{ \
|
||||
__asm__( \
|
||||
"ei \n" \
|
||||
); \
|
||||
}while(0)
|
||||
|
||||
#define portNOP() \
|
||||
do{ \
|
||||
__asm__( \
|
||||
"nop \n" \
|
||||
); \
|
||||
}while(0)
|
||||
|
||||
/*
|
||||
* Macros to save all the registers, and save the stack pointer into the TCB.
|
||||
*
|
||||
* The first thing we do is save the flags then disable interrupts. This is to
|
||||
* guard our stack against having a context switch interrupt after we have already
|
||||
* pushed the registers onto the stack.
|
||||
*
|
||||
* The interrupts will have been disabled during the call to portSAVE_CONTEXT()
|
||||
* so we need not worry about reading/writing to the stack pointer.
|
||||
*/
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
do{ \
|
||||
__asm__( \
|
||||
"push af \n" \
|
||||
"ld a,i \n" \
|
||||
"di \n" \
|
||||
"push af ; iff1:iff2\n" \
|
||||
"push bc \n" \
|
||||
"push de \n" \
|
||||
"push hl \n" \
|
||||
"exx \n" \
|
||||
"ex af,af \n" \
|
||||
"push af \n" \
|
||||
"push bc \n" \
|
||||
"push de \n" \
|
||||
"push hl \n" \
|
||||
"push ix \n" \
|
||||
"push iy \n" \
|
||||
"ld hl,0 \n" \
|
||||
"add hl,sp \n" \
|
||||
"ld de,(_pxCurrentTCB) \n"\
|
||||
"ex de,hl \n" \
|
||||
"ld (hl),e \n" \
|
||||
"inc hl \n" \
|
||||
"ld (hl),d \n" \
|
||||
); \
|
||||
}while(0)
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
do{ \
|
||||
__asm__( \
|
||||
"ld hl,(_pxCurrentTCB) \n" \
|
||||
"ld e,(hl) \n" \
|
||||
"inc hl \n" \
|
||||
"ld d,(hl) \n" \
|
||||
"ex de,hl \n" \
|
||||
"ld sp,hl \n" \
|
||||
"pop iy \n" \
|
||||
"pop ix \n" \
|
||||
"pop hl \n" \
|
||||
"pop de \n" \
|
||||
"pop bc \n" \
|
||||
"pop af \n" \
|
||||
"ex af,af \n" \
|
||||
"exx \n" \
|
||||
"pop hl \n" \
|
||||
"pop de \n" \
|
||||
"pop bc \n" \
|
||||
"pop af ; iff1:iff2\n" \
|
||||
"; di ; unneeded \n" \
|
||||
"jp PO,ASMPC+4 \n" \
|
||||
"ei \n" \
|
||||
"pop af \n" \
|
||||
"ret \n" \
|
||||
); \
|
||||
}while(0)
|
||||
|
||||
#define portSAVE_CONTEXT_IN_ISR() \
|
||||
do{ \
|
||||
__asm__( \
|
||||
"PHASE "string(configISR_ORG)" \n" \
|
||||
"._timer_isr_start \n" \
|
||||
"push af \n" \
|
||||
"ld a,0x7F \n" \
|
||||
"inc a ; set PE \n" \
|
||||
"push af ; iff1:iff2\n" \
|
||||
"push bc \n" \
|
||||
"push de \n" \
|
||||
"push hl \n" \
|
||||
"exx \n" \
|
||||
"ex af,af \n" \
|
||||
"push af \n" \
|
||||
"push bc \n" \
|
||||
"push de \n" \
|
||||
"push hl \n" \
|
||||
"push ix \n" \
|
||||
"push iy \n" \
|
||||
"ld hl,0 \n" \
|
||||
"add hl,sp \n" \
|
||||
"ld de,(_pxCurrentTCB) \n" \
|
||||
"ex de,hl \n" \
|
||||
"ld (hl),e \n" \
|
||||
"inc hl \n" \
|
||||
"ld (hl),d \n" \
|
||||
); \
|
||||
}while(0)
|
||||
|
||||
#define portRESTORE_CONTEXT_IN_ISR()\
|
||||
do{ \
|
||||
__asm__( \
|
||||
"ld hl,(_pxCurrentTCB) \n" \
|
||||
"ld e,(hl) \n" \
|
||||
"inc hl \n" \
|
||||
"ld d,(hl) \n" \
|
||||
"ex de,hl \n" \
|
||||
"ld sp,hl \n" \
|
||||
"pop iy \n" \
|
||||
"pop ix \n" \
|
||||
"pop hl \n" \
|
||||
"pop de \n" \
|
||||
"pop bc \n" \
|
||||
"pop af \n" \
|
||||
"ex af,af \n" \
|
||||
"exx \n" \
|
||||
"pop hl \n" \
|
||||
"pop de \n" \
|
||||
"pop bc \n" \
|
||||
"pop af ; iff1:iff2\n" \
|
||||
"; di ; unneeded \n" \
|
||||
"jp PO,ASMPC+4 \n" \
|
||||
"ei \n" \
|
||||
"pop af \n" \
|
||||
"reti \n" \
|
||||
"._timer_isr_end \n" \
|
||||
"DEPHASE \n" \
|
||||
); \
|
||||
}while(0)
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Kernel utilities. */
|
||||
extern void vPortYield( void );
|
||||
#define portYIELD() vPortYield()
|
||||
|
||||
extern void vPortYieldFromISR( void );
|
||||
#define portYIELD_FROM_ISR() vPortYieldFromISR()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
@@ -0,0 +1,13 @@
|
||||
<h1>Z180 support</h1>
|
||||
|
||||
Description
|
||||
-----------
|
||||
This PR establishes support for a Zilog Z180 port, using the Programmable Reload Timer 1, configured at 256 Hz.
|
||||
|
||||
Because of the generality of the Z180, the address of the Interrupt Vector for the programmable timer PRT1 is configurable, and must be configured by the `crt0.asm` outside of this port. A configuration assumption has been made, which should be checked against the actual system environment.
|
||||
|
||||
The two compilers ([used by the z88dk](https://github.com/z88dk/z88dk)) are supported. The sccz80 compiler and the sdcc compiler. The in-line assembly language notation used can be read by both compilers.
|
||||
|
||||
Background
|
||||
-----------
|
||||
This PR is based on running code for the [SC130](https://smallcomputercentral.wordpress.com/sc130-z180-motherboard/)/[SC131](https://smallcomputercentral.wordpress.com/sc131-z180-pocket-computer/) and [YAZ180](https://github.com/feilipu/yaz180) platforms, and is maintained by the z88dk team in this [z88dk-libraries](https://github.com/feilipu/z88dk-libraries/tree/master/freertos) repository.
|
||||
Reference in New Issue
Block a user