Forráskód Böngészése

fix: 修正bsp/pico在树莓派下编译的错误

Wendal Chen 4 éve
szülő
commit
cb3a842524

+ 1 - 1
.gitignore

@@ -88,4 +88,4 @@ debug.log
 
 CMakefiles
 bsp/win32/build/
-
+bsp/pico/build/

+ 2 - 2
bsp/pico/CMakeLists.txt

@@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.12)
 
 # initialize the SDK based on PICO_SDK_PATH
 # note: this must happen before project()
-include(pico-sdk/pico_sdk_init.cmake)
-#add_subdirectory(luatos)
+include(pico_sdk_import.cmake)
+include(${PICO_SDK_PATH}/pico_sdk_init.cmake)
 project(pico-luatos)
 
 # initialize the Pico SDK

+ 1 - 0
bsp/pico/src/main.c

@@ -3,6 +3,7 @@
 #include "FreeRTOS.h"
 #include "task.h"
 #include "luat_base.h"
+#include "bget.h"
 
 #define LUAT_HEAP_SIZE (64*1024)
 uint8_t luavm_heap[LUAT_HEAP_SIZE] = {0};

+ 566 - 0
components/freertos/portable/GCC/ARM_CM0/port.c

@@ -0,0 +1,566 @@
+/*
+ * FreeRTOS Kernel V10.4.3
+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ */
+
+/*-----------------------------------------------------------
+* Implementation of functions defined in portable.h for the ARM CM0 port.
+*----------------------------------------------------------*/
+
+/* Scheduler includes. */
+#include "FreeRTOS.h"
+#include "task.h"
+
+/* Constants required to manipulate the NVIC. */
+#define portNVIC_SYSTICK_CTRL_REG             ( *( ( volatile uint32_t * ) 0xe000e010 ) )
+#define portNVIC_SYSTICK_LOAD_REG             ( *( ( volatile uint32_t * ) 0xe000e014 ) )
+#define portNVIC_SYSTICK_CURRENT_VALUE_REG    ( *( ( volatile uint32_t * ) 0xe000e018 ) )
+#define portNVIC_INT_CTRL_REG                 ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
+#define portNVIC_SHPR3_REG                    ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
+#define portNVIC_SYSTICK_CLK_BIT              ( 1UL << 2UL )
+#define portNVIC_SYSTICK_INT_BIT              ( 1UL << 1UL )
+#define portNVIC_SYSTICK_ENABLE_BIT           ( 1UL << 0UL )
+#define portNVIC_SYSTICK_COUNT_FLAG_BIT       ( 1UL << 16UL )
+#define portNVIC_PENDSVSET_BIT                ( 1UL << 28UL )
+#define portMIN_INTERRUPT_PRIORITY            ( 255UL )
+#define portNVIC_PENDSV_PRI                   ( portMIN_INTERRUPT_PRIORITY << 16UL )
+#define portNVIC_SYSTICK_PRI                  ( portMIN_INTERRUPT_PRIORITY << 24UL )
+
+/* Constants required to set up the initial stack. */
+#define portINITIAL_XPSR                      ( 0x01000000 )
+
+/* The systick is a 24-bit counter. */
+#define portMAX_24_BIT_NUMBER                 ( 0xffffffUL )
+
+/* A fiddle factor to estimate the number of SysTick counts that would have
+ * occurred while the SysTick counter is stopped during tickless idle
+ * calculations. */
+#ifndef portMISSED_COUNTS_FACTOR
+    #define portMISSED_COUNTS_FACTOR    ( 45UL )
+#endif
+
+/* Let the user override the pre-loading of the initial LR with the address of
+ * prvTaskExitError() in case it messes up unwinding of the stack in the
+ * debugger. */
+#ifdef configTASK_RETURN_ADDRESS
+    #define portTASK_RETURN_ADDRESS    configTASK_RETURN_ADDRESS
+#else
+    #define portTASK_RETURN_ADDRESS    prvTaskExitError
+#endif
+
+/*
+ * Setup the timer to generate the tick interrupts.  The implementation in this
+ * file is weak to allow application writers to change the timer used to
+ * generate the tick interrupt.
+ */
+void vPortSetupTimerInterrupt( void );
+
+/*
+ * Exception handlers.
+ */
+void xPortPendSVHandler( void ) __attribute__( ( naked ) );
+void xPortSysTickHandler( void );
+void vPortSVCHandler( void );
+
+/*
+ * Start first task is a separate function so it can be tested in isolation.
+ */
+static void vPortStartFirstTask( void ) __attribute__( ( naked ) );
+
+/*
+ * Used to catch tasks that attempt to return from their implementing function.
+ */
+static void prvTaskExitError( void );
+
+/*-----------------------------------------------------------*/
+
+/* Each task maintains its own interrupt status in the critical nesting
+ * variable. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
+
+/*-----------------------------------------------------------*/
+
+/*
+ * The number of SysTick increments that make up one tick period.
+ */
+#if ( configUSE_TICKLESS_IDLE == 1 )
+    static uint32_t ulTimerCountsForOneTick = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * The maximum number of tick periods that can be suppressed is limited by the
+ * 24 bit resolution of the SysTick timer.
+ */
+#if ( configUSE_TICKLESS_IDLE == 1 )
+    static uint32_t xMaximumPossibleSuppressedTicks = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*
+ * Compensate for the CPU cycles that pass while the SysTick is stopped (low
+ * power functionality only.
+ */
+#if ( configUSE_TICKLESS_IDLE == 1 )
+    static uint32_t ulStoppedTimerCompensation = 0;
+#endif /* configUSE_TICKLESS_IDLE */
+
+/*-----------------------------------------------------------*/
+
+/*
+ * See header file for description.
+ */
+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--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
+    *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR */
+    pxTopOfStack--;
+    *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC */
+    pxTopOfStack--;
+    *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
+    pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
+    *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0 */
+    pxTopOfStack -= 8;                                       /* R11..R4. */
+
+    return pxTopOfStack;
+}
+/*-----------------------------------------------------------*/
+
+static void prvTaskExitError( void )
+{
+    volatile uint32_t ulDummy = 0UL;
+
+    /* 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. */
+    configASSERT( uxCriticalNesting == ~0UL );
+    portDISABLE_INTERRUPTS();
+
+    while( ulDummy == 0 )
+    {
+        /* This file calls prvTaskExitError() after the scheduler has been
+         * started to remove a compiler warning about the function being defined
+         * but never called.  ulDummy is used purely to quieten other warnings
+         * about code appearing after this function is called - making ulDummy
+         * volatile makes the compiler think the function could return and
+         * therefore not output an 'unreachable code' warning for code that appears
+         * after it. */
+    }
+}
+/*-----------------------------------------------------------*/
+
+void vPortSVCHandler( void )
+{
+    /* This function is no longer used, but retained for backward
+     * compatibility. */
+}
+/*-----------------------------------------------------------*/
+
+void vPortStartFirstTask( void )
+{
+    /* The MSP stack is not reset as, unlike on M3/4 parts, there is no vector
+     * table offset register that can be used to locate the initial stack value.
+     * Not all M0 parts have the application vector table at address 0. */
+    __asm volatile (
+        "	.syntax unified				\n"
+        "	ldr  r2, pxCurrentTCBConst2	\n"/* Obtain location of pxCurrentTCB. */
+        "	ldr  r3, [r2]				\n"
+        "	ldr  r0, [r3]				\n"/* The first item in pxCurrentTCB is the task top of stack. */
+        "	adds r0, #32					\n"/* Discard everything up to r0. */
+        "	msr  psp, r0					\n"/* This is now the new top of stack to use in the task. */
+        "	movs r0, #2					\n"/* Switch to the psp stack. */
+        "	msr  CONTROL, r0				\n"
+        "	isb							\n"
+        "	pop  {r0-r5}					\n"/* Pop the registers that are saved automatically. */
+        "	mov  lr, r5					\n"/* lr is now in r5. */
+        "	pop  {r3}					\n"/* Return address is now in r3. */
+        "	pop  {r2}					\n"/* Pop and discard XPSR. */
+        "	cpsie i						\n"/* The first task has its context and interrupts can be enabled. */
+        "	bx   r3						\n"/* Finally, jump to the user defined task code. */
+        "								\n"
+        "	.align 4					\n"
+        "pxCurrentTCBConst2: .word pxCurrentTCB	  "
+        );
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * See header file for description.
+ */
+BaseType_t xPortStartScheduler( void )
+{
+    /* Make PendSV, CallSV and SysTick the same priority as the kernel. */
+    portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
+    portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
+
+    /* Start the timer that generates the tick ISR.  Interrupts are disabled
+     * here already. */
+    vPortSetupTimerInterrupt();
+
+    /* Initialise the critical nesting count ready for the first task. */
+    uxCriticalNesting = 0;
+
+    /* Start the first task. */
+    vPortStartFirstTask();
+
+    /* Should never get here as the tasks will now be executing!  Call the task
+     * exit error function to prevent compiler warnings about a static function
+     * not being called in the case that the application writer overrides this
+     * functionality by defining configTASK_RETURN_ADDRESS.  Call
+     * vTaskSwitchContext() so link time optimisation does not remove the
+     * symbol. */
+    vTaskSwitchContext();
+    prvTaskExitError();
+
+    /* Should not get here! */
+    return 0;
+}
+/*-----------------------------------------------------------*/
+
+void vPortEndScheduler( void )
+{
+    /* Not implemented in ports where there is nothing to return to.
+     * Artificially force an assert. */
+    configASSERT( uxCriticalNesting == 1000UL );
+}
+/*-----------------------------------------------------------*/
+
+void vPortYield( void )
+{
+    /* Set a PendSV to request a context switch. */
+    portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
+
+    /* Barriers are normally not required but do ensure the code is completely
+     * within the specified behaviour for the architecture. */
+    __asm volatile ( "dsb" ::: "memory" );
+    __asm volatile ( "isb" );
+}
+/*-----------------------------------------------------------*/
+
+void vPortEnterCritical( void )
+{
+    portDISABLE_INTERRUPTS();
+    uxCriticalNesting++;
+    __asm volatile ( "dsb" ::: "memory" );
+    __asm volatile ( "isb" );
+}
+/*-----------------------------------------------------------*/
+
+void vPortExitCritical( void )
+{
+    configASSERT( uxCriticalNesting );
+    uxCriticalNesting--;
+
+    if( uxCriticalNesting == 0 )
+    {
+        portENABLE_INTERRUPTS();
+    }
+}
+/*-----------------------------------------------------------*/
+
+uint32_t ulSetInterruptMaskFromISR( void )
+{
+    __asm volatile (
+        " mrs r0, PRIMASK	\n"
+        " cpsid i			\n"
+        " bx lr				  "
+        ::: "memory"
+        );
+}
+/*-----------------------------------------------------------*/
+
+void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask )
+{
+    __asm volatile (
+        " msr PRIMASK, r0	\n"
+        " bx lr				  "
+        ::: "memory"
+        );
+}
+/*-----------------------------------------------------------*/
+
+void xPortPendSVHandler( void )
+{
+    /* This is a naked function. */
+
+    __asm volatile
+    (
+        "	.syntax unified						\n"
+        "	mrs r0, psp							\n"
+        "										\n"
+        "	ldr	r3, pxCurrentTCBConst			\n"/* Get the location of the current TCB. */
+        "	ldr	r2, [r3]						\n"
+        "										\n"
+        "	subs r0, r0, #32					\n"/* Make space for the remaining low registers. */
+        "	str r0, [r2]						\n"/* Save the new top of stack. */
+        "	stmia r0!, {r4-r7}					\n"/* Store the low registers that are not saved automatically. */
+        " 	mov r4, r8							\n"/* Store the high registers. */
+        " 	mov r5, r9							\n"
+        " 	mov r6, r10							\n"
+        " 	mov r7, r11							\n"
+        " 	stmia r0!, {r4-r7}					\n"
+        "										\n"
+        "	push {r3, r14}						\n"
+        "	cpsid i								\n"
+        "	bl vTaskSwitchContext				\n"
+        "	cpsie i								\n"
+        "	pop {r2, r3}						\n"/* lr goes in r3. r2 now holds tcb pointer. */
+        "										\n"
+        "	ldr r1, [r2]						\n"
+        "	ldr r0, [r1]						\n"/* The first item in pxCurrentTCB is the task top of stack. */
+        "	adds r0, r0, #16					\n"/* Move to the high registers. */
+        "	ldmia r0!, {r4-r7}					\n"/* Pop the high registers. */
+        " 	mov r8, r4							\n"
+        " 	mov r9, r5							\n"
+        " 	mov r10, r6							\n"
+        " 	mov r11, r7							\n"
+        "										\n"
+        "	msr psp, r0							\n"/* Remember the new top of stack for the task. */
+        "										\n"
+        "	subs r0, r0, #32					\n"/* Go back for the low registers that are not automatically restored. */
+        " 	ldmia r0!, {r4-r7}					\n"/* Pop low registers.  */
+        "										\n"
+        "	bx r3								\n"
+        "										\n"
+        "	.align 4							\n"
+        "pxCurrentTCBConst: .word pxCurrentTCB	  "
+    );
+}
+/*-----------------------------------------------------------*/
+
+void xPortSysTickHandler( void )
+{
+    uint32_t ulPreviousMask;
+
+    ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    {
+        /* Increment the RTOS tick. */
+        if( xTaskIncrementTick() != pdFALSE )
+        {
+            /* Pend a context switch. */
+            portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
+        }
+    }
+    portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
+}
+/*-----------------------------------------------------------*/
+
+/*
+ * Setup the systick timer to generate the tick interrupts at the required
+ * frequency.
+ */
+__attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void )
+{
+    /* Calculate the constants required to configure the tick interrupt. */
+    #if ( configUSE_TICKLESS_IDLE == 1 )
+        {
+            ulTimerCountsForOneTick = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );
+            xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
+            ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR;
+        }
+    #endif /* configUSE_TICKLESS_IDLE */
+
+    /* Stop and reset the SysTick. */
+    portNVIC_SYSTICK_CTRL_REG = 0UL;
+    portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+
+    /* Configure SysTick to interrupt at the requested rate. */
+    portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
+    portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
+}
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TICKLESS_IDLE == 1 )
+
+    __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
+    {
+        uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
+        TickType_t xModifiableIdleTime;
+
+        /* Make sure the SysTick reload value does not overflow the counter. */
+        if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
+        {
+            xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
+        }
+
+        /* Stop the SysTick momentarily.  The time the SysTick is stopped for
+         * is accounted for as best it can be, but using the tickless mode will
+         * inevitably result in some tiny drift of the time maintained by the
+         * kernel with respect to calendar time. */
+        portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
+
+        /* Calculate the reload value required to wait xExpectedIdleTime
+         * tick periods.  -1 is used because this code will execute part way
+         * through one of the tick periods. */
+        ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
+
+        if( ulReloadValue > ulStoppedTimerCompensation )
+        {
+            ulReloadValue -= ulStoppedTimerCompensation;
+        }
+
+        /* Enter a critical section but don't use the taskENTER_CRITICAL()
+         * method as that will mask interrupts that should exit sleep mode. */
+        __asm volatile ( "cpsid i" ::: "memory" );
+        __asm volatile ( "dsb" );
+        __asm volatile ( "isb" );
+
+        /* If a context switch is pending or a task is waiting for the scheduler
+         * to be unsuspended then abandon the low power entry. */
+        if( eTaskConfirmSleepModeStatus() == eAbortSleep )
+        {
+            /* Restart from whatever is left in the count register to complete
+             * this tick period. */
+            portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
+
+            /* Restart SysTick. */
+            portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+
+            /* Reset the reload register to the value required for normal tick
+             * periods. */
+            portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+            /* Re-enable interrupts - see comments above the cpsid instruction()
+             * above. */
+            __asm volatile ( "cpsie i" ::: "memory" );
+        }
+        else
+        {
+            /* Set the new reload value. */
+            portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
+
+            /* Clear the SysTick count flag and set the count value back to
+             * zero. */
+            portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+
+            /* Restart SysTick. */
+            portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+
+            /* Sleep until something happens.  configPRE_SLEEP_PROCESSING() can
+             * set its parameter to 0 to indicate that its implementation contains
+             * its own wait for interrupt or wait for event instruction, and so wfi
+             * should not be executed again.  However, the original expected idle
+             * time variable must remain unmodified, so a copy is taken. */
+            xModifiableIdleTime = xExpectedIdleTime;
+            configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
+
+            if( xModifiableIdleTime > 0 )
+            {
+                __asm volatile ( "dsb" ::: "memory" );
+                __asm volatile ( "wfi" );
+                __asm volatile ( "isb" );
+            }
+
+            configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
+
+            /* Re-enable interrupts to allow the interrupt that brought the MCU
+             * out of sleep mode to execute immediately.  see comments above
+             * __disable_interrupt() call above. */
+            __asm volatile ( "cpsie i" ::: "memory" );
+            __asm volatile ( "dsb" );
+            __asm volatile ( "isb" );
+
+            /* Disable interrupts again because the clock is about to be stopped
+             * and interrupts that execute while the clock is stopped will increase
+             * any slippage between the time maintained by the RTOS and calendar
+             * time. */
+            __asm volatile ( "cpsid i" ::: "memory" );
+            __asm volatile ( "dsb" );
+            __asm volatile ( "isb" );
+
+            /* Disable the SysTick clock without reading the
+             * portNVIC_SYSTICK_CTRL_REG register to ensure the
+             * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set.  Again,
+             * the time the SysTick is stopped for is accounted for as best it can
+             * be, but using the tickless mode will inevitably result in some tiny
+             * drift of the time maintained by the kernel with respect to calendar
+             * time*/
+            portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
+
+            /* Determine if the SysTick clock has already counted to zero and
+             * been set back to the current reload value (the reload back being
+             * correct for the entire expected idle time) or if the SysTick is yet
+             * to count to zero (in which case an interrupt other than the SysTick
+             * must have brought the system out of sleep mode). */
+            if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
+            {
+                uint32_t ulCalculatedLoadValue;
+
+                /* The tick interrupt is already pending, and the SysTick count
+                 * reloaded with ulReloadValue.  Reset the
+                 * portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
+                 * period. */
+                ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
+
+                /* Don't allow a tiny value, or values that have somehow
+                 * underflowed because the post sleep hook did something
+                 * that took too long. */
+                if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
+                {
+                    ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
+                }
+
+                portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
+
+                /* As the pending tick will be processed as soon as this
+                 * function exits, the tick value maintained by the tick is stepped
+                 * forward by one less than the time spent waiting. */
+                ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
+            }
+            else
+            {
+                /* Something other than the tick interrupt ended the sleep.
+                 * Work out how long the sleep lasted rounded to complete tick
+                 * periods (not the ulReload value which accounted for part
+                 * ticks). */
+                ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
+
+                /* How many complete tick periods passed while the processor
+                 * was waiting? */
+                ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
+
+                /* The reload value is set to whatever fraction of a single tick
+                 * period remains. */
+                portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
+            }
+
+            /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
+             * again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
+             * value. */
+            portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
+            portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
+            vTaskStepTick( ulCompleteTickPeriods );
+            portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
+
+            /* Exit with interrpts enabled. */
+            __asm volatile ( "cpsie i" ::: "memory" );
+        }
+    }
+
+#endif /* configUSE_TICKLESS_IDLE */

