mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-19 21:11:57 -04:00
Merge branch 'main' into update-pxcurrentTCB
This commit is contained in:
commit
ba2306d098
18
.github/.cSpellWords.txt
vendored
18
.github/.cSpellWords.txt
vendored
|
@ -75,6 +75,7 @@ CCNT
|
||||||
CCNTR
|
CCNTR
|
||||||
CCPN
|
CCPN
|
||||||
CCPR
|
CCPR
|
||||||
|
CCRH
|
||||||
CDTY
|
CDTY
|
||||||
CDTYR
|
CDTYR
|
||||||
CFBS
|
CFBS
|
||||||
|
@ -86,6 +87,7 @@ CHSR
|
||||||
CICR
|
CICR
|
||||||
CISR
|
CISR
|
||||||
CKDIV
|
CKDIV
|
||||||
|
CKDIVMD
|
||||||
CKEY
|
CKEY
|
||||||
CKGR
|
CKGR
|
||||||
CKLO
|
CKLO
|
||||||
|
@ -125,6 +127,7 @@ CODR
|
||||||
comms
|
comms
|
||||||
COMPA
|
COMPA
|
||||||
CONFG
|
CONFG
|
||||||
|
coreid
|
||||||
coremqtt
|
coremqtt
|
||||||
CORTUS
|
CORTUS
|
||||||
coverity
|
coverity
|
||||||
|
@ -149,6 +152,7 @@ CPRE
|
||||||
cpsid
|
cpsid
|
||||||
cpsie
|
cpsie
|
||||||
CPSR
|
CPSR
|
||||||
|
CPUCLK
|
||||||
CPUID
|
CPUID
|
||||||
CRCB
|
CRCB
|
||||||
crflash
|
crflash
|
||||||
|
@ -164,6 +168,8 @@ csrs
|
||||||
csrw
|
csrw
|
||||||
CTCR
|
CTCR
|
||||||
ctest
|
ctest
|
||||||
|
CTPC
|
||||||
|
CTPSW
|
||||||
CTRLA
|
CTRLA
|
||||||
CTSIC
|
CTSIC
|
||||||
CUPD
|
CUPD
|
||||||
|
@ -227,6 +233,7 @@ DTREN
|
||||||
DTXD
|
DTXD
|
||||||
DUNITY
|
DUNITY
|
||||||
DVAR
|
DVAR
|
||||||
|
Dxxx
|
||||||
EABI
|
EABI
|
||||||
ecall
|
ecall
|
||||||
ECIT
|
ECIT
|
||||||
|
@ -237,6 +244,7 @@ EEVT
|
||||||
eevtedg
|
eevtedg
|
||||||
EEVTEDG
|
EEVTEDG
|
||||||
EFRHD
|
EFRHD
|
||||||
|
EIIC
|
||||||
EINT
|
EINT
|
||||||
EIPC
|
EIPC
|
||||||
EIPSW
|
EIPSW
|
||||||
|
@ -310,6 +318,7 @@ FNTR
|
||||||
FOSC
|
FOSC
|
||||||
FPCCR
|
FPCCR
|
||||||
FPCSR
|
FPCSR
|
||||||
|
FPEPC
|
||||||
FPSW
|
FPSW
|
||||||
FPUL
|
FPUL
|
||||||
FRDY
|
FRDY
|
||||||
|
@ -338,6 +347,7 @@ GPTA
|
||||||
HCLK
|
HCLK
|
||||||
Hitach
|
Hitach
|
||||||
HRESP
|
HRESP
|
||||||
|
HTCFG
|
||||||
HWHSH
|
HWHSH
|
||||||
HWORD
|
HWORD
|
||||||
HWRD
|
HWRD
|
||||||
|
@ -353,6 +363,7 @@ ICCR
|
||||||
ICCRPR
|
ICCRPR
|
||||||
ICCRX
|
ICCRX
|
||||||
ICERST
|
ICERST
|
||||||
|
ICIPI
|
||||||
ICSR
|
ICSR
|
||||||
IDCR
|
IDCR
|
||||||
IECR
|
IECR
|
||||||
|
@ -372,6 +383,7 @@ INTTM
|
||||||
IODEFINE
|
IODEFINE
|
||||||
IORLW
|
IORLW
|
||||||
IPEN
|
IPEN
|
||||||
|
IPIR
|
||||||
IPLB
|
IPLB
|
||||||
ipsr
|
ipsr
|
||||||
IPSR
|
IPSR
|
||||||
|
@ -380,8 +392,8 @@ IRET
|
||||||
IRXFCS
|
IRXFCS
|
||||||
ISRAM
|
ISRAM
|
||||||
ISRR
|
ISRR
|
||||||
ISR's
|
|
||||||
ISRS
|
ISRS
|
||||||
|
ISR's
|
||||||
ISRTICK
|
ISRTICK
|
||||||
isystem
|
isystem
|
||||||
ITIF
|
ITIF
|
||||||
|
@ -564,6 +576,7 @@ OSCEN
|
||||||
OSCOFF
|
OSCOFF
|
||||||
OSCOUNT
|
OSCOUNT
|
||||||
OSMC
|
OSMC
|
||||||
|
OSTM
|
||||||
outpw
|
outpw
|
||||||
OVLY
|
OVLY
|
||||||
OVRE
|
OVRE
|
||||||
|
@ -584,6 +597,7 @@ PCLKSEL
|
||||||
PCSR
|
PCSR
|
||||||
PCXI
|
PCXI
|
||||||
PDSR
|
PDSR
|
||||||
|
PEID
|
||||||
PEIE
|
PEIE
|
||||||
PENDSV
|
PENDSV
|
||||||
PENDSVCLEAR
|
PENDSVCLEAR
|
||||||
|
@ -799,6 +813,8 @@ SWINTR
|
||||||
SWRST
|
SWRST
|
||||||
SWTRG
|
SWTRG
|
||||||
synchronise
|
synchronise
|
||||||
|
SYNCM
|
||||||
|
syncm
|
||||||
SYSC
|
SYSC
|
||||||
sysclk
|
sysclk
|
||||||
Sysclk
|
Sysclk
|
||||||
|
|
|
@ -109,7 +109,7 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t;
|
||||||
* the same size.
|
* the same size.
|
||||||
*
|
*
|
||||||
* @return If the queue is successfully create then a handle to the newly
|
* @return If the queue is successfully create then a handle to the newly
|
||||||
* created queue is returned. If the queue cannot be created then 0 is
|
* created queue is returned. If the queue cannot be created then NULL is
|
||||||
* returned.
|
* returned.
|
||||||
*
|
*
|
||||||
* Example usage:
|
* Example usage:
|
||||||
|
@ -126,7 +126,7 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t;
|
||||||
*
|
*
|
||||||
* // Create a queue capable of containing 10 uint32_t values.
|
* // Create a queue capable of containing 10 uint32_t values.
|
||||||
* xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
|
* xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
|
||||||
* if( xQueue1 == 0 )
|
* if( xQueue1 == NULL )
|
||||||
* {
|
* {
|
||||||
* // Queue was not created and must not be used.
|
* // Queue was not created and must not be used.
|
||||||
* }
|
* }
|
||||||
|
@ -134,7 +134,7 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t;
|
||||||
* // Create a queue capable of containing 10 pointers to AMessage structures.
|
* // Create a queue capable of containing 10 pointers to AMessage structures.
|
||||||
* // These should be passed by pointer as they contain a lot of data.
|
* // These should be passed by pointer as they contain a lot of data.
|
||||||
* xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
|
* xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
|
||||||
* if( xQueue2 == 0 )
|
* if( xQueue2 == NULL )
|
||||||
* {
|
* {
|
||||||
* // Queue was not created and must not be used.
|
* // Queue was not created and must not be used.
|
||||||
* }
|
* }
|
||||||
|
@ -292,7 +292,7 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t;
|
||||||
* queue is full. The time is defined in tick periods so the constant
|
* queue is full. The time is defined in tick periods so the constant
|
||||||
* portTICK_PERIOD_MS should be used to convert to real time if this is required.
|
* portTICK_PERIOD_MS should be used to convert to real time if this is required.
|
||||||
*
|
*
|
||||||
* @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
|
* @return pdPASS if the item was successfully posted, otherwise errQUEUE_FULL.
|
||||||
*
|
*
|
||||||
* Example usage:
|
* Example usage:
|
||||||
* @code{c}
|
* @code{c}
|
||||||
|
@ -375,7 +375,7 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t;
|
||||||
* is full. The time is defined in tick periods so the constant
|
* is full. The time is defined in tick periods so the constant
|
||||||
* portTICK_PERIOD_MS should be used to convert to real time if this is required.
|
* portTICK_PERIOD_MS should be used to convert to real time if this is required.
|
||||||
*
|
*
|
||||||
* @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
|
* @return pdPASS if the item was successfully posted, otherwise errQUEUE_FULL.
|
||||||
*
|
*
|
||||||
* Example usage:
|
* Example usage:
|
||||||
* @code{c}
|
* @code{c}
|
||||||
|
@ -460,7 +460,7 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t;
|
||||||
* queue is full. The time is defined in tick periods so the constant
|
* queue is full. The time is defined in tick periods so the constant
|
||||||
* portTICK_PERIOD_MS should be used to convert to real time if this is required.
|
* portTICK_PERIOD_MS should be used to convert to real time if this is required.
|
||||||
*
|
*
|
||||||
* @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
|
* @return pdPASS if the item was successfully posted, otherwise errQUEUE_FULL.
|
||||||
*
|
*
|
||||||
* Example usage:
|
* Example usage:
|
||||||
* @code{c}
|
* @code{c}
|
||||||
|
@ -633,7 +633,7 @@ typedef struct QueueDefinition * QueueSetMemberHandle_t;
|
||||||
* item at the back of the queue, or queueSEND_TO_FRONT to place the item
|
* item at the back of the queue, or queueSEND_TO_FRONT to place the item
|
||||||
* at the front of the queue (for high priority messages).
|
* at the front of the queue (for high priority messages).
|
||||||
*
|
*
|
||||||
* @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL.
|
* @return pdPASS if the item was successfully posted, otherwise errQUEUE_FULL.
|
||||||
*
|
*
|
||||||
* Example usage:
|
* Example usage:
|
||||||
* @code{c}
|
* @code{c}
|
||||||
|
@ -723,8 +723,8 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
|
||||||
* xQueuePeek() will return immediately if xTicksToWait is 0 and the queue
|
* xQueuePeek() will return immediately if xTicksToWait is 0 and the queue
|
||||||
* is empty.
|
* is empty.
|
||||||
*
|
*
|
||||||
* @return pdTRUE if an item was successfully received from the queue,
|
* @return pdPASS if an item was successfully received from the queue,
|
||||||
* otherwise pdFALSE.
|
* otherwise errQUEUE_EMPTY.
|
||||||
*
|
*
|
||||||
* Example usage:
|
* Example usage:
|
||||||
* @code{c}
|
* @code{c}
|
||||||
|
@ -811,8 +811,8 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue,
|
||||||
* @param pvBuffer Pointer to the buffer into which the received item will
|
* @param pvBuffer Pointer to the buffer into which the received item will
|
||||||
* be copied.
|
* be copied.
|
||||||
*
|
*
|
||||||
* @return pdTRUE if an item was successfully received from the queue,
|
* @return pdPASS if an item was successfully received from the queue,
|
||||||
* otherwise pdFALSE.
|
* otherwise pdFAIL.
|
||||||
*
|
*
|
||||||
* \defgroup xQueuePeekFromISR xQueuePeekFromISR
|
* \defgroup xQueuePeekFromISR xQueuePeekFromISR
|
||||||
* \ingroup QueueManagement
|
* \ingroup QueueManagement
|
||||||
|
@ -852,8 +852,8 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue,
|
||||||
* constant portTICK_PERIOD_MS should be used to convert to real time if this is
|
* constant portTICK_PERIOD_MS should be used to convert to real time if this is
|
||||||
* required.
|
* required.
|
||||||
*
|
*
|
||||||
* @return pdTRUE if an item was successfully received from the queue,
|
* @return pdPASS if an item was successfully received from the queue,
|
||||||
* otherwise pdFALSE.
|
* otherwise errQUEUE_EMPTY.
|
||||||
*
|
*
|
||||||
* Example usage:
|
* Example usage:
|
||||||
* @code{c}
|
* @code{c}
|
||||||
|
@ -998,7 +998,7 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
|
||||||
* running task. If xQueueSendToFrontFromISR() sets this value to pdTRUE then
|
* running task. If xQueueSendToFrontFromISR() sets this value to pdTRUE then
|
||||||
* a context switch should be requested before the interrupt is exited.
|
* a context switch should be requested before the interrupt is exited.
|
||||||
*
|
*
|
||||||
* @return pdTRUE if the data was successfully sent to the queue, otherwise
|
* @return pdPASS if the data was successfully sent to the queue, otherwise
|
||||||
* errQUEUE_FULL.
|
* errQUEUE_FULL.
|
||||||
*
|
*
|
||||||
* Example usage for buffered IO (where the ISR can obtain more than one value
|
* Example usage for buffered IO (where the ISR can obtain more than one value
|
||||||
|
@ -1070,7 +1070,7 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
|
||||||
* running task. If xQueueSendToBackFromISR() sets this value to pdTRUE then
|
* running task. If xQueueSendToBackFromISR() sets this value to pdTRUE then
|
||||||
* a context switch should be requested before the interrupt is exited.
|
* a context switch should be requested before the interrupt is exited.
|
||||||
*
|
*
|
||||||
* @return pdTRUE if the data was successfully sent to the queue, otherwise
|
* @return pdPASS if the data was successfully sent to the queue, otherwise
|
||||||
* errQUEUE_FULL.
|
* errQUEUE_FULL.
|
||||||
*
|
*
|
||||||
* Example usage for buffered IO (where the ISR can obtain more than one value
|
* Example usage for buffered IO (where the ISR can obtain more than one value
|
||||||
|
@ -1235,7 +1235,7 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
|
||||||
* running task. If xQueueSendFromISR() sets this value to pdTRUE then
|
* running task. If xQueueSendFromISR() sets this value to pdTRUE then
|
||||||
* a context switch should be requested before the interrupt is exited.
|
* a context switch should be requested before the interrupt is exited.
|
||||||
*
|
*
|
||||||
* @return pdTRUE if the data was successfully sent to the queue, otherwise
|
* @return pdPASS if the data was successfully sent to the queue, otherwise
|
||||||
* errQUEUE_FULL.
|
* errQUEUE_FULL.
|
||||||
*
|
*
|
||||||
* Example usage for buffered IO (where the ISR can obtain more than one value
|
* Example usage for buffered IO (where the ISR can obtain more than one value
|
||||||
|
@ -1318,7 +1318,7 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
|
||||||
* item at the back of the queue, or queueSEND_TO_FRONT to place the item
|
* item at the back of the queue, or queueSEND_TO_FRONT to place the item
|
||||||
* at the front of the queue (for high priority messages).
|
* at the front of the queue (for high priority messages).
|
||||||
*
|
*
|
||||||
* @return pdTRUE if the data was successfully sent to the queue, otherwise
|
* @return pdPASS if the data was successfully sent to the queue, otherwise
|
||||||
* errQUEUE_FULL.
|
* errQUEUE_FULL.
|
||||||
*
|
*
|
||||||
* Example usage for buffered IO (where the ISR can obtain more than one value
|
* Example usage for buffered IO (where the ISR can obtain more than one value
|
||||||
|
@ -1389,8 +1389,8 @@ BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue,
|
||||||
* to unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will
|
* to unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will
|
||||||
* remain unchanged.
|
* remain unchanged.
|
||||||
*
|
*
|
||||||
* @return pdTRUE if an item was successfully received from the queue,
|
* @return pdPASS if an item was successfully received from the queue,
|
||||||
* otherwise pdFALSE.
|
* otherwise pdFAIL.
|
||||||
*
|
*
|
||||||
* Example usage:
|
* Example usage:
|
||||||
* @code{c}
|
* @code{c}
|
||||||
|
|
46
portable/CCRH/F1Kx/README.md
Normal file
46
portable/CCRH/F1Kx/README.md
Normal file
|
@ -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.
|
734
portable/CCRH/F1Kx/port.c
Normal file
734
portable/CCRH/F1Kx/port.c
Normal file
|
@ -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) */
|
325
portable/CCRH/F1Kx/portasm.s
Normal file
325
portable/CCRH/F1Kx/portasm.s
Normal file
|
@ -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
|
||||||
|
|
193
portable/CCRH/F1Kx/portmacro.h
Normal file
193
portable/CCRH/F1Kx/portmacro.h
Normal file
|
@ -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 */
|
|
@ -26,6 +26,9 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Hardware includes. */
|
||||||
|
#include "msp430.h"
|
||||||
|
|
||||||
/* Scheduler includes. */
|
/* Scheduler includes. */
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
|
@ -39,9 +39,6 @@
|
||||||
*-----------------------------------------------------------
|
*-----------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Hardware includes. */
|
|
||||||
#include "msp430.h"
|
|
||||||
|
|
||||||
/* Type definitions. */
|
/* Type definitions. */
|
||||||
#define portCHAR char
|
#define portCHAR char
|
||||||
#define portFLOAT float
|
#define portFLOAT float
|
||||||
|
@ -75,8 +72,8 @@ typedef unsigned short UBaseType_t;
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Interrupt control macros. */
|
/* Interrupt control macros. */
|
||||||
#define portDISABLE_INTERRUPTS() _disable_interrupt(); _nop()
|
#define portDISABLE_INTERRUPTS() __asm volatile ( " DINT\n" " NOP" )
|
||||||
#define portENABLE_INTERRUPTS() _enable_interrupt(); _nop()
|
#define portENABLE_INTERRUPTS() __asm volatile ( " NOP\n" " EINT\n" " NOP" )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Critical section control macros. */
|
/* Critical section control macros. */
|
||||||
|
@ -126,7 +123,7 @@ extern void vPortYield( void );
|
||||||
#define portBYTE_ALIGNMENT 2
|
#define portBYTE_ALIGNMENT 2
|
||||||
#define portSTACK_GROWTH ( -1 )
|
#define portSTACK_GROWTH ( -1 )
|
||||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
#define portNOP() __no_operation()
|
#define portNOP() __asm volatile ( " NOP" )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
.extern pxCurrentTCB
|
.extern pxCurrentTCB
|
||||||
.extern vTaskSwitchContext
|
.extern vTaskSwitchContext
|
||||||
.extern vApplicationIRQHandler
|
.extern vApplicationIRQHandler
|
||||||
|
.extern vApplicationFPUSafeIRQHandler
|
||||||
.extern ulPortInterruptNesting
|
.extern ulPortInterruptNesting
|
||||||
.extern ulPortTaskHasFPUContext
|
.extern ulPortTaskHasFPUContext
|
||||||
.extern ulICCEOIR
|
.extern ulICCEOIR
|
||||||
|
@ -237,6 +238,50 @@ vApplicationSVCHandler:
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* If the application provides an implementation of vApplicationIRQHandler(),
|
||||||
|
* then it will get called directly without saving the FPU registers on
|
||||||
|
* interrupt entry, and this weak implementation of vApplicationIRQHandler()
|
||||||
|
* will not get called.
|
||||||
|
*
|
||||||
|
* If the application provides its own implementation of
|
||||||
|
* vApplicationFPUSafeIRQHandler() then this implementation of
|
||||||
|
* vApplicationIRQHandler() will be called, save the FPU registers, and then
|
||||||
|
* call vApplicationFPUSafeIRQHandler().
|
||||||
|
*
|
||||||
|
* Therefore, if the application writer wants FPU registers to be saved on
|
||||||
|
* interrupt entry, their IRQ handler must be called
|
||||||
|
* vApplicationFPUSafeIRQHandler(), and if the application writer does not want
|
||||||
|
* FPU registers to be saved on interrupt entry their IRQ handler must be
|
||||||
|
* called vApplicationIRQHandler().
|
||||||
|
*/
|
||||||
|
.align 4
|
||||||
|
.weak vApplicationIRQHandler
|
||||||
|
.type vApplicationIRQHandler, %function
|
||||||
|
vApplicationIRQHandler:
|
||||||
|
PUSH {LR}
|
||||||
|
|
||||||
|
VMRS R1, FPSCR
|
||||||
|
VPUSH {D0-D7}
|
||||||
|
PUSH {R1}
|
||||||
|
|
||||||
|
BLX vApplicationFPUSafeIRQHandler
|
||||||
|
|
||||||
|
POP {R0}
|
||||||
|
VPOP {D0-D7}
|
||||||
|
VMSR FPSCR, R0
|
||||||
|
|
||||||
|
POP {PC}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.weak vApplicationFPUSafeIRQHandler
|
||||||
|
.type vApplicationFPUSafeIRQHandler, %function
|
||||||
|
vApplicationFPUSafeIRQHandler:
|
||||||
|
B vApplicationFPUSafeIRQHandler
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UBaseType_t ulPortCountLeadingZeros( UBaseType_t ulBitmap );
|
* UBaseType_t ulPortCountLeadingZeros( UBaseType_t ulBitmap );
|
||||||
*
|
*
|
||||||
|
|
|
@ -37,18 +37,16 @@
|
||||||
pusha
|
pusha
|
||||||
|
|
||||||
/* If ulInterruptNesting is zero the rest of the task context will need
|
/* If ulInterruptNesting is zero the rest of the task context will need
|
||||||
* saving and a stack switch might be required. */
|
saving and a stack switch might be required. */
|
||||||
movl ulInterruptNesting, %eax
|
movl ulInterruptNesting, %eax
|
||||||
test %eax, %eax
|
test %eax, %eax
|
||||||
jne 2f
|
jne 2f
|
||||||
|
|
||||||
/* Interrupts are not nested, so save the rest of the task context. */
|
/* Interrupts are not nested, so save the rest of the task context. */
|
||||||
.
|
.if configSUPPORT_FPU == 1
|
||||||
|
|
||||||
if configSUPPORT_FPU == 1
|
|
||||||
|
|
||||||
/* If the task has a buffer allocated to save the FPU context then
|
/* If the task has a buffer allocated to save the FPU context then
|
||||||
* save the FPU context now. */
|
save the FPU context now. */
|
||||||
movl pucPortTaskFPUContextBuffer, %eax
|
movl pucPortTaskFPUContextBuffer, %eax
|
||||||
test %eax, %eax
|
test %eax, %eax
|
||||||
je 1f
|
je 1f
|
||||||
|
@ -97,17 +95,16 @@ call vTaskSwitchContext
|
||||||
|
|
||||||
1:
|
1:
|
||||||
/* Stack location is first item in the TCB. */
|
/* Stack location is first item in the TCB. */
|
||||||
movl pxCurrentTCB, % eax movl( % eax ), % esp
|
movl pxCurrentTCB, %eax
|
||||||
|
movl (%eax), %esp
|
||||||
|
|
||||||
.
|
.if configSUPPORT_FPU == 1
|
||||||
|
|
||||||
if configSUPPORT_FPU == 1
|
|
||||||
|
|
||||||
/* Restore address of task's FPU context buffer. */
|
/* Restore address of task's FPU context buffer. */
|
||||||
pop pucPortTaskFPUContextBuffer
|
pop pucPortTaskFPUContextBuffer
|
||||||
|
|
||||||
/* If the task has a buffer allocated in which its FPU context is saved,
|
/* If the task has a buffer allocated in which its FPU context is saved,
|
||||||
* then restore it now. */
|
then restore it now. */
|
||||||
movl pucPortTaskFPUContextBuffer, %eax
|
movl pucPortTaskFPUContextBuffer, %eax
|
||||||
test %eax, %eax
|
test %eax, %eax
|
||||||
je 1f
|
je 1f
|
||||||
|
|
|
@ -30,6 +30,9 @@
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
|
/* Hardware includes. */
|
||||||
|
#include "msp430.h"
|
||||||
|
|
||||||
/*-----------------------------------------------------------
|
/*-----------------------------------------------------------
|
||||||
* Implementation of functions defined in portable.h for the MSP430X port.
|
* Implementation of functions defined in portable.h for the MSP430X port.
|
||||||
*----------------------------------------------------------*/
|
*----------------------------------------------------------*/
|
||||||
|
|
|
@ -39,9 +39,6 @@
|
||||||
*-----------------------------------------------------------
|
*-----------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Hardware includes. */
|
|
||||||
#include "msp430.h"
|
|
||||||
|
|
||||||
/* Type definitions. */
|
/* Type definitions. */
|
||||||
#define portCHAR char
|
#define portCHAR char
|
||||||
#define portFLOAT float
|
#define portFLOAT float
|
||||||
|
@ -75,8 +72,8 @@ typedef unsigned short UBaseType_t;
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Interrupt control macros. */
|
/* Interrupt control macros. */
|
||||||
#define portDISABLE_INTERRUPTS() _DINT(); _NOP()
|
#define portDISABLE_INTERRUPTS() __asm volatile ( "DINT\n" "NOP" )
|
||||||
#define portENABLE_INTERRUPTS() _EINT(); _NOP()
|
#define portENABLE_INTERRUPTS() __asm volatile ( "NOP\n" "EINT\n" "NOP" )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Critical section control macros. */
|
/* Critical section control macros. */
|
||||||
|
@ -126,7 +123,7 @@ extern void vPortYield( void );
|
||||||
#define portBYTE_ALIGNMENT 2
|
#define portBYTE_ALIGNMENT 2
|
||||||
#define portSTACK_GROWTH ( -1 )
|
#define portSTACK_GROWTH ( -1 )
|
||||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
#define portNOP() __no_operation()
|
#define portNOP() __asm volatile ( "NOP" )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||||
|
|
1
portable/ThirdParty/XCC/Xtensa/portmacro.h
vendored
1
portable/ThirdParty/XCC/Xtensa/portmacro.h
vendored
|
@ -114,6 +114,7 @@ static inline unsigned portENTER_CRITICAL_NESTED() { unsigned state = XTOS_SET_I
|
||||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
#define portBYTE_ALIGNMENT 4
|
#define portBYTE_ALIGNMENT 4
|
||||||
#define portNOP() XT_NOP()
|
#define portNOP() XT_NOP()
|
||||||
|
#define portMEMORY_BARRIER() XT_MEMW()
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Fine resolution time */
|
/* Fine resolution time */
|
||||||
|
|
8
queue.c
8
queue.c
|
@ -247,7 +247,7 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
|
||||||
* other tasks that are waiting for the same mutex. This function returns
|
* other tasks that are waiting for the same mutex. This function returns
|
||||||
* that priority.
|
* that priority.
|
||||||
*/
|
*/
|
||||||
static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;
|
static UBaseType_t prvGetHighestPriorityOfWaitToReceiveList( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;
|
||||||
#endif
|
#endif
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -1844,13 +1844,13 @@ BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue,
|
||||||
* has timed out the priority should be disinherited
|
* has timed out the priority should be disinherited
|
||||||
* again, but only as low as the next highest priority
|
* again, but only as low as the next highest priority
|
||||||
* task that is waiting for the same mutex. */
|
* task that is waiting for the same mutex. */
|
||||||
uxHighestWaitingPriority = prvGetDisinheritPriorityAfterTimeout( pxQueue );
|
uxHighestWaitingPriority = prvGetHighestPriorityOfWaitToReceiveList( pxQueue );
|
||||||
|
|
||||||
/* vTaskPriorityDisinheritAfterTimeout uses the uxHighestWaitingPriority
|
/* vTaskPriorityDisinheritAfterTimeout uses the uxHighestWaitingPriority
|
||||||
* parameter to index pxReadyTasksLists when adding the task holding
|
* parameter to index pxReadyTasksLists when adding the task holding
|
||||||
* mutex to the ready list for its new priority. Coverity thinks that
|
* mutex to the ready list for its new priority. Coverity thinks that
|
||||||
* it can result in out-of-bounds access which is not true because
|
* it can result in out-of-bounds access which is not true because
|
||||||
* uxHighestWaitingPriority, as returned by prvGetDisinheritPriorityAfterTimeout,
|
* uxHighestWaitingPriority, as returned by prvGetHighestPriorityOfWaitToReceiveList,
|
||||||
* is capped at ( configMAX_PRIORITIES - 1 ). */
|
* is capped at ( configMAX_PRIORITIES - 1 ). */
|
||||||
/* coverity[overrun] */
|
/* coverity[overrun] */
|
||||||
vTaskPriorityDisinheritAfterTimeout( pxQueue->u.xSemaphore.xMutexHolder, uxHighestWaitingPriority );
|
vTaskPriorityDisinheritAfterTimeout( pxQueue->u.xSemaphore.xMutexHolder, uxHighestWaitingPriority );
|
||||||
|
@ -2362,7 +2362,7 @@ UBaseType_t uxQueueGetQueueLength( QueueHandle_t xQueue ) /* PRIVILEGED_FUNCTION
|
||||||
|
|
||||||
#if ( configUSE_MUTEXES == 1 )
|
#if ( configUSE_MUTEXES == 1 )
|
||||||
|
|
||||||
static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue )
|
static UBaseType_t prvGetHighestPriorityOfWaitToReceiveList( const Queue_t * const pxQueue )
|
||||||
{
|
{
|
||||||
UBaseType_t uxHighestPriorityOfWaitingTasks;
|
UBaseType_t uxHighestPriorityOfWaitingTasks;
|
||||||
|
|
||||||
|
|
8
tasks.c
8
tasks.c
|
@ -4747,10 +4747,6 @@ BaseType_t xTaskIncrementTick( void )
|
||||||
TickType_t xItemValue;
|
TickType_t xItemValue;
|
||||||
BaseType_t xSwitchRequired = pdFALSE;
|
BaseType_t xSwitchRequired = pdFALSE;
|
||||||
|
|
||||||
#if ( configUSE_PREEMPTION == 1 ) && ( configNUMBER_OF_CORES > 1 )
|
|
||||||
BaseType_t xYieldRequiredForCore[ configNUMBER_OF_CORES ] = { pdFALSE };
|
|
||||||
#endif /* #if ( configUSE_PREEMPTION == 1 ) && ( configNUMBER_OF_CORES > 1 ) */
|
|
||||||
|
|
||||||
traceENTER_xTaskIncrementTick();
|
traceENTER_xTaskIncrementTick();
|
||||||
|
|
||||||
/* Called by the portable layer each time a tick interrupt occurs.
|
/* Called by the portable layer each time a tick interrupt occurs.
|
||||||
|
@ -4904,7 +4900,7 @@ BaseType_t xTaskIncrementTick( void )
|
||||||
{
|
{
|
||||||
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCBs[ xCoreID ]->uxPriority ] ) ) > 1U )
|
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCBs[ xCoreID ]->uxPriority ] ) ) > 1U )
|
||||||
{
|
{
|
||||||
xYieldRequiredForCore[ xCoreID ] = pdTRUE;
|
xYieldPendings[ xCoreID ] = pdTRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -4956,7 +4952,7 @@ BaseType_t xTaskIncrementTick( void )
|
||||||
if( pxCurrentTCBs[ xCoreID ]->xPreemptionDisable == pdFALSE )
|
if( pxCurrentTCBs[ xCoreID ]->xPreemptionDisable == pdFALSE )
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if( ( xYieldRequiredForCore[ xCoreID ] != pdFALSE ) || ( xYieldPendings[ xCoreID ] != pdFALSE ) )
|
if( xYieldPendings[ xCoreID ] != pdFALSE )
|
||||||
{
|
{
|
||||||
if( xCoreID == xCurrentCoreID )
|
if( xCoreID == xCurrentCoreID )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue