Add CC-RH port for Renesas F1Kx devices (#1100)
Add CC-RH port for Renesas F1Kx devices
diff --git a/.github/.cSpellWords.txt b/.github/.cSpellWords.txt
index 0ba0be7..42f9196 100644
--- a/.github/.cSpellWords.txt
+++ b/.github/.cSpellWords.txt
@@ -75,6 +75,7 @@
CCNTR
CCPN
CCPR
+CCRH
CDTY
CDTYR
CFBS
@@ -86,6 +87,7 @@
CICR
CISR
CKDIV
+CKDIVMD
CKEY
CKGR
CKLO
@@ -125,6 +127,7 @@
comms
COMPA
CONFG
+coreid
coremqtt
CORTUS
coverity
@@ -149,6 +152,7 @@
cpsid
cpsie
CPSR
+CPUCLK
CPUID
CRCB
crflash
@@ -164,6 +168,8 @@
csrw
CTCR
ctest
+CTPC
+CTPSW
CTRLA
CTSIC
CUPD
@@ -227,6 +233,7 @@
DTXD
DUNITY
DVAR
+Dxxx
EABI
ecall
ECIT
@@ -237,6 +244,7 @@
eevtedg
EEVTEDG
EFRHD
+EIIC
EINT
EIPC
EIPSW
@@ -310,6 +318,7 @@
FOSC
FPCCR
FPCSR
+FPEPC
FPSW
FPUL
FRDY
@@ -338,6 +347,7 @@
HCLK
Hitach
HRESP
+HTCFG
HWHSH
HWORD
HWRD
@@ -353,6 +363,7 @@
ICCRPR
ICCRX
ICERST
+ICIPI
ICSR
IDCR
IECR
@@ -372,6 +383,7 @@
IODEFINE
IORLW
IPEN
+IPIR
IPLB
ipsr
IPSR
@@ -380,8 +392,8 @@
IRXFCS
ISRAM
ISRR
-ISR's
ISRS
+ISR's
ISRTICK
isystem
ITIF
@@ -564,6 +576,7 @@
OSCOFF
OSCOUNT
OSMC
+OSTM
outpw
OVLY
OVRE
@@ -584,6 +597,7 @@
PCSR
PCXI
PDSR
+PEID
PEIE
PENDSV
PENDSVCLEAR
@@ -799,6 +813,8 @@
SWRST
SWTRG
synchronise
+SYNCM
+syncm
SYSC
sysclk
Sysclk
diff --git a/portable/CCRH/F1Kx/README.md b/portable/CCRH/F1Kx/README.md
new file mode 100644
index 0000000..7583c67
--- /dev/null
+++ b/portable/CCRH/F1Kx/README.md
@@ -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.
\ No newline at end of file
diff --git a/portable/CCRH/F1Kx/port.c b/portable/CCRH/F1Kx/port.c
new file mode 100644
index 0000000..e3d7192
--- /dev/null
+++ b/portable/CCRH/F1Kx/port.c
@@ -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) */
diff --git a/portable/CCRH/F1Kx/portasm.s b/portable/CCRH/F1Kx/portasm.s
new file mode 100644
index 0000000..4e56f44
--- /dev/null
+++ b/portable/CCRH/F1Kx/portasm.s
@@ -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
+
diff --git a/portable/CCRH/F1Kx/portmacro.h b/portable/CCRH/F1Kx/portmacro.h
new file mode 100644
index 0000000..e2b41f2
--- /dev/null
+++ b/portable/CCRH/F1Kx/portmacro.h
@@ -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 */