Add CC-RH port for Renesas F1Kx devices ()

Add CC-RH port for Renesas F1Kx devices
pull/1116/head
Trong Nguyen committed by GitHub
parent c963d24001
commit da3c35aa48
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -75,6 +75,7 @@ CCNT
CCNTR
CCPN
CCPR
CCRH
CDTY
CDTYR
CFBS
@ -86,6 +87,7 @@ CHSR
CICR
CISR
CKDIV
CKDIVMD
CKEY
CKGR
CKLO
@ -125,6 +127,7 @@ CODR
comms
COMPA
CONFG
coreid
coremqtt
CORTUS
coverity
@ -149,6 +152,7 @@ CPRE
cpsid
cpsie
CPSR
CPUCLK
CPUID
CRCB
crflash
@ -164,6 +168,8 @@ csrs
csrw
CTCR
ctest
CTPC
CTPSW
CTRLA
CTSIC
CUPD
@ -227,6 +233,7 @@ DTREN
DTXD
DUNITY
DVAR
Dxxx
EABI
ecall
ECIT
@ -237,6 +244,7 @@ EEVT
eevtedg
EEVTEDG
EFRHD
EIIC
EINT
EIPC
EIPSW
@ -310,6 +318,7 @@ FNTR
FOSC
FPCCR
FPCSR
FPEPC
FPSW
FPUL
FRDY
@ -338,6 +347,7 @@ GPTA
HCLK
Hitach
HRESP
HTCFG
HWHSH
HWORD
HWRD
@ -353,6 +363,7 @@ ICCR
ICCRPR
ICCRX
ICERST
ICIPI
ICSR
IDCR
IECR
@ -372,6 +383,7 @@ INTTM
IODEFINE
IORLW
IPEN
IPIR
IPLB
ipsr
IPSR
@ -380,8 +392,8 @@ IRET
IRXFCS
ISRAM
ISRR
ISR's
ISRS
ISR's
ISRTICK
isystem
ITIF
@ -564,6 +576,7 @@ OSCEN
OSCOFF
OSCOUNT
OSMC
OSTM
outpw
OVLY
OVRE
@ -584,6 +597,7 @@ PCLKSEL
PCSR
PCXI
PDSR
PEID
PEIE
PENDSV
PENDSVCLEAR
@ -799,6 +813,8 @@ SWINTR
SWRST
SWTRG
synchronise
SYNCM
syncm
SYSC
sysclk
Sysclk

