| /* |
| * 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 |
| * |
| */ |
| |
| /*----------------------------------------------------------- |
| * Implementation of functions defined in portable.h for the SH2A port. |
| *----------------------------------------------------------*/ |
| |
| /* Scheduler includes. */ |
| #include "FreeRTOS.h" |
| #include "task.h" |
| |
| /* Library includes. */ |
| #include "string.h" |
| |
| /*-----------------------------------------------------------*/ |
| |
| /* The SR assigned to a newly created task. The only important thing in this |
| * value is for all interrupts to be enabled. */ |
| #define portINITIAL_SR ( 0UL ) |
| |
| /* Dimensions the array into which the floating point context is saved. |
| * Allocate enough space for FPR0 to FPR15, FPUL and FPSCR, each of which is 4 |
| * bytes big. If this number is changed then the 72 in portasm.src also needs |
| * changing. */ |
| #define portFLOP_REGISTERS_TO_STORE ( 18 ) |
| #define portFLOP_STORAGE_SIZE ( portFLOP_REGISTERS_TO_STORE * 4 ) |
| |
| #if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) |
| #error configSUPPORT_DYNAMIC_ALLOCATION must be 1 to use this port. |
| #endif |
| |
| /*-----------------------------------------------------------*/ |
| |
| /* |
| * The TRAPA handler used to force a context switch. |
| */ |
| void vPortYield( void ); |
| |
| /* |
| * Function to start the first task executing - defined in portasm.src. |
| */ |
| extern void vPortStartFirstTask( void ); |
| |
| /* |
| * Obtains the current GBR value - defined in portasm.src. |
| */ |
| extern uint32_t ulPortGetGBR( void ); |
| |
| /*-----------------------------------------------------------*/ |
| |
| /* |
| * See header file for description. |
| */ |
| StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, |
| TaskFunction_t pxCode, |
| void * pvParameters ) |
| { |
| /* Mark the end of the stack - used for debugging only and can be removed. */ |
| *pxTopOfStack = 0x11111111UL; |
| pxTopOfStack--; |
| *pxTopOfStack = 0x22222222UL; |
| pxTopOfStack--; |
| *pxTopOfStack = 0x33333333UL; |
| pxTopOfStack--; |
| |
| /* SR. */ |
| *pxTopOfStack = portINITIAL_SR; |
| pxTopOfStack--; |
| |
| /* PC. */ |
| *pxTopOfStack = ( uint32_t ) pxCode; |
| pxTopOfStack--; |
| |
| /* PR. */ |
| *pxTopOfStack = 15; |
| pxTopOfStack--; |
| |
| /* 14. */ |
| *pxTopOfStack = 14; |
| pxTopOfStack--; |
| |
| /* R13. */ |
| *pxTopOfStack = 13; |
| pxTopOfStack--; |
| |
| /* R12. */ |
| *pxTopOfStack = 12; |
| pxTopOfStack--; |
| |
| /* R11. */ |
| *pxTopOfStack = 11; |
| pxTopOfStack--; |
| |
| /* R10. */ |
| *pxTopOfStack = 10; |
| pxTopOfStack--; |
| |
| /* R9. */ |
| *pxTopOfStack = 9; |
| pxTopOfStack--; |
| |
| /* R8. */ |
| *pxTopOfStack = 8; |
| pxTopOfStack--; |
| |
| /* R7. */ |
| *pxTopOfStack = 7; |
| pxTopOfStack--; |
| |
| /* R6. */ |
| *pxTopOfStack = 6; |
| pxTopOfStack--; |
| |
| /* R5. */ |
| *pxTopOfStack = 5; |
| pxTopOfStack--; |
| |
| /* R4. */ |
| *pxTopOfStack = ( uint32_t ) pvParameters; |
| pxTopOfStack--; |
| |
| /* R3. */ |
| *pxTopOfStack = 3; |
| pxTopOfStack--; |
| |
| /* R2. */ |
| *pxTopOfStack = 2; |
| pxTopOfStack--; |
| |
| /* R1. */ |
| *pxTopOfStack = 1; |
| pxTopOfStack--; |
| |
| /* R0 */ |
| *pxTopOfStack = 0; |
| pxTopOfStack--; |
| |
| /* MACL. */ |
| *pxTopOfStack = 16; |
| pxTopOfStack--; |
| |
| /* MACH. */ |
| *pxTopOfStack = 17; |
| pxTopOfStack--; |
| |
| /* GBR. */ |
| *pxTopOfStack = ulPortGetGBR(); |
| |
| /* GBR = global base register. |
| * VBR = vector base register. |
| * TBR = jump table base register. |
| * R15 is the stack pointer. */ |
| |
| return pxTopOfStack; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| BaseType_t xPortStartScheduler( void ) |
| { |
| extern void vApplicationSetupTimerInterrupt( void ); |
| |
| /* Call an application function to set up the timer that will generate the |
| * tick interrupt. This way the application can decide which peripheral to |
| * use. A demo application is provided to show a suitable example. */ |
| vApplicationSetupTimerInterrupt(); |
| |
| /* Start the first task. This will only restore the standard registers and |
| * not the flop registers. This does not really matter though because the only |
| * flop register that is initialised to a particular value is fpscr, and it is |
| * only initialised to the current value, which will still be the current value |
| * when the first task starts executing. */ |
| trapa( portSTART_SCHEDULER_TRAP_NO ); |
| |
| /* Should not get here. */ |
| return pdFAIL; |
| } |
| /*-----------------------------------------------------------*/ |
| |
| void vPortEndScheduler( void ) |
| { |
| /* Not implemented as there is nothing to return to. */ |
| } |
| /*-----------------------------------------------------------*/ |
| |
| void vPortYield( void ) |
| { |
| int32_t lInterruptMask; |
| |
| /* Ensure the yield trap runs at the same priority as the other interrupts |
| * that can cause a context switch. */ |
| lInterruptMask = get_imask(); |
| |
| /* taskYIELD() can only be called from a task, not an interrupt, so the |
| * current interrupt mask can only be 0 or portKERNEL_INTERRUPT_PRIORITY and |
| * the mask can be set without risk of accidentally lowering the mask value. */ |
| set_imask( portKERNEL_INTERRUPT_PRIORITY ); |
| |
| trapa( portYIELD_TRAP_NO ); |
| |
| /* Restore the interrupt mask to whatever it was previously (when the |
| * function was entered). */ |
| set_imask( ( int ) lInterruptMask ); |
| } |
| /*-----------------------------------------------------------*/ |
| |
| BaseType_t xPortUsesFloatingPoint( TaskHandle_t xTask ) |
| { |
| uint32_t * pulFlopBuffer; |
| BaseType_t xReturn; |
| extern void * volatile pxCurrentTCB; |
| |
| /* This function tells the kernel that the task referenced by xTask is |
| * going to use the floating point registers and therefore requires the |
| * floating point registers saved as part of its context. */ |
| |
| /* Passing NULL as xTask is used to indicate that the calling task is the |
| * subject task - so pxCurrentTCB is the task handle. */ |
| if( xTask == NULL ) |
| { |
| xTask = ( TaskHandle_t ) pxCurrentTCB; |
| } |
| |
| /* Allocate a buffer large enough to hold all the flop registers. */ |
| pulFlopBuffer = ( uint32_t * ) pvPortMalloc( portFLOP_STORAGE_SIZE ); |
| |
| if( pulFlopBuffer != NULL ) |
| { |
| /* Start with the registers in a benign state. */ |
| memset( ( void * ) pulFlopBuffer, 0x00, portFLOP_STORAGE_SIZE ); |
| |
| /* The first thing to get saved in the buffer is the FPSCR value - |
| * initialise this to the current FPSCR value. */ |
| *pulFlopBuffer = get_fpscr(); |
| |
| /* Use the task tag to point to the flop buffer. Pass pointer to just |
| * above the buffer because the flop save routine uses a pre-decrement. */ |
| vTaskSetApplicationTaskTag( xTask, ( void * ) ( pulFlopBuffer + portFLOP_REGISTERS_TO_STORE ) ); |
| xReturn = pdPASS; |
| } |
| else |
| { |
| xReturn = pdFAIL; |
| } |
| |
| return xReturn; |
| } |
| /*-----------------------------------------------------------*/ |