+ 124 - 0
components/freertos/portable/GCC/ARM_CM0/portmacro.h

@@ -0,0 +1,124 @@
+/*
+ * FreeRTOS Kernel V10.4.3
+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * https://www.FreeRTOS.org
+ * https://github.com/FreeRTOS
+ *
+ * 1 tab == 4 spaces!
+ */
+
+
+#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. */
+    #define portCHAR          char
+    #define portFLOAT         float
+    #define portDOUBLE        double
+    #define portLONG          long
+    #define portSHORT         short
+    #define portSTACK_TYPE    uint32_t
+    #define portBASE_TYPE     long
+
+    typedef portSTACK_TYPE   StackType_t;
+    typedef long             BaseType_t;
+    typedef unsigned long    UBaseType_t;
+
+    #if ( configUSE_16_BIT_TICKS == 1 )
+        typedef uint16_t     TickType_t;
+        #define portMAX_DELAY              ( TickType_t ) 0xffff
+    #else
+        typedef uint32_t     TickType_t;
+        #define portMAX_DELAY              ( TickType_t ) 0xffffffffUL
+
+/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
+ * not need to be guarded with a critical section. */
+        #define portTICK_TYPE_IS_ATOMIC    1
+    #endif
+/*-----------------------------------------------------------*/
+
+/* Architecture specifics. */
+    #define portSTACK_GROWTH      ( -1 )
+    #define portTICK_PERIOD_MS    ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
+    #define portBYTE_ALIGNMENT    8
+    #define portDONT_DISCARD      __attribute__( ( used ) )
+/*-----------------------------------------------------------*/
+
+
+/* Scheduler utilities. */
+    extern void vPortYield( void );
+    #define portNVIC_INT_CTRL_REG     ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
+    #define portNVIC_PENDSVSET_BIT    ( 1UL << 28UL )
+    #define portYIELD()                                 vPortYield()
+    #define portEND_SWITCHING_ISR( xSwitchRequired )    if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
+    #define portYIELD_FROM_ISR( x )                     portEND_SWITCHING_ISR( x )
+/*-----------------------------------------------------------*/
+
+
+/* Critical section management. */
+    extern void vPortEnterCritical( void );
+    extern void vPortExitCritical( void );
+    extern uint32_t ulSetInterruptMaskFromISR( void ) __attribute__( ( naked ) );
+    extern void vClearInterruptMaskFromISR( uint32_t ulMask )  __attribute__( ( naked ) );
+
+    #define portSET_INTERRUPT_MASK_FROM_ISR()         ulSetInterruptMaskFromISR()
+    #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vClearInterruptMaskFromISR( x )
+    #define portDISABLE_INTERRUPTS()                  __asm volatile ( " cpsid i " ::: "memory" )
+    #define portENABLE_INTERRUPTS()                   __asm volatile ( " cpsie i " ::: "memory" )
+    #define portENTER_CRITICAL()                      vPortEnterCritical()
+    #define portEXIT_CRITICAL()                       vPortExitCritical()
+
+/*-----------------------------------------------------------*/
+
+/* Tickless idle/low power functionality. */
+    #ifndef portSUPPRESS_TICKS_AND_SLEEP
+        extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
+        #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime )    vPortSuppressTicksAndSleep( xExpectedIdleTime )
+    #endif
+/*-----------------------------------------------------------*/
+
+/* 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 )
+
+    #define portNOP()
+
+    #define portMEMORY_BARRIER()    __asm volatile ( "" ::: "memory" )
+
+    #ifdef __cplusplus
+        }
+    #endif
+
+#endif /* PORTMACRO_H */