@ -0,0 +1,46 @@
# RH850/F1K and F1Kx FreeRTOS Port with CC-RH Compiler
## Introduction
This repository contains the port of FreeRTOS for Renesas RH850/F1K and F1Kx microcontrollers using the CC-RH compiler. The following sections provide instructions on how to use this port, a link to the test project, and other relevant information.
## Prerequisites
- Compiler: CC-RH
- FreeRTOS version 11.1.0
| Device | FPU | SMP |
|----------|-----|-----|
| F1K | Yes | No |
| F1KM-S1 | Yes | No |
| F1KM-S2 | Yes | No |
| F1KM-S4 | Yes | No |
| F1KH-D8 | Yes | Yes |
## Link to Test Project
The test project can be found [here](https://github.com/FreeRTOS/FreeRTOS-Community-Supported-Demos) (`RH850_F1Kx_CCRH`). This project contains example tasks and configurations to help you get started with FreeRTOS on the RH850/F1K and F1Kx.
## Note
1. Configure IPIR Interrupt: Ensure that the bit specifying the destination for binding (requesting) an interrupt is enabled (e.g: IBDxxx register of F1KH-D8) (1)
2. `Channel 0` and address `0xFFFEEC00` are used as default configuration for configIPIR_CHANNEL and configEXCLUSIVE_ADDRESS, in case of resource confliction other channel/address can be used. (2)
3. The minimal stack size (configMINIMAL_STACK_SIZE) must be included the reserved memory for nested interrupt. This formula can be referred: `(task_context_size) * (1 + configMAX_INT_NESTING) + Stack_depth_of_taskcode`
In which, `task_context_size` is calculated as `36*4bytes = 144bytes` (when FPU enabled) or `34*4bytes = 136` (when FPU disabled), configMAX_INT_NESTING is 02 as default.
4. `configTIMER_PRESCALE`: This value is required in order to correctly configure clock for `CPUCLK_L`. Refer to Hardware Manual at `Table 44.22` for `option byte`: If the user sets the option byte `CKDIVMD to 1`, then `configTIMER_PRESCALE = 4`. Otherwise, if `CKDIVMD is set to 0`, then `configTIMER_PRESCALE = 2`.
(1) This is applicable for F1KH-D8 with SMP only.
(2) This is optional and applicable for SMP only.
## Other Relevant Information
- **Documentation:**
- Refer to the official [FreeRTOS documentation](https://www.freertos.org/Documentation/RTOS_book.html) for detailed information on configuring and using FreeRTOS.
- Consult the [RH850 F1K group user manual hardware manual](https://www.renesas.com/us/en/document/mah/rh850f1k-group-users-manual-hardware?r=1170166) for specific details about the microcontroller.
- For more information about Renesas RH850/F1K and F1Kx, please visit [this website](https://www.renesas.com/us/en/products/microcontrollers-microprocessors/rh850-automotive-mcus)
- The CC-RH compiler can be downloaded [here](https://www.renesas.com/us/en/software-tool/c-compiler-package-rh850-family#downloads)
- **Support:**
- If you encounter any issues or have questions about this port, please open an issue in this repository or contact the maintainer.
- **Contributing:**
- Contributions to improve this port are welcome. Please fork the repository, make your changes, and submit a pull request.

@ -0,0 +1,734 @@
/*
* 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
*
*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
/* This port uses xTaskGetCurrentTaskHandle to get TCB stack, it is required to
* enable this API. */
#if ( ( INCLUDE_xTaskGetCurrentTaskHandle != 1 ) && ( configNUMBER_OF_CORES == 1 ) )
#error INCLUDE_xTaskGetCurrentTaskHandle must be set to 1 in single core.
#endif
/***********************************************************
* Macro definitions
***********************************************************/
/* Hardware specific macros */
#define portPSW_REGISTER_ID ( 5 )
#define portFPSR_REGISTER_ID ( 6 )
/* PSW.EBV and PSW.CUx bits are kept as current status */
#define portINITIAL_PSW_MASK ( 0x000f8000 )
#define portCURRENT_PSW_VALUE ( portSTSR( portPSW_REGISTER_ID ) )
#define portCURRENT_SR_ZERO_VALUE ( ( StackType_t ) 0x00000000 )
#define portCURRENT_FPSR_VALUE ( portSTSR( portFPSR_REGISTER_ID ) )
/* Mask for FPU configuration bits (FN, PEM, RM, FS) */
#define portINITIAL_FPSR_MASK ( 0x00ae0000 )
#define portPSW_ID_MASK ( 0x00000020 )
/* Define necessary hardware IO for OSTM timer. OSTM0 is used by default as
* it is common for almost device variants. If it conflicts with application,
* the application shall implement another timer.*/
#define portOSTM_EIC_ADDR ( 0xFFFFB0A8 )
#define portOSTM0CMP_ADDR ( 0xFFD70000 )
#define portOSTM0CTL_ADDR ( 0xFFD70020 )
#define portOSTM0TS_ADDR ( 0xFFD70014 )
#if ( configNUMBER_OF_CORES > 1 )
/* IPIR base address, the peripheral is used for Inter-Processor communication
* Hardware supports 4 channels which is offset by 0x0, 0x4, 0x8, 0xC bytes from
* base address. By default, channel 0 is selected. */
#ifdef configIPIR_CHANNEL
#define portIPIR_BASE_ADDR ( ( 0xFFFEEC80 ) + ( configIPIR_CHANNEL << 2 ) )
#else
#define portIPIR_BASE_ADDR ( 0xFFFEEC80 )
#endif
/* Address used for exclusive control for variable shared between PEs
* (common resources), each CPU cores have independent access path to
* this address. By default, G0MEV0 register is selected*/
#ifdef configEXCLUSIVE_ADDRESS
#define portMEV_BASE_ADDR configEXCLUSIVE_ADDRESS
#else
#define portMEV_BASE_ADDR ( 0xFFFEEC00 )
#endif
#endif /* if ( configNUMBER_OF_CORES > 1 ) */
/* Macros required to set up the initial stack. */
#define portSTACK_INITIAL_VALUE_R1 ( ( StackType_t ) 0x01010101 )
#define portSTACK_INITIAL_VALUE_R2 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x02 )
#define portSTACK_INITIAL_VALUE_R3 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x03 )
#define portSTACK_INITIAL_VALUE_R4 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x04 )
#define portSTACK_INITIAL_VALUE_R5 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x05 )
#define portSTACK_INITIAL_VALUE_R6 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x06 )
#define portSTACK_INITIAL_VALUE_R7 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x07 )
#define portSTACK_INITIAL_VALUE_R8 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x08 )
#define portSTACK_INITIAL_VALUE_R9 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x09 )
#define portSTACK_INITIAL_VALUE_R10 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x10 )
#define portSTACK_INITIAL_VALUE_R11 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x11 )
#define portSTACK_INITIAL_VALUE_R12 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x12 )
#define portSTACK_INITIAL_VALUE_R13 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x13 )
#define portSTACK_INITIAL_VALUE_R14 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x14 )
#define portSTACK_INITIAL_VALUE_R15 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x15 )
#define portSTACK_INITIAL_VALUE_R16 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x16 )
#define portSTACK_INITIAL_VALUE_R17 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x17 )
#define portSTACK_INITIAL_VALUE_R18 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x18 )
#define portSTACK_INITIAL_VALUE_R19 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x19 )
#define portSTACK_INITIAL_VALUE_R20 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x20 )
#define portSTACK_INITIAL_VALUE_R21 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x21 )
#define portSTACK_INITIAL_VALUE_R22 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x22 )
#define portSTACK_INITIAL_VALUE_R23 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x23 )
#define portSTACK_INITIAL_VALUE_R24 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x24 )
#define portSTACK_INITIAL_VALUE_R25 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x25 )
#define portSTACK_INITIAL_VALUE_R26 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x26 )
#define portSTACK_INITIAL_VALUE_R27 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x27 )
#define portSTACK_INITIAL_VALUE_R28 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x28 )
#define portSTACK_INITIAL_VALUE_R29 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x29 )
#define portSTACK_INITIAL_VALUE_R30 ( ( StackType_t ) portSTACK_INITIAL_VALUE_R1 * 0x30 )
/***********************************************************
* Typedef definitions
***********************************************************/
/* 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 )
#define portOSTM_MODE_FREE_RUNNING ( 0x02U )
/* Disables or Enable the interrupts when counting starts */
#define portOSTM_START_INTERRUPT_DISABLE ( 0x00U )
#define portOSTM_START_INTERRUPT_ENABLE ( 0x01U )
/* Interrupt vector method select (TBxxx) */
#define portINT_DIRECT_VECTOR ( 0x0U )
#define portINT_TABLE_VECTOR ( 0x1U )
/* Interrupt mask (MKxxx) */
#define portINT_PROCESSING_ENABLED ( 0x0U )
#define portINT_PROCESSING_DISABLED ( 0x1U )
/* Specify 16 interrupt priority levels */
#define portINT_PRIORITY_HIGHEST ( 0x0000U ) /* Level 0 (highest) */
#define portINT_PRIORITY_LEVEL1 ( 0x0001U ) /* Level 1 */
#define portINT_PRIORITY_LEVEL2 ( 0x0002U ) /* Level 2 */
#define portINT_PRIORITY_LEVEL3 ( 0x0003U ) /* Level 3 */
#define portINT_PRIORITY_LEVEL4 ( 0x0004U ) /* Level 4 */
#define portINT_PRIORITY_LEVEL5 ( 0x0005U ) /* Level 5 */
#define portINT_PRIORITY_LEVEL6 ( 0x0006U ) /* Level 6 */
#define portINT_PRIORITY_LEVEL7 ( 0x0007U ) /* Level 7 */
#define portINT_PRIORITY_LEVEL8 ( 0x0008U ) /* Level 8 */
#define portINT_PRIORITY_LEVEL9 ( 0x0009U ) /* Level 9 */
#define portINT_PRIORITY_LEVEL10 ( 0x000AU ) /* Level 10 */
#define portINT_PRIORITY_LEVEL11 ( 0x000BU ) /* Level 11 */
#define portINT_PRIORITY_LEVEL12 ( 0x000CU ) /* Level 12 */
#define portINT_PRIORITY_LEVEL13 ( 0x000DU ) /* Level 13 */
#define portINT_PRIORITY_LEVEL14 ( 0x000EU ) /* Level 14 */
#define portINT_PRIORITY_LOWEST ( 0x000FU ) /* Level 15 (lowest) */
/* Macros indicating status of scheduler request */
#define PORT_SCHEDULER_NOREQUEST 0UL
#define PORT_SCHEDULER_TASKSWITCH 1UL /* Do not modify */
#define PORT_SCHEDULER_STARTFIRSTTASK 2UL /* Do not modify */
#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 */
#ifndef configMAX_INT_NESTING
/* Set the default value for depth of nested interrupt. In theory, the
* microcontroller have mechanism to limit number of nested level of interrupt
* by priority (maximum 16 levels). However, the large stack memory should be
* prepared for each task to save resource in interrupt handler. Therefore, it
* is necessary to limit depth of nesting interrupt to optimize memory usage.
* In addition, the execution time of interrupt handler should be very short
* (typically not exceed 20us), this constraint does not impact to system.
*/
#define configMAX_INT_NESTING 2UL
#endif
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError( 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 );
#if ( configNUMBER_OF_CORES > 1 )
/*
* Functions implement spin-lock between cores by atomic accesses to Exclusive
* Control Register (G0MEVm). There are separated access path between CPU cores,
* but they should wait if access to same register
*/
static void prvExclusiveLock( BaseType_t xFromIsr );
static void prvExclusiveRelease( BaseType_t xFromIsr );
#endif
/*
* Function to start the first task executing
*/
extern void vPortStartFirstTask( void );
/* Scheduler request on each cores which are starting first task and switching
* context */
volatile BaseType_t xPortScheduleStatus[ configNUMBER_OF_CORES ] = { 0 };
/* Counts the interrupt nesting depth. A context switch is only performed if
* the nesting depth is 0. In addition, the interrupt shares same stack
* allocated for each tasks. With supporting nesting interrupt, the stack
* may be overflowed.
* It is necessary to control maximum stack depth.
*/
volatile UBaseType_t uxInterruptNesting[ configNUMBER_OF_CORES ] = { 0 };
volatile const UBaseType_t uxPortMaxInterruptDepth = configMAX_INT_NESTING - 1;
/* Count number of nested locks by same cores. The lock is completely released
* only if this count is decreased to 0, the lock is separated for task
* and isr */
UBaseType_t uxLockNesting[ configNUMBER_OF_CORES ][ 2 ] = { 0 };
#if ( configNUMBER_OF_CORES > 1 )
/* Pointer to exclusive access memory */
volatile BaseType_t * pxPortExclusiveReg = ( volatile BaseType_t * ) ( portMEV_BASE_ADDR );
#endif
/* Interrupt handler for OSTM timer which handling tick increment and resulting
* to switch context. */
void vPortTickISR( void );
#if ( configNUMBER_OF_CORES > 1 )
/* Yield specific cores by send inter-processor interrupt */
void vPortYieldCore( uint32_t xCoreID );
/*
* Inter-processor interrupt handler. The interrupt is triggered by
* portYIELD_CORE().
*/
void vPortIPIHander( void );
/* These functions below implement recursive spinlock for exclusive access among
* cores. The core will wait until lock will be available, whilst the core which
* already had lock can acquire lock without waiting. This function could be
* call from task and interrupt context, the critical section is called
* as in ISR */
void vPortRecursiveLockAcquire( BaseType_t xFromIsr );
void vPortRecursiveLockRelease( BaseType_t xFromIsr );
#endif /* (configNUMBER_OF_CORES > 1) */
/*-----------------------------------------------------------*/
/*
* These below functions implement interrupt mask from interrupt. They are not
* called in nesting, it is protected by FreeRTOS kernel.
*/
portLONG xPortSetInterruptMask( void )
{
portLONG ulPSWValue = portSTSR( portPSW_REGISTER_ID );
portDISABLE_INTERRUPTS();
/* It returns current value of Program Status Word register */
return ulPSWValue;
}
/*-----------------------------------------------------------*/
void vPortClearInterruptMask( portLONG uxSavedInterruptStatus )
{
portLONG ulPSWValue = portSTSR( portPSW_REGISTER_ID );
/* Interrupt Disable status is indicates by bit#5 of PSW
* (1: Interrupt is disabled; 0: Interrupt is enabled) */
/* Revert to the status before interrupt mask. */
ulPSWValue &= ( ~( portPSW_ID_MASK ) );
ulPSWValue |= ( portPSW_ID_MASK & uxSavedInterruptStatus );
portLDSR( portPSW_REGISTER_ID, ulPSWValue );
}
/*-----------------------------------------------------------*/
/*
* Using CC-RH intrinsic function to get HTCFG0 (regID, selID) = (0,2)
* Core ID is indicates by bit HTCFG0.PEID located at bit 18 to 16
* Bit 31 to 19 are read only and always be read as 0. HTCFG0.PEID is 1 and 2
* corresponding to core 0 (PE1) and core 1 (PE2). It is adjusted to 0 and 1.
*/
BaseType_t xPortGET_CORE_ID( void )
{
#if ( configNUMBER_OF_CORES > 1 )
return ( portSTSR_CCRH( 0, 2 ) >> 16 ) - 1;
#else
/* In single core, xPortGET_CORE_ID is used in this port only.
* The dummy core ID could be controlled inside this port. */
return 0;
#endif
}
/*-----------------------------------------------------------*/
/*
* This port supports both multi-cores and single-core, whilst TCB stack
* variables are different which are respectively pxCurrentTCB (single-core)
* and pxCurrentTCBs[] (multiple-cores). This function is defined to obtains
* TCBs of current cores. Also, the C function could switch to corresponding
* pointer by pre-compile conditions.
*/
void * pvPortGetCurrentTCB( void )
{
void * pvCurrentTCB = ( void * ) xTaskGetCurrentTaskHandle();
configASSERT( pvCurrentTCB != NULL );
return pvCurrentTCB;
}
/*-----------------------------------------------------------*/
/*
* This function checks if a context switch is required and, if so, updates
* the scheduler status for the core on which the function is called. The
* scheduler status is set to indicate that a task switch should occur.
*/
void vPortSetSwitch( BaseType_t xSwitchRequired )
{
if( xSwitchRequired != pdFALSE )
{
xPortScheduleStatus[ xPortGET_CORE_ID() ] = PORT_SCHEDULER_TASKSWITCH;
}
}
/*-----------------------------------------------------------*/
/*
* 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 ) prvTaskExitError; /* 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 (EP) */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R1; /* R1 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portSTACK_INITIAL_VALUE_R2; /* R2 */
pxTopOfStack--;
/* Keep System pre-configuration (HV, CUx, EBV) as current setting in
* PSW register */
*pxTopOfStack = ( StackType_t ) ( portCURRENT_PSW_VALUE & portINITIAL_PSW_MASK ); /* EIPSW */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode; /* EIPC */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portCURRENT_SR_ZERO_VALUE; /* EIIC */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) ( portCURRENT_PSW_VALUE & portINITIAL_PSW_MASK ); /* CTPSW */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portCURRENT_SR_ZERO_VALUE; /* CTPC */
/* __FPU is defined by CCRH compiler if FPU is enabled */
#if ( configENABLE_FPU == 1 )
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) ( portCURRENT_FPSR_VALUE & portINITIAL_FPSR_MASK ); /* FPSR */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portCURRENT_SR_ZERO_VALUE; /* FPEPC */
#endif /* (configENABLE_FPU == 1) */
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
/*
* Configures the tick frequency and starts the first task.
*/
BaseType_t xPortStartScheduler( void )
{
#if ( configNUMBER_OF_CORES > 1 )
BaseType_t xCurrentCore = xPortGET_CORE_ID();
#endif
/* Prevent interrupt by timer interrupt during starting first task.
* The interrupt shall be enabled automatically by being restored from
* task stack */
portDISABLE_INTERRUPTS();
/* Setup the tick interrupt */
configSETUP_TICK_INTERRUPT();
#if ( configNUMBER_OF_CORES > 1 )
/* Start scheduler on other cores */
for( uint16_t xCoreID = 0; xCoreID < configNUMBER_OF_CORES; xCoreID++ )
{
if( xCoreID != xCurrentCore )
{
/* Send yielding request to other cores with flag to start
* first task. TaskContextSwitch is not executed */
xPortScheduleStatus[ xCoreID ] = PORT_SCHEDULER_STARTFIRSTTASK;
vPortYieldCore( xCoreID );
}
else
{
/* Nothing to do. The first task is started in this call by
* below vPortStartFirstTask() */
xPortScheduleStatus[ xCoreID ] = PORT_SCHEDULER_NOREQUEST;
}
}
#endif /* if ( configNUMBER_OF_CORES > 1 ) */
/* Start first task in primary core */
vPortStartFirstTask();
/* Should never get here as the tasks will now be executing! */
prvTaskExitError();
/* To prevent compiler warnings in the case that the application writer
* overrides this functionality by defining configTASK_RETURN_ADDRESS.
* Call vTaskSwitchContext() so link time optimization does not remove
* the symbol. */
vTaskSwitchContext(
#if ( configNUMBER_OF_CORES > 1 )
xCurrentCore
#endif
);
return pdFALSE;
}
/*-----------------------------------------------------------*/
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError( void )
{
/* A function that implements a task must not exit or attempt to return to
* its caller as there is nothing to return to. If a task wants to exit it
* should instead call vTaskDelete( NULL ).
*
* Artificially force an assert() to be triggered if configASSERT() is
* defined, then stop here so application writers can catch the error. */
/* This statement will always fail, triggering the assert */
configASSERT( pdFALSE );
/*
* The following statement may be unreachable because configASSERT(pdFALSE)
* always triggers an assertion failure, which typically halts program
* execution.
* The warning may be reported to indicate to indicate that the compiler
* detects the subsequent code will not be executed.
* The warning is acceptable to ensure program is halt regardless of
* configASSERT(pdFALSE) implementation
*/
portDISABLE_INTERRUPTS();
for( ; ; )
{
/* Infinite loop to ensure the function does not return. */
}
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
* Artificially force an assert. */
configASSERT( pdFALSE );
}
/*-----------------------------------------------------------*/
#if ( configNUMBER_OF_CORES > 1 )
void vPortYieldCore( uint32_t xCoreID )
{
/* Check if we need to yield on a different core */
if( xCoreID != xPortGET_CORE_ID() )
{
volatile uint32_t * pulIPIRReg;
/* Determine the IPI register based on the target core ID */
pulIPIRReg = ( volatile uint32_t * ) ( portIPIR_BASE_ADDR );
/*Inter-processor interrupt generates an interrupt request by
* writing 1 to applicable bits of target cores. The interrupt
* should be enabled by application in corresponding cores
* including PSW.ID (EI instruction) and interrupt control setting
* for ICIPIRn channel (interrupt mask, vector method)
*/
*pulIPIRReg = ( 1 << xCoreID );
}
else
{
/* Yielding current core */
vPortYield();
}
}
/*-----------------------------------------------------------*/
/*
* Handler for inter-processor interrupt in second cores. The interrupt is
* triggered by portYIELD_CORE(). vTaskSwitchContext() is invoked to
* switch tasks
*/
void vPortIPIHander( void )
{
BaseType_t xCurrentCore = xPortGET_CORE_ID();
/* 1st execution starts 1st task, TaskSwitchContext is not executed */
if( PORT_SCHEDULER_STARTFIRSTTASK != xPortScheduleStatus[ xCurrentCore ] )
{
xPortScheduleStatus[ xCurrentCore ] = PORT_SCHEDULER_TASKSWITCH;
}
}
/*-----------------------------------------------------------*/
#endif /* (configNUMBER_OF_CORES > 1) */
void vPortTickISR( void )
{
/* In case of multicores with SMP, xTaskIncrementTick is required to
* called in critical section to avoid conflict resource as this function
* could be called by xTaskResumeAll() from any cores. */
#if ( configNUMBER_OF_CORES > 1 )
BaseType_t xSavedInterruptStatus;
xSavedInterruptStatus = portENTER_CRITICAL_FROM_ISR();
#endif
{
/* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE )
{
/* Pend a context switch. */
xPortScheduleStatus[ xPortGET_CORE_ID() ] = PORT_SCHEDULER_TASKSWITCH;
}
}
#if ( configNUMBER_OF_CORES > 1 )
portEXIT_CRITICAL_FROM_ISR( xSavedInterruptStatus );
#endif
}
/*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt( void )
{
volatile uint32_t * pulOSTMIntReg;
/* Interrupt configuration for OSTM Timer
* By default, the second lowest priority is set for timer interrupt to
* avoid blocking other interrupt. Normally, user could set the lowest
* priority for non-critical event. It try to keep timer on time.
* In addition, direct vector table is used by default.
*/
pulOSTMIntReg = ( volatile uint32_t * ) portOSTM_EIC_ADDR;
*pulOSTMIntReg = ( portINT_PROCESSING_ENABLED | portINT_DIRECT_VECTOR | portINT_PRIORITY_LEVEL14 );
/* Set OSTM0 control setting */
*( ( volatile uint32_t * ) portOSTM0CTL_ADDR ) =
( portOSTM_MODE_INTERVAL_TIMER | portOSTM_START_INTERRUPT_DISABLE );
*( ( volatile uint32_t * ) portOSTM0CMP_ADDR ) =
( ( configCPU_CLOCK_HZ / configTIMER_PRESCALE ) / configTICK_RATE_HZ ) - 1;
/* Enable OSTM0 operation */
*( ( volatile uint32_t * ) portOSTM0TS_ADDR ) = portOSTM_COUNTER_START;
}
/*-----------------------------------------------------------*/
#if ( configNUMBER_OF_CORES > 1 )
/*
* These functions implement spin-lock mechanism among cores using hardware
* exclusive control with atomic access by CLR1 and SET1 instruction.
* Nesting calls to these APIs are possible.
*/
#pragma inline_asm prvExclusiveLock
static void prvExclusiveLock( BaseType_t xBitPosition )
{
/* No problem with r19, CCRH does not required to restore same value
* before and after function call. */
mov # _pxPortExclusiveReg, r19
ld.w 0[ r19 ], r19
prvExclusiveLock_Lock:
/* r6 is xBitPosition */
set1 r6, [ r19 ]
bz prvExclusiveLock_Lock_success
snooze
br prvExclusiveLock_Lock
prvExclusiveLock_Lock_success:
}
/*-----------------------------------------------------------*/
#pragma inline_asm prvExclusiveRelease
static void prvExclusiveRelease( BaseType_t xBitPosition )
{
mov # _pxPortExclusiveReg, r19
ld.w 0[ r19 ], r19
/* r6 is xBitPosition */
clr1 r6, [ r19 ]
}
/*-----------------------------------------------------------*/
void vPortRecursiveLockAcquire( BaseType_t xFromIsr )
{
BaseType_t xSavedInterruptStatus;
BaseType_t xCoreID = xPortGET_CORE_ID();
BaseType_t xBitPosition = ( xFromIsr == pdTRUE );
xSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
if( uxLockNesting[ xCoreID ][ xBitPosition ] == 0 )
{
prvExclusiveLock( xBitPosition );
}
uxLockNesting[ xCoreID ][ xBitPosition ]++;
portCLEAR_INTERRUPT_MASK_FROM_ISR( xSavedInterruptStatus );
}
void vPortRecursiveLockRelease( BaseType_t xFromIsr )
{
BaseType_t xSavedInterruptStatus;
BaseType_t xCoreID = xPortGET_CORE_ID();
BaseType_t xBitPosition = ( xFromIsr == pdTRUE );
xSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
/* Sync memory */
portSYNCM();
/* Error check whether vPortRecursiveLockRelease() is not called in
* pair with vPortRecursiveLockAcquire() */
configASSERT( ( uxLockNesting[ xCoreID ][ xBitPosition ] > 0 ) );
uxLockNesting[ xCoreID ][ xBitPosition ]--;
if( uxLockNesting[ xCoreID ][ xBitPosition ] == 0 )
{
prvExclusiveRelease( xBitPosition );
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( xSavedInterruptStatus );
}
/*-----------------------------------------------------------*/
#endif /* (configNUMBER_OF_CORES > 1) */

@ -0,0 +1,325 @@
;/*
; * 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
; *
; */
;------------------------------------------------------------------------------
; Extern symbols
;------------------------------------------------------------------------------
.extern _uxInterruptNesting
.extern _uxPortMaxInterruptDepth
.extern _xPortScheduleStatus
.extern _vTaskSwitchContext
.extern _pvPortGetCurrentTCB
.extern _vCommonISRHandler
.extern _xPortGET_CORE_ID
.public _vIrq_Handler
.public _vPortStartFirstTask
.public _vPortYield
.public _vTRAP0_Handler
;------------------------------------------------------------------------------
; Macro definitions
;------------------------------------------------------------------------------
EIPC .set 0
EIPSW .set 1
PSW .set 5
FPSR .set 6
FPEPC .set 7
EIIC .set 13
CTPC .set 16
CTPSW .set 17
EIIC_MSK .set 0x00000FFF
FPU_MSK .set 0x00010000
;------------------------------------------------------------------------------
; portSAVE_CONTEXT
; Context saving
;------------------------------------------------------------------------------
portSAVE_CONTEXT .macro
prepare lp, 0
; Save general-purpose registers and EIPSW, EIPC, EIIC, CTPSW, CTPC into stack.
pushsp r5, r30
$nowarning
pushsp r1, r2
$warning
stsr EIPSW, r15
stsr EIPC, r16
stsr EIIC, r17
stsr CTPSW, r18
stsr CTPC, r19
pushsp r15, r19
; Save FPU registers to stack if FPU is enabled
mov FPU_MSK, r19
tst r15, r19
; Jump over next 3 instructions: stsr (4 bytes)*2 + pushsp (4 bytes)
bz 12
stsr FPSR, r18
stsr FPEPC, r19
pushsp r18, r19
; Get current TCB, the return value is stored in r10 (CCRH compiler)
jarl _pvPortGetCurrentTCB, lp
st.w sp, 0[r10]
.endm
;------------------------------------------------------------------------------
; portRESTORE_CONTEXT
; Context restoring
;------------------------------------------------------------------------------
portRESTORE_CONTEXT .macro
; Current TCB is returned by r10 (CCRH compiler)
jarl _pvPortGetCurrentTCB, lp
ld.w 0[r10], sp ; Restore the stack pointer from the TCB
; Restore FPU registers if FPU is enabled
mov FPU_MSK, r19
stsr PSW, r18
tst r18, r19
; Jump over next 3 instructions: stsr (4 bytes)*2 + popsp (4 bytes)
bz 12
popsp r18, r19
ldsr r18, FPEPC
ldsr r19, FPSR
;Restore general-purpose registers and EIPSW, EIPC, EIIC, CTPSW, CTPC
popsp r15, r19
ldsr r19, CTPC
ldsr r18, CTPSW
ldsr r17, EIIC
ldsr r16, EIPC
ldsr r15, EIPSW
$nowarning
popsp r1, r2
$warning
popsp r5, r30
dispose 0, lp
.endm
;------------------------------------------------------------------------------
; Save used registers
;------------------------------------------------------------------------------
SAVE_REGISTER .macro
; Save general-purpose registers and EIPSW, EIPC, EIIC, CTPSW, CTPC into stack.
; Callee-Save registers (r20 to r30) are not used in interrupt handler and
; guaranteed no change after function call. So, don't need to save register
; to optimize the used stack memory.
pushsp r5, r19
$nowarning
pushsp r1, r2
$warning
stsr EIPSW, r19
stsr EIPC, r18
stsr EIIC, r17
mov lp, r16
mov ep, r15
stsr CTPSW, r14
stsr CTPC, r13
pushsp r13, r19
mov FPU_MSK, r16
tst r16, r19
bz 12
stsr FPSR, r18
stsr FPEPC, r19
pushsp r18, r19
.endm
;------------------------------------------------------------------------------
; Restore used registers
;------------------------------------------------------------------------------
RESTORE_REGISTER .macro
mov FPU_MSK, r16
stsr PSW, r18
tst r18, r19
bz 12
popsp r18, r19
ldsr r18, FPEPC
ldsr r19, FPSR
popsp r13, r19
ldsr r13, CTPC
ldsr r14, CTPSW
mov r15, ep
mov r16, lp
ldsr r17, EIIC
ldsr r18, EIPC
ldsr r19, EIPSW
$nowarning
popsp r1, r2
$warning
popsp r5, r19
.endm
;------------------------------------------------------------------------------
; Start the first task.
;------------------------------------------------------------------------------
_vPortStartFirstTask:
portRESTORE_CONTEXT
eiret
;------------------------------------------------------------------------------
; _vPortYield
;------------------------------------------------------------------------------
_vPortYield:
trap 0
jmp [lp] ; Return to caller function
;------------------------------------------------------------------------------
; PortYield handler. This is installed as the TRAP exception handler.
;------------------------------------------------------------------------------
_vTRAP0_Handler:
;Save the context of the current task.
portSAVE_CONTEXT
; The use case that portYield() is called from interrupt context as nested interrupt.
; Context switch should be executed at the most outer of interrupt tree.
; In that case, set xPortScheduleStatus to flag context switch in interrupt handler.
jarl _xPortGET_CORE_ID, lp ; return value is contained in r10 (CCRH compiler)
mov r10, r11
shl 2, r11
mov #_uxInterruptNesting, r19
add r11, r19
ld.w 0[r19], r18
cmp r0, r18
be _vTRAP0_Handler_ContextSwitch
mov #_xPortScheduleStatus, r19
add r11, r19
; Set xPortScheduleStatus[coreID]=PORT_SCHEDULER_TASKSWITCH
mov 1, r17
st.w r17, 0[r19]
br _vTRAP0_Handler_Exit
_vTRAP0_Handler_ContextSwitch:
; Pass coreID (r10) as parameter by r6 (CCRH compiler) in SMP support.
mov r10, r6
; Call the scheduler to select the next task.
; vPortYeild may be called to current core again at the end of vTaskSwitchContext.
; This may case nested interrupt, however, it is not necessary to set
; uxInterruptNesting (currently 0) for nested trap0 exception. The user interrupt
; (EI level interrupt) is not accepted inside of trap0 exception.
jarl _vTaskSwitchContext, lp
_vTRAP0_Handler_Exit:
; Restore the context of the next task to run.
portRESTORE_CONTEXT
eiret
;------------------------------------------------------------------------------
; _Irq_Handler
; Handler interrupt service routine (ISR).
;------------------------------------------------------------------------------
_vIrq_Handler:
; Save used registers.
SAVE_REGISTER
; Get core ID by HTCFG0, thread configuration register.
; Then, increase nesting count for current core.
jarl _xPortGET_CORE_ID, lp ; return value is contained in r10 (CCRH compiler)
shl 2, r10
mov r10, r17
mov #_uxInterruptNesting, r19
add r17, r19
ld.w 0[r19], r18
addi 0x1, r18, r16
st.w r16, 0[r19]
pushsp r17, r19
;Call the interrupt handler.
stsr EIIC, r6
andi EIIC_MSK, r6, r6
; Do not enable interrupt for nesting. Stackover flow may occurs if the
; depth of nesting interrupt is exceeded.
mov #_uxPortMaxInterruptDepth, r15
cmp r16, r15
be 4 ; Jump over ei instruction
ei
jarl _vCommonISRHandler, lp
di
synce
popsp r17, r19
st.w r18, 0[r19] ; Restore the old nesting count.
; A context switch if no nesting interrupt.
cmp 0x0, r18
bne _vIrq_Handler_NotSwitchContext
; Check if context switch is requested.
mov #_xPortScheduleStatus, r19
add r17, r19
ld.w 0[r19], r18
cmp r0, r18
bne _vIrq_Handler_SwitchContext
_vIrq_Handler_NotSwitchContext:
; No context switch. Restore used registers
RESTORE_REGISTER
eiret
;This sequence is executed for primary core only to switch context
_vIrq_Handler_SwitchContext:
; Clear the context switch pending flag.
st.w r0, 0[r19]
add -1, r18
bnz _vIrq_Handler_StartFirstTask
; Restore used registers before saving the context to the task stack.
RESTORE_REGISTER
portSAVE_CONTEXT
; Get Core ID and pass to vTaskSwitchContext as parameter (CCRH compiler)
; The parameter is unused in single core, no problem with this redudant setting
jarl _xPortGET_CORE_ID, lp ; return value is contained in r10 (CCRH compiler)
mov r10, r6
; vPortYeild may be called to current core again at the end of vTaskSwitchContext.
; This may case nested interrupt, however, it is not necessary to set
; uxInterruptNesting (currently 0) for trap0 exception. The user interrupt
; (EI level interrupt) is not accepted inside of trap0 exception.
jarl _vTaskSwitchContext, lp ;
portRESTORE_CONTEXT
eiret
_vIrq_Handler_StartFirstTask:
RESTORE_REGISTER
jr _vPortStartFirstTask

@ -0,0 +1,193 @@
/*
* 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 PORTMACRO_H
#define PORTMACRO_H
#ifdef __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 ( 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 portSTSR( reg ) __stsr( ( reg ) )
#define portLDSR( reg, val ) __ldsr( ( reg ), ( val ) )
#define portSTSR_CCRH( reg, sel ) __stsr_rh( ( reg ), ( sel ) )
#define portSYNCM() __syncm()
/* 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 ( 4 )
/* Interrupt control macros. */
#define portENABLE_INTERRUPTS() __EI() /* Macro to enable all maskable interrupts. */
#define portDISABLE_INTERRUPTS() __DI() /* Macro to disable all maskable interrupts. */
#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS()
#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS()
/* SMP build which means configNUM_CORES is relevant */
#define portSUPPORT_SMP 1
#define portMAX_CORE_COUNT 2
#ifndef configNUMBER_OF_CORES
#define configNUMBER_OF_CORES 1
#endif
/*-----------------------------------------------------------*/
/* Scheduler utilities */
/* Called at the end of an ISR that can cause a context switch */
extern void vPortSetSwitch( BaseType_t vPortSetSwitch );
#define portEND_SWITCHING_ISR( xSwitchRequired ) vPortSetSwitch( vPortSetSwitch )
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/* Use to transfer control from one task to perform other tasks of
* higher priority */
extern void vPortYield( void );
#define portYIELD() vPortYield()
#if ( configNUMBER_OF_CORES > 1 )
/* Return the core ID on which the code is running. */
extern BaseType_t xPortGET_CORE_ID();
#define portGET_CORE_ID() xPortGET_CORE_ID()
#define coreid xPortGET_CORE_ID()
/* Request the core ID x to yield. */
extern void vPortYieldCore( unsigned int coreID );
#define portYIELD_CORE( x ) vPortYieldCore( x )
#define portENTER_CRITICAL_FROM_ISR() vTaskEnterCriticalFromISR()
#define portEXIT_CRITICAL_FROM_ISR( x ) vTaskExitCriticalFromISR( x )
#endif /* if ( configNUMBER_OF_CORES > 1 ) */
#if ( configNUMBER_OF_CORES == 1 )
#define portGET_ISR_LOCK()
#define portRELEASE_ISR_LOCK()
#define portGET_TASK_LOCK()
#define portRELEASE_TASK_LOCK()
#else
extern void vPortRecursiveLockAcquire( BaseType_t xFromIsr );
extern void vPortRecursiveLockRelease( BaseType_t xFromIsr );
#define portGET_ISR_LOCK() vPortRecursiveLockAcquire( pdTRUE )
#define portRELEASE_ISR_LOCK() vPortRecursiveLockRelease( pdTRUE )
#define portGET_TASK_LOCK() vPortRecursiveLockAcquire( pdFALSE )
#define portRELEASE_TASK_LOCK() vPortRecursiveLockRelease( pdFALSE )
#endif /* if ( configNUMBER_OF_CORES == 1 ) */
/*-----------------------------------------------------------*/
/* Critical section management. */
/* 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()
/*-----------------------------------------------------------*/
/* Macros to set and clear the interrupt mask. */
portLONG xPortSetInterruptMask();
void vPortClearInterruptMask( portLONG );
#define portSET_INTERRUPT_MASK() xPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK( x ) vPortClearInterruptMask( ( x ) )
#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortClearInterruptMask( ( x ) )
/*-----------------------------------------------------------*/
/* 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 */
Loading…
Cancel
Save