Merge branch 'main' into blocking_buffer

This commit is contained in:
Soren Ptak 2024-01-25 09:37:28 -05:00 committed by GitHub
commit 2869514910
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
122 changed files with 6081 additions and 3692 deletions

View file

@ -59,6 +59,7 @@ brhi
brne brne
bswtrg bswtrg
BSWTRG BSWTRG
Bytesto
CANEN CANEN
CANRX CANRX
CANTX CANTX
@ -89,13 +90,16 @@ CKGR
CKLO CKLO
CKPS CKPS
CLDIV CLDIV
CLEARINTENA
CLKA CLKA
CLKB CLKB
CLKDIS
CLKEN CLKEN
clki clki
CLKI CLKI
CLKP CLKP
CLKS CLKS
CLKSOURCE
CLKSTA CLKSTA
CLRB CLRB
CLRF CLRF
@ -120,6 +124,7 @@ CODR
comms comms
COMPA COMPA
CONFG CONFG
coremqtt
CORTUS CORTUS
coverity coverity
Coverity Coverity
@ -152,6 +157,7 @@ crhook
croutine croutine
CRTV CRTV
CSAAT CSAAT
CSDK
csrr csrr
csrs csrs
csrw csrw
@ -174,10 +180,15 @@ DATNB
DATRDY DATRDY
DBGU DBGU
DCDIC DCDIC
DCMOCK
DCMR DCMR
Dconfig
DCOUNT DCOUNT
decf decf
decfsz decfsz
decihours
Decihours
DECIHOURS
DECNT DECNT
DFPU DFPU
DFREERTOS DFREERTOS
@ -310,6 +321,7 @@ FSR
fwait fwait
GCACC GCACC
GCTRL GCTRL
getpacketid
getvect getvect
GIEH GIEH
GIEL GIEL
@ -370,6 +382,7 @@ ISRR
ISR's ISR's
ISRS ISRS
ISRTICK ISRTICK
isystem
ITIF ITIF
ITMC ITMC
ITMK ITMK
@ -512,6 +525,7 @@ MVTACHI
MVTACLO MVTACLO
MVTC MVTC
MVTIPL MVTIPL
mypy
NCFGR NCFGR
NCPHA NCPHA
NEBP NEBP
@ -521,6 +535,9 @@ NIOSII
NIRQ NIRQ
NOGIC NOGIC
noheap noheap
nondet
Nondet
NONDET
nostdint nostdint
NPCS NPCS
NRSTL NRSTL
@ -634,6 +651,9 @@ PUSHNE
PUSHW PUSHW
pushx pushx
PWMC PWMC
pylint
pytest
pyyaml
RAMPZ RAMPZ
RASR RASR
Rationalised Rationalised
@ -689,6 +709,7 @@ Rsvd
RTAR RTAR
RTCEN RTCEN
RTCSC RTCSC
RTICTL
RTIE RTIE
RTIF RTIF
RTIFRC RTIFRC
@ -712,6 +733,7 @@ RXRSM
RXSETUP RXSETUP
RXSUSP RXSUSP
RXSYN RXSYN
RXTDIS
RXTEN RXTEN
RXUBR RXUBR
SBYCR SBYCR
@ -725,6 +747,7 @@ SECU
SENDA SENDA
SETB SETB
SETEN SETEN
SETINTENA
SETPSW SETPSW
SETR SETR
setvect setvect
@ -847,8 +870,16 @@ TXUBR
TXVC TXVC
TXVDIS TXVDIS
UDCP UDCP
UNACKED
uncrustify uncrustify
UNDADD
unpadded
Unpadded
UNPADDED
UNRE UNRE
UNSUB
UNSUBACK
unsubscriptions
unsuspended unsuspended
URAD URAD
URAT URAT
@ -864,8 +895,10 @@ utilises
utilising utilising
VDDCORE VDDCORE
vect vect
Vect
VECT VECT
VECTACTIVE VECTACTIVE
VECTKEY
visualisation visualisation
vldmdbeq vldmdbeq
vldmia vldmia

View file

@ -62,7 +62,8 @@ KERNEL_IGNORED_EXTENSIONS = [
'.bat', '.bat',
'.sh', '.sh',
'.txt', '.txt',
'.cmake' '.cmake',
'.config'
] ]
KERNEL_ASM_EXTENSIONS = [ KERNEL_ASM_EXTENSIONS = [
@ -94,7 +95,7 @@ KERNEL_IGNORED_PATTERNS = [
r'.*IAR/78K0R/*', r'.*IAR/78K0R/*',
r'.*CCS/MSP430X/*', r'.*CCS/MSP430X/*',
r'.*portable/template/*', r'.*portable/template/*',
r'.*sample_configuration/*' r'.*template_configuration/*'
] ]
KERNEL_THIRD_PARTY_PATTERNS = [ KERNEL_THIRD_PARTY_PATTERNS = [

View file

@ -1,5 +1,123 @@
Documentation and download available at https://www.FreeRTOS.org/ Documentation and download available at https://www.FreeRTOS.org/
Changes between FreeRTOS V11.0.0 and FreeRTOS V11.0.1 released December 21, 2023
+ Updated the SBOM file.
Changes between FreeRTOS V10.6.2 and FreeRTOS V11.0.0 released December 18, 2023
+ SMP merged into the mainline: While FreeRTOS introduced Asymmetric
Multiprocessing (AMP) support in 2017, FreeRTOS Version 11.0.0 is the
first to merge Symmetric Multiprocessing (SMP) support into the mainline
release. SMP enables one instance of the FreeRTOS Kernel to schedule tasks
across multiple identical processor cores. We thank Mike Bruno and Jerry
McCarthy of XMOS and, Darian Liang, Sudeep Mohanty and Zim Kalinowski of
Espressif Systems for their contributions.
+ Switch MISRA compliance checking from PC Lint to Coverity, and update from
MISRA C:2004 to MISRA C:2012.
+ Add a template FreeRTOSConfig.h, inclusive of an abbreviated explanation of
each configuration item. Application writers can use this template as a
starting point to create the FreeRTOSConfig.h file for their application.
+ Add a template FreeRTOS port which can be used as a starting point for
developing a new FreeRTOS port.
+ Add bounds checking and obfuscation to internal heap block pointers in
heap_4.c and heap_5.c to help catch pointer corruptions. The application can
enable these checks by setting configENABLE_HEAP_PROTECTOR to 1 in their
FreeRTOSConfig.h. We thank @oliverlavery for their contribution.
+ Update vTaskList and vTaskGetRunTimeStats APIs to replace the use of sprintf
with snprintf.
+ Add trace macros to ports that enable tracing the interaction of ISRs with
scheduler events. We thank @conara for their contribution.
+ Add trace macros that enable tracing of entering and exiting all APIs. We
thank @Techcore123 for their contribution.
+ Add uxTaskBasePriorityGet and uxTaskBasePriorityGetFromISR APIs to get the
base priority of a task. The base priority of a task is the priority that
was last assigned to the task - which due to priority inheritance, may not
be the current priority of the task.
+ Add pdTICKS_TO_MS macro to convert time in FreeRTOS ticks to time in
milliseconds. We thank @Dazza0 for their contribution.
+ Add default implementations of vApplicationGetIdleTaskMemory and
vApplicationGetTimerTaskMemory. The application can enable these default
implementations by setting configKERNEL_PROVIDED_STATIC_MEMORY to 1 in their
FreeRTOSConfig.h. We thank @mdnr-g for their contribution.
+ Update vTaskGetInfo to include start and end of the stack whenever both
values are available. We thank @vinceburns for their contribution.
+ Prevent tasks waiting for a notification from being resumed by calls to
vTaskResume or vTaskResumeFromISR. We thank @Moral-Hao for their
contribution.
+ Add asserts to validate that the application has correctly installed
FreeRTOS handlers for PendSV and SVCall interrupts on Cortex-M devices.
We thank @jefftenney for their contribution.
+ Rename ARM_CA53_64_BIT and ARM_CA53_64_BIT_SRE ports to Arm_AARCH64 and
Arm_AARCH64_SRE respectively as these ports are applicable to all AArch64
architecture. We thank @urutva for their contribution.
+ Add CMake support to allow the application writer to select the RISC-V
chip extension. We thank @JoeBenczarski for their contribution.
+ Add CMake support to allow the application writer to build an application
with static allocation only. We thank @conara for their contribution.
+ Make taskYIELD available to unprivileged tasks for ARMv8-M ports.
+ Update Cortex-M23 ports to not use PSPLIM_NS. We thank @urutva for their
contribution.
+ Update the SysTick setup code for ARMv8-M ports to first configure the clock
source and then enable SysTick. This is needed to address a bug in QEMU
versions older than 7.0.0, which causes an emulation error if SysTick is
enabled without first selecting a valid clock source. We thank @jefftenney
for their contribution.
+ Add the port-optimized task selection algorithm optionally available for
ARMv7-M ports to the ARMv8-M ports. We thank @jefftenney for their
contribution.
+ Improve the speed of pvPortMalloc in heap_4.c and heap_5.c by removing
unnecessary steps while splitting a large memory block into two. We thank
@Moral-Hao for their contribution.
+ Shorten the critical section in pvPortMalloc in heap_2.c, heap_4.c and
heap_5.c by moving the size calculation out of the critical section. We thank
@Moral-Hao for their contribution.
+ Update xTaskNotifyWait and ulTaskNotifyTake to remove the non-deterministic
operation of traversing a linked link from a critical section. We thank
@karver8 for their contribution.
+ Fix stack end and stack size computation in POSIX port to meet the stack
alignment requirements on MacOS. We thank @tegimeki for their contribution.
+ Update the vTaskPrioritySet implementation to use the new priority when the
task has inherited priority from a mutex it is holding, and the new priority
is bigger than the inherited priority. We thank @Moral-Hao for their
contribution.
+ Add stack alignment adjustment if stack grows upwards. We thank @ivq for
their contribution.
+ Fix pxTopOfStack calculation in configINIT_TLS_BLOCK when picolib C is
selected as the C library implementation to ensure that
pxPortInitialiseStack does not overwrite the data in the TLS block portion
of the stack. We thank @bebebib-rs for their contribution.
+ Fix vPortEndScheduler() for the MSVC port so that the function
prvProcessSimulatedInterrupts is not stuck in an infinite loop when the
scheduler is stopped. We thank @Ju1He1 for their contribution.
+ Add the Pull Request (PR) Process explaining the stages a PR goes through.
Changes between FreeRTOS V10.6.1 and FreeRTOS V10.6.2 released November 29, 2023
+ Add the following improvements to the new MPU wrapper (mpu_wrappers_v2.c)
introduced in version 10.6.0:
- Introduce Access Control List (ACL) feature to allow the application
writer to control an unprivileged tasks access to kernel objects.
- Update the system call entry mechanism to only require one Supervisor
Call (SVC) instruction.
- Wrap parameters for system calls with more than four parameters in a
struct to avoid special handling during system call entry.
- Fix 2 possible integer overflows.
- Convert some asserts to run time parameter checks.
Changes between FreeRTOS V10.6.0 and FreeRTOS V10.6.1 released August 17, 2023
+ Add runtime parameter checks to functions in mpu_wrappers_v2.c file.
The same checks are already performed in API implementations using
asserts.
We thank the following people for their inputs in these changes:
- Lan Luo, Zixia Liu of School of Computer Science and Technology,
Anhui University of Technology, China.
- Xinwen Fu of Department of Computer Science, University of
Massachusetts Lowell, USA.
- Xinhui Shao, Yumeng Wei, Huaiyu Yan, Zhen Ling of School of
Computer Science and Engineering, Southeast University, China.
Changes between FreeRTOS V10.5.1 and FreeRTOS 10.6.0 released July 13, 2023 Changes between FreeRTOS V10.5.1 and FreeRTOS 10.6.0 released July 13, 2023
+ Add a new MPU wrapper that places additional restrictions on unprivileged + Add a new MPU wrapper that places additional restrictions on unprivileged

129
MISRA.md
View file

@ -8,8 +8,8 @@ has to be efficient. To achieve that and to increase the performance, it
deviates from some MISRA rules. The specific deviations, suppressed inline, deviates from some MISRA rules. The specific deviations, suppressed inline,
are listed below. are listed below.
Additionally, [MISRA configuration](#misra-configuration) contains project Additionally, [MISRA configuration file](examples/coverity/coverity_misra.config)
wide deviations. contains project wide deviations.
### Suppressed with Coverity Comments ### Suppressed with Coverity Comments
To find the violation references in the source files run grep on the source code To find the violation references in the source files run grep on the source code
@ -20,25 +20,46 @@ grep 'MISRA Ref 8.4.1' . -rI
#### Rule 8.4 #### Rule 8.4
MISRA C:2012 Rule 8.4: A compatible declaration shall be visible when an
object or function with external linkage is defined.
_Ref 8.4.1_ _Ref 8.4.1_
- pxCurrentTCB(s) is defined with external linkage but it is only referenced
from the assembly code in the port files. Therefore, adding a declaration in
header file is not useful as the assembly code will still need to declare it
separately.
- MISRA C:2012 Rule 8.4: A compatible declaration shall be visible when an _Ref 8.4.2_
object or function with external linkage is defined. - xQueueRegistry is defined with external linkage because it is accessed by the
This rule requires that a compatible declaration is made available kernel unit tests. It is not meant to be directly accessed by the application
in a header file when an object with external linkage is defined. and therefore, not declared in a header file.
pxCurrentTCB(s) is defined with external linkage but it is only
referenced from the assembly code in the port files. Therefore, adding
a declaration in header file is not useful as the assembly code will
still need to declare it separately.
#### Rule 8.6
MISRA C:2012 Rule 8.6: An identifier with external linkage shall have exactly
one external definition.
_Ref 8.6.1_
- This rule prohibits an identifier with external linkage to have multiple
definitions or no definition. FreeRTOS hook functions are implemented in
the application and therefore, have no definition in the Kernel code.
#### Rule 11.1
MISRA C:2012 Rule 11.1: Conversions shall not be performed between a pointer to
function and any other type.
_Ref 11.1.1_
- The pointer to function is casted into void to avoid unused parameter
compiler warning when Stream Buffer's Tx and Rx Completed callback feature is
not used.
#### Rule 11.3 #### Rule 11.3
_Ref 11.3.1_ MISRA C:2012 Rule 11.3: A cast shall not be performed between a pointer to
object type and a pointer to a different object type.
- MISRA C:2012 Rule 11.3: A cast shall not be performed between a pointer to _Ref 11.3.1_
object type and a pointer to a different object type. - This rule prohibits casting a pointer to object into a pointer to a
This rule prohibits casting a pointer to object into a pointer to a
different object because it may result in an incorrectly aligned pointer, different object because it may result in an incorrectly aligned pointer,
leading to undefined behavior. Even if the casting produces a correctly leading to undefined behavior. Even if the casting produces a correctly
aligned pointer, the behavior may be still undefined if the pointer is aligned pointer, the behavior may be still undefined if the pointer is
@ -50,42 +71,48 @@ _Ref 11.3.1_
checked using configASSERT. checked using configASSERT.
### MISRA configuration #### Rule 11.5
Copy below content to `misra.conf` to run Coverity on FreeRTOS-Kernel. MISRA C:2012 Rule 11.5: A conversion should not be performed from pointer to
void into pointer to object.
This rule prohibits conversion of a pointer to void into a pointer to
object because it may result in an incorrectly aligned pointer leading
to undefined behavior.
``` _Ref 11.5.1_
// MISRA C-2012 Rules - The memory blocks returned by pvPortMalloc() are guaranteed to meet the
{ architecture alignment requirements specified by portBYTE_ALIGNMENT.
version : "2.0", The casting of the pointer to void returned by pvPortMalloc() is,
standard : "c2012", therefore, safe because it is guaranteed to be aligned.
title: "Coverity MISRA Configuration",
deviations : [ _Ref 11.5.2_
// Disable the following rules. - The conversion from a pointer to void into a pointer to EventGroup_t is
{ safe because it is a pointer to EventGroup_t, which is returned to the
deviation: "Directive 4.8", application at the time of event group creation for data hiding
reason: "HeapRegion_t and HeapStats_t are used only in heap files but declared in portable.h which is included in multiple source files. As a result, these definitions appear in multiple source files where they are not used." purposes.
},
{ _Ref 11.5.3_
deviation: "Directive 4.9", - The conversion from a pointer to void in list macros for list item owner
reason: "FreeRTOS-Kernel is optimised to work on small micro-controllers. To achieve that, function-like macros are used." is safe because the type of the pointer stored and retrieved is the
}, same.
{
deviation: "Rule 1.2", _Ref 11.5.4_
reason: "The __attribute__ tags are used via macros which are defined in port files." - The conversion from a pointer to void into a pointer to EventGroup_t is
}, safe because it is a pointer to EventGroup_t, which is passed as a
{ parameter to the xTimerPendFunctionCallFromISR API when the callback is
deviation: "Rule 3.1", pended.
reason: "We post HTTP links in code comments which contain // inside comments blocks."
}, _Ref 11.5.5_
{ - The conversion from a pointer to void into a pointer to uint8_t is safe
deviation: "Rule 8.7", because data storage buffers are implemented as uint8_t arrays for the
reason: "API functions are not used by the library outside of the files they are defined; however, they must be externally visible in order to be used by an application." ease of sizing, alignment and access.
},
{ #### Rule 21.6
deviation: "Rule 11.5",
reason: "Allow casts from `void *`. List owner, pvOwner, is stored as `void *` and are cast to various types for use in functions." MISRA C-2012 Rule 21.6: The Standard Library input/output functions shall not
} be used.
]
} _Ref 21.6.1_
``` - The Standard Library function snprintf is used in vTaskListTasks and
vTaskGetRunTimeStatistics APIs, both of which are utility functions only and
are not considered part of core kernel implementation.

View file

@ -124,8 +124,8 @@ See the readme file in the ```./portable``` directory for more information.
- The ```./include``` directory contains the real time kernel header files. - The ```./include``` directory contains the real time kernel header files.
- The ```./sample_configuration``` directory contains a sample `FreeRTOSConfig.h` to help jumpstart a new project. - The ```./template_configuration``` directory contains a sample `FreeRTOSConfig.h` to help jumpstart a new project.
See the [FreeRTOSConfig.h](examples/sample_configuration/FreeRTOSConfig.h) file for instructions. See the [FreeRTOSConfig.h](examples/template_configuration/FreeRTOSConfig.h) file for instructions.
### Code Formatting ### Code Formatting

View file

@ -110,6 +110,9 @@
traceENTER_xCoRoutineCreate( pxCoRoutineCode, uxPriority, uxIndex ); traceENTER_xCoRoutineCreate( pxCoRoutineCode, uxPriority, uxIndex );
/* Allocate the memory that will store the co-routine control block. */ /* Allocate the memory that will store the co-routine control block. */
/* MISRA Ref 11.5.1 [Malloc memory assignment] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) ); pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );
if( pxCoRoutine ) if( pxCoRoutine )

View file

@ -40,11 +40,10 @@
#include "timers.h" #include "timers.h"
#include "event_groups.h" #include "event_groups.h"
/* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified /* The MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
* because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
* for the header files above, but not in this file, in order to generate the * for the header files above, but not in this file, in order to generate the
* correct privileged Vs unprivileged linkage and placement. */ * correct privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021 See comment above. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
typedef struct EventGroupDef_t typedef struct EventGroupDef_t
{ {
@ -94,7 +93,7 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
* event group structure. */ * event group structure. */
volatile size_t xSize = sizeof( StaticEventGroup_t ); volatile size_t xSize = sizeof( StaticEventGroup_t );
configASSERT( xSize == sizeof( EventGroup_t ) ); configASSERT( xSize == sizeof( EventGroup_t ) );
} /*lint !e529 xSize is referenced if configASSERT() is defined. */ }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* The user has provided a statically allocated event group - use it. */ /* The user has provided a statically allocated event group - use it. */
@ -143,20 +142,10 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
traceENTER_xEventGroupCreate(); traceENTER_xEventGroupCreate();
/* Allocate the event group. Justification for MISRA deviation as /* MISRA Ref 11.5.1 [Malloc memory assignment] */
* follows: pvPortMalloc() always ensures returned memory blocks are /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
* aligned per the requirements of the MCU stack. In this case /* coverity[misra_c_2012_rule_11_5_violation] */
* pvPortMalloc() must return a pointer that is guaranteed to meet the pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
* alignment requirements of the EventGroup_t structure - which (if you
* follow it through) is the alignment requirements of the TickType_t type
* (EventBits_t being of TickType_t itself). Therefore, whenever the
* stack alignment requirements are greater than or equal to the
* TickType_t alignment requirements the cast is safe. In other cases,
* where the natural word size of the architecture is less than
* sizeof( TickType_t ), the TickType_t variables will be accessed in two
* or more reads operations, and the alignment requirements is only that
* of each individual read. */
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); /*lint !e9087 !e9079 see comment above. */
if( pxEventBits != NULL ) if( pxEventBits != NULL )
{ {
@ -176,7 +165,7 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
} }
else else
{ {
traceEVENT_GROUP_CREATE_FAILED(); /*lint !e9063 Else branch only exists to allow tracing and does not generate code if trace macros are not defined. */ traceEVENT_GROUP_CREATE_FAILED();
} }
traceRETURN_xEventGroupCreate( pxEventBits ); traceRETURN_xEventGroupCreate( pxEventBits );
@ -516,7 +505,7 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
traceENTER_xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ); traceENTER_xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear );
traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ); traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */ xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL );
traceRETURN_xEventGroupClearBitsFromISR( xReturn ); traceRETURN_xEventGroupClearBitsFromISR( xReturn );
@ -543,7 +532,7 @@ EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
traceRETURN_xEventGroupGetBitsFromISR( uxReturn ); traceRETURN_xEventGroupGetBitsFromISR( uxReturn );
return uxReturn; return uxReturn;
} /*lint !e818 EventGroupHandle_t is a typedef used in other functions to so can't be pointer to const. */ }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
@ -565,7 +554,7 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
pxList = &( pxEventBits->xTasksWaitingForBits ); pxList = &( pxEventBits->xTasksWaitingForBits );
pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ pxListEnd = listGET_END_MARKER( pxList );
vTaskSuspendAll(); vTaskSuspendAll();
{ {
traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ); traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
@ -745,11 +734,14 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup )
/* For internal use only - execute a 'set bits' command that was pended from /* For internal use only - execute a 'set bits' command that was pended from
* an interrupt. */ * an interrupt. */
void vEventGroupSetBitsCallback( void * pvEventGroup, void vEventGroupSetBitsCallback( void * pvEventGroup,
const uint32_t ulBitsToSet ) uint32_t ulBitsToSet )
{ {
traceENTER_vEventGroupSetBitsCallback( pvEventGroup, ulBitsToSet ); traceENTER_vEventGroupSetBitsCallback( pvEventGroup, ulBitsToSet );
( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */ /* MISRA Ref 11.5.4 [Callback function parameter] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet );
traceRETURN_vEventGroupSetBitsCallback(); traceRETURN_vEventGroupSetBitsCallback();
} }
@ -758,11 +750,14 @@ void vEventGroupSetBitsCallback( void * pvEventGroup,
/* For internal use only - execute a 'clear bits' command that was pended from /* For internal use only - execute a 'clear bits' command that was pended from
* an interrupt. */ * an interrupt. */
void vEventGroupClearBitsCallback( void * pvEventGroup, void vEventGroupClearBitsCallback( void * pvEventGroup,
const uint32_t ulBitsToClear ) uint32_t ulBitsToClear )
{ {
traceENTER_vEventGroupClearBitsCallback( pvEventGroup, ulBitsToClear ); traceENTER_vEventGroupClearBitsCallback( pvEventGroup, ulBitsToClear );
( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); /*lint !e9079 Can't avoid cast to void* as a generic timer callback prototype. Callback casts back to original type so safe. */ /* MISRA Ref 11.5.4 [Callback function parameter] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear );
traceRETURN_vEventGroupClearBitsCallback(); traceRETURN_vEventGroupClearBitsCallback();
} }
@ -816,7 +811,7 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
traceENTER_xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ); traceENTER_xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken );
traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ); traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); /*lint !e9087 Can't avoid cast to void* as a generic callback function not specific to this use case. Callback casts back to original type so safe. */ xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken );
traceRETURN_xEventGroupSetBitsFromISR( xReturn ); traceRETURN_xEventGroupSetBitsFromISR( xReturn );
@ -831,7 +826,11 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
UBaseType_t uxEventGroupGetNumber( void * xEventGroup ) UBaseType_t uxEventGroupGetNumber( void * xEventGroup )
{ {
UBaseType_t xReturn; UBaseType_t xReturn;
EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */
/* MISRA Ref 11.5.2 [Opaque pointer] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup;
traceENTER_uxEventGroupGetNumber( xEventGroup ); traceENTER_uxEventGroupGetNumber( xEventGroup );
@ -859,7 +858,10 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
{ {
traceENTER_vEventGroupSetNumber( xEventGroup, uxEventGroupNumber ); traceENTER_vEventGroupSetNumber( xEventGroup, uxEventGroupNumber );
( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; /*lint !e9087 !e9079 EventGroupHandle_t is a pointer to an EventGroup_t, but EventGroupHandle_t is kept opaque outside of this file for data hiding purposes. */ /* MISRA Ref 11.5.2 [Opaque pointer] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */
/* coverity[misra_c_2012_rule_11_5_violation] */
( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber;
traceRETURN_vEventGroupSetNumber(); traceRETURN_vEventGroupSetNumber();
} }

View file

@ -7,18 +7,15 @@ set(FREERTOS_KERNEL_PATH "../../")
# Add the freertos_config for FreeRTOS-Kernel # Add the freertos_config for FreeRTOS-Kernel
add_library(freertos_config INTERFACE) add_library(freertos_config INTERFACE)
target_include_directories(freertos_config
INTERFACE
"../template_configuration"
)
if (DEFINED FREERTOS_SMP_EXAMPLE AND FREERTOS_SMP_EXAMPLE STREQUAL "1") if (DEFINED FREERTOS_SMP_EXAMPLE AND FREERTOS_SMP_EXAMPLE STREQUAL "1")
message(STATUS "Build FreeRTOS SMP example") message(STATUS "Build FreeRTOS SMP example")
target_include_directories(freertos_config # Adding the following configurations to build SMP template port
INTERFACE add_compile_options( -DconfigNUMBER_OF_CORES=2 -DconfigUSE_PASSIVE_IDLE_HOOK=0 )
"../sample_configuration/smp"
)
else()
message(STATUS "Build FreeRTOS example")
target_include_directories(freertos_config
INTERFACE
"../sample_configuration"
)
endif() endif()
# Select the heap port. values between 1-4 will pick a heap. # Select the heap port. values between 1-4 will pick a heap.

View file

@ -33,17 +33,16 @@
* https://freertos.org/FreeRTOS-quick-start-guide.html * https://freertos.org/FreeRTOS-quick-start-guide.html
*/ */
/* FreeRTOS includes. */
#include <FreeRTOS.h> #include <FreeRTOS.h>
#include <task.h> #include <task.h>
#include <queue.h> #include <queue.h>
#include <timers.h> #include <timers.h>
#include <semphr.h> #include <semphr.h>
/* Standard includes. */
#include <stdio.h> #include <stdio.h>
static StaticTask_t exampleTaskTCB;
static StackType_t exampleTaskStack[ configMINIMAL_STACK_SIZE ];
void exampleTask( void * parameters ) void exampleTask( void * parameters )
{ {
/* Unused parameters. */ /* Unused parameters. */
@ -55,9 +54,13 @@ void exampleTask( void * parameters )
vTaskDelay( 100 ); /* delay 100 ticks */ vTaskDelay( 100 ); /* delay 100 ticks */
} }
} }
/*-----------------------------------------------------------*/
void main( void ) void main( void )
{ {
static StaticTask_t exampleTaskTCB;
static StackType_t exampleTaskStack[ configMINIMAL_STACK_SIZE ];
printf( "Example FreeRTOS Project\n" ); printf( "Example FreeRTOS Project\n" );
xTaskCreateStatic( exampleTask, xTaskCreateStatic( exampleTask,
@ -65,8 +68,8 @@ void main( void )
configMINIMAL_STACK_SIZE, configMINIMAL_STACK_SIZE,
NULL, NULL,
configMAX_PRIORITIES - 1, configMAX_PRIORITIES - 1,
exampleTaskStack, &( exampleTaskStack[ 0 ] ),
&exampleTaskTCB ); &( exampleTaskTCB ) );
/* Start the scheduler. */ /* Start the scheduler. */
vTaskStartScheduler(); vTaskStartScheduler();
@ -76,6 +79,7 @@ void main( void )
/* Should not reach here. */ /* Should not reach here. */
} }
} }
/*-----------------------------------------------------------*/
void vApplicationStackOverflowHook( TaskHandle_t xTask, void vApplicationStackOverflowHook( TaskHandle_t xTask,
char * pcTaskName ) char * pcTaskName )
@ -85,3 +89,4 @@ void vApplicationStackOverflowHook( TaskHandle_t xTask,
( void ) xTask; ( void ) xTask;
( void ) pcTaskName; ( void ) pcTaskName;
} }
/*-----------------------------------------------------------*/

View file

@ -0,0 +1,39 @@
cmake_minimum_required(VERSION 3.15)
project(coverity)
set(FREERTOS_KERNEL_PATH "../../")
FILE(GLOB FREERTOS_KERNEL_SOURCE ${FREERTOS_KERNEL_PATH}*.c)
# Coverity incorrectly infers the type of pdTRUE and pdFALSE as boolean because
# of their names. This generates multiple false positive warnings about type
# mismatch. Replace pdTRUE with pdPASS and pdFALSE with pdFAIL to avoid these
# false positive warnings. This workaround will not be needed after Coverity
# fixes the issue of incorrectly inferring the type of pdTRUE and pdFALSE as
# boolean.
add_custom_target(fix_source ALL
COMMAND sed -i -b -e 's/pdFALSE/pdFAIL/g' -e 's/pdTRUE/pdPASS/g' ${FREERTOS_KERNEL_SOURCE}
DEPENDS ${FREERTOS_KERNEL_SOURCE})
# Add the freertos_config for FreeRTOS-Kernel.
add_library(freertos_config INTERFACE)
target_include_directories(freertos_config
INTERFACE
./)
# Select the heap. Values between 1-5 will pick a heap.
set(FREERTOS_HEAP "3" CACHE STRING "" FORCE)
# Select the FreeRTOS port.
set(FREERTOS_PORT "TEMPLATE" CACHE STRING "" FORCE)
# Add the FreeRTOS-Kernel subdirectory.
add_subdirectory(${FREERTOS_KERNEL_PATH} FreeRTOS-Kernel)
add_executable(${PROJECT_NAME}
../cmake_example/main.c)
add_dependencies(${PROJECT_NAME} fix_source)
target_link_libraries(${PROJECT_NAME} freertos_kernel freertos_config)

View file

@ -0,0 +1,135 @@
/*
* 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 FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/******************************************************************************/
/* Hardware description related definitions. **********************************/
/******************************************************************************/
#define configCPU_CLOCK_HZ ( ( unsigned long ) 20000000 )
/******************************************************************************/
/* Scheduling behaviour related definitions. **********************************/
/******************************************************************************/
#define configTICK_RATE_HZ ( 100U )
#define configUSE_PREEMPTION 1
#define configUSE_TIME_SLICING 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configUSE_TICKLESS_IDLE 1
#define configMAX_PRIORITIES 5U
#define configMINIMAL_STACK_SIZE 128U
#define configMAX_TASK_NAME_LEN 4U
#define configTICK_TYPE_WIDTH_IN_BITS TICK_TYPE_WIDTH_64_BITS
#define configIDLE_SHOULD_YIELD 1
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 1U
#define configQUEUE_REGISTRY_SIZE 0U
#define configENABLE_BACKWARD_COMPATIBILITY 1
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0
#define configSTACK_DEPTH_TYPE size_t
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t
#define configUSE_NEWLIB_REENTRANT 0
/******************************************************************************/
/* Software timer related definitions. ****************************************/
/******************************************************************************/
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1U )
#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
#define configTIMER_QUEUE_LENGTH 10U
/******************************************************************************/
/* Memory allocation related definitions. *************************************/
/******************************************************************************/
#define configSUPPORT_STATIC_ALLOCATION 1
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configTOTAL_HEAP_SIZE 4096U
#define configAPPLICATION_ALLOCATED_HEAP 1
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
#define configUSE_MINI_LIST_ITEM 0
/******************************************************************************/
/* Interrupt nesting behaviour configuration. *********************************/
/******************************************************************************/
#define configKERNEL_INTERRUPT_PRIORITY 0U
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 0U
#define configMAX_API_CALL_INTERRUPT_PRIORITY 0U
/******************************************************************************/
/* Hook and callback function related definitions. ****************************/
/******************************************************************************/
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
#define configCHECK_FOR_STACK_OVERFLOW 0
/******************************************************************************/
/* Run time and task stats gathering related definitions. *********************/
/******************************************************************************/
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 0
#define configUSE_STATS_FORMATTING_FUNCTIONS 0
#define configKERNEL_PROVIDED_STATIC_MEMORY 1
/******************************************************************************/
/* Definitions that include or exclude functionality. *************************/
/******************************************************************************/
#define configUSE_TASK_NOTIFICATIONS 1
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_QUEUE_SETS 1
#define configUSE_APPLICATION_TASK_TAG 1
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_xResumeFromISR 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_xTaskGetIdleTaskHandle 1
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xEventGroupSetBitFromISR 1
#define INCLUDE_xTimerPendFunctionCall 1
#define INCLUDE_xTaskAbortDelay 1
#define INCLUDE_xTaskGetHandle 1
#define INCLUDE_xTaskResumeFromISR 1
#endif /* FREERTOS_CONFIG_H */

View file

@ -0,0 +1,58 @@
# MISRA Compliance for FreeRTOS-Kernel
FreeRTOS-Kernel is MISRA C:2012 compliant. This directory contains a project to
run [Synopsys Coverity](https://www.synopsys.com/software-integrity/security-testing/static-analysis-sast.html)
for checking MISRA compliance.
> **Note**
Coverity version 2022.6.1 incorrectly infers the type of `pdTRUE` and `pdFALSE`
as boolean because of their names, resulting in multiple false positive warnings
about type mismatch. We replace `pdTRUE` with `pdPASS` and `pdFALSE` with
`pdFAIL` to avoid these false positive warnings. This workaround will not be
needed after Coverity fixes the issue of incorrectly inferring the type of
`pdTRUE` and `pdFALSE` as boolean.
Deviations from the MISRA C:2012 guidelines are documented in
[MISRA.md](../../MISRA.md) and [coverity_misra.config](coverity_misra.config)
files.
## Getting Started
### Prerequisites
Coverity can be run on any platform mentioned [here](https://sig-docs.synopsys.com/polaris/topics/c_coverity-compatible-platforms.html).
The following are the prerequisites to generate coverity report:
1. CMake version > 3.13.0 (You can check whether you have this by typing `cmake --version`).
2. GCC compiler.
- See download and installation instructions [here](https://gcc.gnu.org/install/).
3. Clone the repo using the following command:
- `git clone https://github.com/FreeRTOS/FreeRTOS-Kernel.git ./FreeRTOS-Kernel`
### Generating Report
Go to the root directory of the FreeRTOS-Kernel repo and run the following
commands in a terminal:
1. Update the compiler configuration in Coverity:
~~~
cov-configure --force --compiler cc --comptype gcc
~~~
2. Create the build files using CMake in a `build` directory:
~~~
cmake -B build -S examples/coverity
~~~
3. Build the (pseudo) application:
~~~
cd build/
cov-build --emit-complementary-info --dir cov-out make
~~~
4. Go to the Coverity output directory (`cov-out`) and begin Coverity static
analysis:
~~~
cd cov-out/
cov-analyze --dir ./cov-out \
--coding-standard-config ../examples/coverity/coverity_misra.config \
--tu-pattern "file('.*/FreeRTOS/Source/[A-Za-z_]*\.c')
~~~
5. Generate the HTML report:
~~~
cov-format-errors --dir ./cov-out --html-output html-output
~~~
HTML report should now be generated in a directory named `html-output`.

View file

@ -0,0 +1,97 @@
// MISRA C-2012 Rules
{
version : "2.0",
standard : "c2012",
title: "Coverity MISRA Configuration",
deviations : [
// Disable the following rules.
{
deviation: "Rule 3.1",
reason: "We post HTTP links in code comments which contain // inside comments blocks."
},
{
deviation: "Rule 14.4",
reason: "do while( 0 ) pattern is used in macros to prevent extra semi-colon."
},
// Disable the following advisory rules and directives.
{
deviation: "Directive 4.4",
reason: "Code snippet is used in comment to help explanation."
},
{
deviation: "Directive 4.5",
reason: "Allow names that MISRA considers ambiguous."
},
{
deviation: "Directive 4.6",
reason: "Allow port to use primitive type with typedefs."
},
{
deviation: "Directive 4.8",
reason: "HeapRegion_t and HeapStats_t are used only in heap files but declared in portable.h which is included in multiple source files. As a result, these definitions appear in multiple source files where they are not used."
},
{
deviation: "Directive 4.9",
reason: "FreeRTOS-Kernel is optimised to work on small micro-controllers. To achieve that, function-like macros are used."
},
{
deviation: "Rule 2.3",
reason: "FreeRTOS defines types which is used in application."
},
{
deviation: "Rule 2.4",
reason: "Allow to define unused tag."
},
{
deviation: "Rule 2.5",
reason: "Allow to define unused macro."
},
{
deviation: "Rule 5.9",
reason: "Allow to define identifier with the same name in structure and global variable."
},
{
deviation: "Rule 8.7",
reason: "API functions are not used by the library outside of the files they are defined; however, they must be externally visible in order to be used by an application."
},
{
deviation: "Rule 8.9",
reason: "Allow to object to be defined in wider scope for debug purpose."
},
{
deviation: "Rule 8.13",
reason: "Allow to not to use const-qualified type for callback function."
},
{
deviation: "Rule 11.4",
reason: "Allow to convert between a pointer to object and an interger type for stack alignment."
},
{
deviation: "Rule 15.4",
reason: "Allow to use multiple break statements in a loop."
},
{
deviation: "Rule 15.5",
reason: "Allow to use multiple points of exit."
},
{
deviation: "Rule 17.8",
reason: "Allow to update the parameters of a function."
},
{
deviation: "Rule 18.4",
reason: "Allow to use pointer arithmetic."
},
{
deviation: "Rule 19.2",
reason: "Allow to use union."
},
{
deviation: "Rule 20.5",
reason: "Allow to use #undef for MPU wrappers."
}
]
}

View file

@ -1,65 +0,0 @@
/*
* 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
*
*/
/*******************************************************************************
* This file provides an example FreeRTOSConfig.h header file, inclusive of an
* abbreviated explanation of each configuration item. Online and reference
* documentation provides more information.
* https://www.freertos.org/a00110.html
*
* Constant values enclosed in square brackets ('[' and ']') must be completed
* before this file will build.
*
* Use the FreeRTOSConfig.h supplied with the RTOS port in use rather than this
* generic file, if one is available.
******************************************************************************/
#ifndef __FREERTOS_CONFIG_SMP_H__
#define __FREERTOS_CONFIG_SMP_H__
#include "../FreeRTOSConfig.h"
/******************************************************************************/
/* Scheduling behaviour related definitions. **********************************/
/******************************************************************************/
/* Set configNUMBER_OF_CORES to greater than 1 to enable running one instance of
* FreeRTOS kernel to schedule tasks across multiple identical processor cores. */
#define configNUMBER_OF_CORES 2
/******************************************************************************/
/* Hook and callback function related definitions. ****************************/
/******************************************************************************/
/* Set the following configUSE_* constants to 1 to include the named hook
* functionality in the build. Set to 0 to exclude the hook functionality from the
* build. The application writer is responsible for providing the hook function
* for any set to 1. See https://www.freertos.org/a00016.html */
#define configUSE_PASSIVE_IDLE_HOOK 0
#endif /* __FREERTOS_CONFIG_SMP_H__ */

View file

@ -1,10 +0,0 @@
# Configuration support for FreeRTOS SMP
## Overview
The FreeRTOSConfig.h provided in this folder is a sample configuration that will
assist you in preparing the configuration to enable SMP support in the FreeRTOS
Kernel for your application.
Based on single core sample configuration file, this configuration file is created
with minimal configuration change. More SMP scheduler configurations can be found
in [Symmetric Multiprocessing (SMP) with FreeRTOS](https://freertos.org/symmetric-multiprocessing-introduction.html)

View file

@ -39,8 +39,8 @@
* generic file, if one is available. * generic file, if one is available.
******************************************************************************/ ******************************************************************************/
#ifndef __FREERTOS_CONFIG_H__ #ifndef FREERTOS_CONFIG_H
#define __FREERTOS_CONFIG_H__ #define FREERTOS_CONFIG_H
/******************************************************************************/ /******************************************************************************/
/* Hardware description related definitions. **********************************/ /* Hardware description related definitions. **********************************/
@ -63,7 +63,7 @@
* frequency, as normal, and configSYSTICK_CLOCK_HZ to the SysTick clock * frequency, as normal, and configSYSTICK_CLOCK_HZ to the SysTick clock
* frequency. Not used if left undefined. * frequency. Not used if left undefined.
* The default value is undefined (commented out). If you need this value bring it * The default value is undefined (commented out). If you need this value bring it
* back and set it to a suitable value */ * back and set it to a suitable value. */
/* /*
#define configSYSTICK_CLOCK_HZ [Platform specific] #define configSYSTICK_CLOCK_HZ [Platform specific]
@ -79,14 +79,14 @@
/* Set configUSE_PREEMPTION to 1 to use pre-emptive scheduling. Set /* Set configUSE_PREEMPTION to 1 to use pre-emptive scheduling. Set
* configUSE_PREEMPTION to 0 to use co-operative scheduling. * configUSE_PREEMPTION to 0 to use co-operative scheduling.
* See https://www.freertos.org/single-core-amp-smp-rtos-scheduling.html */ * See https://www.freertos.org/single-core-amp-smp-rtos-scheduling.html. */
#define configUSE_PREEMPTION 1 #define configUSE_PREEMPTION 1
/* Set configUSE_TIME_SLICING to 1 to have the scheduler switch between Ready /* Set configUSE_TIME_SLICING to 1 to have the scheduler switch between Ready
* state tasks of equal priority on every tick interrupt. Set * state tasks of equal priority on every tick interrupt. Set
* configUSE_TIME_SLICING to 0 to prevent the scheduler switching between Ready * configUSE_TIME_SLICING to 0 to prevent the scheduler switching between Ready
* state tasks just because there was a tick interrupt. See * state tasks just because there was a tick interrupt. See
* https://freertos.org/single-core-amp-smp-rtos-scheduling.html */ * https://freertos.org/single-core-amp-smp-rtos-scheduling.html. */
#define configUSE_TIME_SLICING 0 #define configUSE_TIME_SLICING 0
/* Set configUSE_PORT_OPTIMISED_TASK_SELECTION to 1 to select the next task to /* Set configUSE_PORT_OPTIMISED_TASK_SELECTION to 1 to select the next task to
@ -162,6 +162,13 @@
* Defaults to 0 if left undefined. */ * Defaults to 0 if left undefined. */
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0 #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0
/* When configUSE_MINI_LIST_ITEM is set to 0, MiniListItem_t and ListItem_t are
* both the same. When configUSE_MINI_LIST_ITEM is set to 1, MiniListItem_t contains
* 3 fewer fields than ListItem_t which saves some RAM at the cost of violating
* strict aliasing rules which some compilers depend on for optimization. Defaults
* to 1 if left undefined. */
#define configUSE_MINI_LIST_ITEM 1
/* Sets the type used by the parameter to xTaskCreate() that specifies the stack /* Sets the type used by the parameter to xTaskCreate() that specifies the stack
* size of the task being created. The same type is used to return information * size of the task being created. The same type is used to return information
* about stack usage in various other API calls. Defaults to size_t if left * about stack usage in various other API calls. Defaults to size_t if left
@ -174,6 +181,19 @@
* space if messages never go above a length that could be held in a uint8_t. */ * space if messages never go above a length that could be held in a uint8_t. */
#define configMESSAGE_BUFFER_LENGTH_TYPE size_t #define configMESSAGE_BUFFER_LENGTH_TYPE size_t
/* If configHEAP_CLEAR_MEMORY_ON_FREE is set to 1, then blocks of memory allocated
* using pvPortMalloc() will be cleared (i.e. set to zero) when freed using
* vPortFree(). Defaults to 0 if left undefined. */
#define configHEAP_CLEAR_MEMORY_ON_FREE 1
/* vTaskList and vTaskGetRunTimeStats APIs take a buffer as a parameter and assume
* that the length of the buffer is configSTATS_BUFFER_MAX_LENGTH. Defaults to
* 0xFFFF if left undefined.
* New applications are recommended to use vTaskListTasks and
* vTaskGetRunTimeStatistics APIs instead and supply the length of the buffer
* explicitly to avoid memory corruption. */
#define configSTATS_BUFFER_MAX_LENGTH 0xFFFF
/* Set configUSE_NEWLIB_REENTRANT to 1 to have a newlib reent structure /* Set configUSE_NEWLIB_REENTRANT to 1 to have a newlib reent structure
* allocated for each task. Set to 0 to not support newlib reent structures. * allocated for each task. Set to 0 to not support newlib reent structures.
* Default to 0 if left undefined. * Default to 0 if left undefined.
@ -194,7 +214,7 @@
* build. Set to 0 to exclude software timer functionality from the build. The * build. Set to 0 to exclude software timer functionality from the build. The
* FreeRTOS/source/timers.c source file must be included in the build if * FreeRTOS/source/timers.c source file must be included in the build if
* configUSE_TIMERS is set to 1. Default to 0 if left undefined. See * configUSE_TIMERS is set to 1. Default to 0 if left undefined. See
* https://www.freertos.org/RTOS-software-timer.html */ * https://www.freertos.org/RTOS-software-timer.html. */
#define configUSE_TIMERS 1 #define configUSE_TIMERS 1
/* configTIMER_TASK_PRIORITY sets the priority used by the timer task. Only /* configTIMER_TASK_PRIORITY sets the priority used by the timer task. Only
@ -224,20 +244,20 @@
* that create FreeRTOS objects (tasks, queues, etc.) using statically allocated * that create FreeRTOS objects (tasks, queues, etc.) using statically allocated
* memory in the build. Set to 0 to exclude the ability to create statically * memory in the build. Set to 0 to exclude the ability to create statically
* allocated objects from the build. Defaults to 0 if left undefined. See * allocated objects from the build. Defaults to 0 if left undefined. See
* https://www.freertos.org/Static_Vs_Dynamic_Memory_Allocation.html */ * https://www.freertos.org/Static_Vs_Dynamic_Memory_Allocation.html. */
#define configSUPPORT_STATIC_ALLOCATION 1 #define configSUPPORT_STATIC_ALLOCATION 1
/* Set configSUPPORT_DYNAMIC_ALLOCATION to 1 to include FreeRTOS API functions /* Set configSUPPORT_DYNAMIC_ALLOCATION to 1 to include FreeRTOS API functions
* that create FreeRTOS objects (tasks, queues, etc.) using dynamically allocated * that create FreeRTOS objects (tasks, queues, etc.) using dynamically allocated
* memory in the build. Set to 0 to exclude the ability to create dynamically * memory in the build. Set to 0 to exclude the ability to create dynamically
* allocated objects from the build. Defaults to 1 if left undefined. See * allocated objects from the build. Defaults to 1 if left undefined. See
* https://www.freertos.org/Static_Vs_Dynamic_Memory_Allocation.html */ * https://www.freertos.org/Static_Vs_Dynamic_Memory_Allocation.html. */
#define configSUPPORT_DYNAMIC_ALLOCATION 1 #define configSUPPORT_DYNAMIC_ALLOCATION 1
/* Sets the total size of the FreeRTOS heap, in bytes, when heap_1.c, heap_2.c /* Sets the total size of the FreeRTOS heap, in bytes, when heap_1.c, heap_2.c
* or heap_4.c are included in the build. This value is defaulted to 4096 bytes but * or heap_4.c are included in the build. This value is defaulted to 4096 bytes but
* it must be tailored to each application. Note the heap will appear in the .bss * it must be tailored to each application. Note the heap will appear in the .bss
* section. See https://www.freertos.org/a00111.html */ * section. See https://www.freertos.org/a00111.html. */
#define configTOTAL_HEAP_SIZE 4096 #define configTOTAL_HEAP_SIZE 4096
/* Set configAPPLICATION_ALLOCATED_HEAP to 1 to have the application allocate /* Set configAPPLICATION_ALLOCATED_HEAP to 1 to have the application allocate
@ -253,6 +273,11 @@
* Defaults to 0 if left undefined. */ * Defaults to 0 if left undefined. */
#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 #define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
/* Set configENABLE_HEAP_PROTECTOR to 1 to enable bounds checking and obfuscation
* to internal heap block pointers in heap_4.c and heap_5.c to help catch pointer
* corruptions. Defaults to 0 if left undefined. */
#define configENABLE_HEAP_PROTECTOR 0
/******************************************************************************/ /******************************************************************************/
/* Interrupt nesting behaviour configuration. *********************************/ /* Interrupt nesting behaviour configuration. *********************************/
/******************************************************************************/ /******************************************************************************/
@ -283,12 +308,20 @@
/* Set the following configUSE_* constants to 1 to include the named hook /* Set the following configUSE_* constants to 1 to include the named hook
* functionality in the build. Set to 0 to exclude the hook functionality from the * functionality in the build. Set to 0 to exclude the hook functionality from the
* build. The application writer is responsible for providing the hook function * build. The application writer is responsible for providing the hook function
* for any set to 1. See https://www.freertos.org/a00016.html */ * for any set to 1. See https://www.freertos.org/a00016.html. */
#define configUSE_IDLE_HOOK 0 #define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0 #define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0 #define configUSE_MALLOC_FAILED_HOOK 0
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0 #define configUSE_DAEMON_TASK_STARTUP_HOOK 0
/* Set configUSE_SB_COMPLETED_CALLBACK to 1 to have send and receive completed
* callbacks for each instance of a stream buffer or message buffer. When the
* option is set to 1, APIs xStreamBufferCreateWithCallback() and
* xStreamBufferCreateStaticWithCallback() (and likewise APIs for message
* buffer) can be used to create a stream buffer or message buffer instance
* with application provided callbacks. Defaults to 0 if left undefined. */
#define configUSE_SB_COMPLETED_CALLBACK 0
/* Set configCHECK_FOR_STACK_OVERFLOW to 1 or 2 for FreeRTOS to check for a /* Set configCHECK_FOR_STACK_OVERFLOW to 1 or 2 for FreeRTOS to check for a
* stack overflow at the time of a context switch. Set to 0 to not look for a * stack overflow at the time of a context switch. Set to 0 to not look for a
* stack overflow. If configCHECK_FOR_STACK_OVERFLOW is 1 then the check only * stack overflow. If configCHECK_FOR_STACK_OVERFLOW is 1 then the check only
@ -307,9 +340,9 @@
/******************************************************************************/ /******************************************************************************/
/* Set configGENERATE_RUN_TIME_STATS to 1 to have FreeRTOS collect data on the /* Set configGENERATE_RUN_TIME_STATS to 1 to have FreeRTOS collect data on the
* processing time used by each task. Set to 0 to not collect the data. The * processing time used by each task. Set to 0 to not collect the data. The
* application writer needs to provide a clock source if set to 1. Defaults to 0 * application writer needs to provide a clock source if set to 1. Defaults to 0
* if left undefined. See https://www.freertos.org/rtos-run-time-stats.html */ * if left undefined. See https://www.freertos.org/rtos-run-time-stats.html. */
#define configGENERATE_RUN_TIME_STATS 0 #define configGENERATE_RUN_TIME_STATS 0
/* Set configUSE_TRACE_FACILITY to include additional task structure members /* Set configUSE_TRACE_FACILITY to include additional task structure members
@ -325,6 +358,21 @@
* undefined. */ * undefined. */
#define configUSE_STATS_FORMATTING_FUNCTIONS 0 #define configUSE_STATS_FORMATTING_FUNCTIONS 0
/******************************************************************************/
/* Co-routine related definitions. ********************************************/
/******************************************************************************/
/* Set configUSE_CO_ROUTINES to 1 to include co-routine functionality in the
* build, or 0 to omit co-routine functionality from the build. To include
* co-routines, croutine.c must be included in the project. Defaults to 0 if left
* undefined. */
#define configUSE_CO_ROUTINES 0
/* configMAX_CO_ROUTINE_PRIORITIES defines the number of priorities available
* to the application co-routines. Any number of co-routines can share the same
* priority. Defaults to 0 if left undefined. */
#define configMAX_CO_ROUTINE_PRIORITIES 1
/******************************************************************************/ /******************************************************************************/
/* Debugging assistance. ******************************************************/ /* Debugging assistance. ******************************************************/
/******************************************************************************/ /******************************************************************************/
@ -346,7 +394,7 @@
} }
/******************************************************************************/ /******************************************************************************/
/* Cortex-M MPU specific definitions. *****************************************/ /* FreeRTOS MPU specific definitions. *****************************************/
/******************************************************************************/ /******************************************************************************/
/* If configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS is set to 1 then /* If configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS is set to 1 then
@ -380,16 +428,93 @@
* escalations originating from outside of the kernel code itself. Set to 1 to * escalations originating from outside of the kernel code itself. Set to 1 to
* allow application tasks to raise privilege. Defaults to 1 if left undefined. * allow application tasks to raise privilege. Defaults to 1 if left undefined.
* Only used by the FreeRTOS Cortex-M MPU ports, not the standard ARMv7-M Cortex-M * Only used by the FreeRTOS Cortex-M MPU ports, not the standard ARMv7-M Cortex-M
* port.*/ * port. */
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 1 #define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 1
/* Set configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS to 1 to allow unprivileged /* Set configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS to 1 to allow unprivileged
* tasks enter critical sections (effectively mask interrupts). Set to 0 to * tasks enter critical sections (effectively mask interrupts). Set to 0 to
* prevent unprivileged tasks entering critical sections. Defaults to 1 if left * prevent unprivileged tasks entering critical sections. Defaults to 1 if left
* undefined. Only used by the FreeRTOS Cortex-M MPU ports, not the standard * undefined. Only used by the FreeRTOS Cortex-M MPU ports, not the standard
* ARMv7-M Cortex-M port.*/ * ARMv7-M Cortex-M port. */
#define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 0 #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 0
/* FreeRTOS Kernel version 10.6.0 introduced a new v2 MPU wrapper, namely
* mpu_wrappers_v2.c. Set configUSE_MPU_WRAPPERS_V1 to 0 to use the new v2 MPU
* wrapper. Set configUSE_MPU_WRAPPERS_V1 to 1 to use the old v1 MPU wrapper
* (mpu_wrappers.c). Defaults to 0 if left undefined. */
#define configUSE_MPU_WRAPPERS_V1 0
/* When using the v2 MPU wrapper, set configPROTECTED_KERNEL_OBJECT_POOL_SIZE to
* the total number of kernel objects, which includes tasks, queues, semaphores,
* mutexes, event groups, timers, stream buffers and message buffers, in your
* application. The application will not be able to have more than
* configPROTECTED_KERNEL_OBJECT_POOL_SIZE kernel objects at any point of
* time. */
#define configPROTECTED_KERNEL_OBJECT_POOL_SIZE 10
/* When using the v2 MPU wrapper, set configSYSTEM_CALL_STACK_SIZE to the size
* of the system call stack in words. Each task has a statically allocated
* memory buffer of this size which is used as the stack to execute system
* calls. For example, if configSYSTEM_CALL_STACK_SIZE is defined as 128 and
* there are 10 tasks in the application, the total amount of memory used for
* system call stacks is 128 * 10 = 1280 words. */
#define configSYSTEM_CALL_STACK_SIZE 128
/* When using the v2 MPU wrapper, set configENABLE_ACCESS_CONTROL_LIST to 1 to
* enable Access Control List (ACL) feature. When ACL is enabled, an
* unprivileged task by default does not have access to any kernel object other
* than itself. The application writer needs to explicitly grant the
* unprivileged task access to the kernel objects it needs using the APIs
* provided for the same. Defaults to 0 if left undefined. */
#define configENABLE_ACCESS_CONTROL_LIST 1
/******************************************************************************/
/* SMP( Symmetric MultiProcessing ) Specific Configuration definitions. *******/
/******************************************************************************/
/* Set configNUMBER_OF_CORES to the number of available processor cores. Defaults
* to 1 if left undefined. */
/*
#define configNUMBER_OF_CORES [Num of available cores]
*/
/* When using SMP (i.e. configNUMBER_OF_CORES is greater than one), set
* configRUN_MULTIPLE_PRIORITIES to 0 to allow multiple tasks to run
* simultaneously only if they do not have equal priority, thereby maintaining
* the paradigm of a lower priority task never running if a higher priority task
* is able to run. If configRUN_MULTIPLE_PRIORITIES is set to 1, multiple tasks
* with different priorities may run simultaneously - so a higher and lower
* priority task may run on different cores at the same time. */
#define configRUN_MULTIPLE_PRIORITIES 0
/* When using SMP (i.e. configNUMBER_OF_CORES is greater than one), set
* configUSE_CORE_AFFINITY to 1 to enable core affinity feature. When core
* affinity feature is enabled, the vTaskCoreAffinitySet and vTaskCoreAffinityGet
* APIs can be used to set and retrieve which cores a task can run on. If
* configUSE_CORE_AFFINITY is set to 0 then the FreeRTOS scheduler is free to
* run any task on any available core. */
#define configUSE_CORE_AFFINITY 0
/* When using SMP (i.e. configNUMBER_OF_CORES is greater than one), if
* configUSE_TASK_PREEMPTION_DISABLE is set to 1, individual tasks can be set to
* either pre-emptive or co-operative mode using the vTaskPreemptionDisable and
* vTaskPreemptionEnable APIs. */
#define configUSE_TASK_PREEMPTION_DISABLE 0
/* When using SMP (i.e. configNUMBER_OF_CORES is greater than one), set
* configUSE_PASSIVE_IDLE_HOOK to 1 to allow the application writer to use
* the passive idle task hook to add background functionality without the overhead
* of a separate task. Defaults to 0 if left undefined. */
#define configUSE_PASSIVE_IDLE_HOOK 0
/* When using SMP (i.e. configNUMBER_OF_CORES is greater than one),
* configTIMER_SERVICE_TASK_CORE_AFFINITY allows the application writer to set
* the core affinity of the RTOS Daemon/Timer Service task. Defaults to
* tskNO_AFFINITY if left undefined. */
#define configTIMER_SERVICE_TASK_CORE_AFFINITY tskNO_AFFINITY
/******************************************************************************/ /******************************************************************************/
/* ARMv8-M secure side port related definitions. ******************************/ /* ARMv8-M secure side port related definitions. ******************************/
/******************************************************************************/ /******************************************************************************/
@ -440,4 +565,4 @@
#define INCLUDE_xTaskGetHandle 0 #define INCLUDE_xTaskGetHandle 0
#define INCLUDE_xTaskResumeFromISR 1 #define INCLUDE_xTaskResumeFromISR 1
#endif /* __FREERTOS_CONFIG_H__ */ #endif /* FREERTOS_CONFIG_H */

View file

@ -365,6 +365,17 @@
#define configPRECONDITION_DEFINED 1 #define configPRECONDITION_DEFINED 1
#endif #endif
#ifndef configCHECK_HANDLER_INSTALLATION
#define configCHECK_HANDLER_INSTALLATION 1
#else
/* The application has explicitly defined configCHECK_HANDLER_INSTALLATION
* to 1. The checks requires configASSERT() to be defined. */
#if ( ( configCHECK_HANDLER_INSTALLATION == 1 ) && ( configASSERT_DEFINED == 0 ) )
#error You must define configASSERT() when configCHECK_HANDLER_INSTALLATION is 1.
#endif
#endif
#ifndef portMEMORY_BARRIER #ifndef portMEMORY_BARRIER
#define portMEMORY_BARRIER() #define portMEMORY_BARRIER()
#endif #endif
@ -498,12 +509,36 @@
#endif /* configUSE_TIMERS */ #endif /* configUSE_TIMERS */
#ifndef portHAS_NESTED_INTERRUPTS
#if defined( portSET_INTERRUPT_MASK_FROM_ISR ) && defined( portCLEAR_INTERRUPT_MASK_FROM_ISR )
#define portHAS_NESTED_INTERRUPTS 1
#else
#define portHAS_NESTED_INTERRUPTS 0
#endif
#endif
#ifndef portSET_INTERRUPT_MASK_FROM_ISR #ifndef portSET_INTERRUPT_MASK_FROM_ISR
#if ( portHAS_NESTED_INTERRUPTS == 1 )
#error portSET_INTERRUPT_MASK_FROM_ISR must be defined for ports that support nested interrupts (i.e. portHAS_NESTED_INTERRUPTS is set to 1)
#else
#define portSET_INTERRUPT_MASK_FROM_ISR() 0 #define portSET_INTERRUPT_MASK_FROM_ISR() 0
#endif
#else
#if ( portHAS_NESTED_INTERRUPTS == 0 )
#error portSET_INTERRUPT_MASK_FROM_ISR must not be defined for ports that do not support nested interrupts (i.e. portHAS_NESTED_INTERRUPTS is set to 0)
#endif
#endif #endif
#ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR #ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR
#if ( portHAS_NESTED_INTERRUPTS == 1 )
#error portCLEAR_INTERRUPT_MASK_FROM_ISR must be defined for ports that support nested interrupts (i.e. portHAS_NESTED_INTERRUPTS is set to 1)
#else
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) ( uxSavedStatusValue ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) ( uxSavedStatusValue )
#endif
#else
#if ( portHAS_NESTED_INTERRUPTS == 0 )
#error portCLEAR_INTERRUPT_MASK_FROM_ISR must not be defined for ports that do not support nested interrupts (i.e. portHAS_NESTED_INTERRUPTS is set to 0)
#endif
#endif #endif
#ifndef portCLEAN_UP_TCB #ifndef portCLEAN_UP_TCB
@ -518,6 +553,10 @@
#define portSETUP_TCB( pxTCB ) ( void ) ( pxTCB ) #define portSETUP_TCB( pxTCB ) ( void ) ( pxTCB )
#endif #endif
#ifndef portTASK_SWITCH_HOOK
#define portTASK_SWITCH_HOOK( pxTCB ) ( void ) ( pxTCB )
#endif
#ifndef configQUEUE_REGISTRY_SIZE #ifndef configQUEUE_REGISTRY_SIZE
#define configQUEUE_REGISTRY_SIZE 0U #define configQUEUE_REGISTRY_SIZE 0U
#endif #endif
@ -1886,14 +1925,20 @@
#ifndef traceENTER_xTaskGetIdleTaskHandle #ifndef traceENTER_xTaskGetIdleTaskHandle
#define traceENTER_xTaskGetIdleTaskHandle() #define traceENTER_xTaskGetIdleTaskHandle()
#endif #endif
#else #endif
#ifndef traceENTER_xTaskGetIdleTaskHandle
#define traceENTER_xTaskGetIdleTaskHandle( xCoreID ) #if ( configNUMBER_OF_CORES == 1 )
#ifndef traceRETURN_xTaskGetIdleTaskHandle
#define traceRETURN_xTaskGetIdleTaskHandle( xIdleTaskHandle )
#endif #endif
#endif #endif
#ifndef traceRETURN_xTaskGetIdleTaskHandle #ifndef traceENTER_xTaskGetIdleTaskHandleForCore
#define traceRETURN_xTaskGetIdleTaskHandle( xIdleTaskHandle ) #define traceENTER_xTaskGetIdleTaskHandleForCore( xCoreID )
#endif
#ifndef traceRETURN_xTaskGetIdleTaskHandleForCore
#define traceRETURN_xTaskGetIdleTaskHandleForCore( xIdleTaskHandle )
#endif #endif
#ifndef traceENTER_vTaskStepTick #ifndef traceENTER_vTaskStepTick
@ -2464,6 +2509,22 @@
#define traceRETURN_xStreamBufferReceiveCompletedFromISR( xReturn ) #define traceRETURN_xStreamBufferReceiveCompletedFromISR( xReturn )
#endif #endif
#ifndef traceENTER_uxStreamBufferGetStreamBufferNotificationIndex
#define traceENTER_uxStreamBufferGetStreamBufferNotificationIndex( xStreamBuffer )
#endif
#ifndef traceRETURN_uxStreamBufferGetStreamBufferNotificationIndex
#define traceRETURN_uxStreamBufferGetStreamBufferNotificationIndex( uxNotificationIndex )
#endif
#ifndef traceENTER_vStreamBufferSetStreamBufferNotificationIndex
#define traceENTER_vStreamBufferSetStreamBufferNotificationIndex( xStreamBuffer, uxNotificationIndex )
#endif
#ifndef traceRETURN_vStreamBufferSetStreamBufferNotificationIndex
#define traceRETURN_vStreamBufferSetStreamBufferNotificationIndex()
#endif
#ifndef traceENTER_uxStreamBufferGetStreamBufferNumber #ifndef traceENTER_uxStreamBufferGetStreamBufferNumber
#define traceENTER_uxStreamBufferGetStreamBufferNumber( xStreamBuffer ) #define traceENTER_uxStreamBufferGetStreamBufferNumber( xStreamBuffer )
#endif #endif
@ -3226,6 +3287,7 @@ typedef struct xSTATIC_STREAM_BUFFER
#if ( configUSE_SB_COMPLETED_CALLBACK == 1 ) #if ( configUSE_SB_COMPLETED_CALLBACK == 1 )
void * pvDummy5[ 2 ]; void * pvDummy5[ 2 ];
#endif #endif
UBaseType_t uxDummy6;
} StaticStreamBuffer_t; } StaticStreamBuffer_t;
/* Message buffers are built on stream buffers. */ /* Message buffers are built on stream buffers. */

View file

@ -33,6 +33,14 @@
* This file implements atomic functions by disabling interrupts globally. * This file implements atomic functions by disabling interrupts globally.
* Implementations with architecture specific atomic instructions can be * Implementations with architecture specific atomic instructions can be
* provided under each compiler directory. * provided under each compiler directory.
*
* The atomic interface can be used in FreeRTOS tasks on all FreeRTOS ports. It
* can also be used in Interrupt Service Routines (ISRs) on FreeRTOS ports that
* support nested interrupts (i.e. portHAS_NESTED_INTERRUPTS is set to 1). The
* atomic interface must not be used in ISRs on FreeRTOS ports that do not
* support nested interrupts (i.e. portHAS_NESTED_INTERRUPTS is set to 0)
* because ISRs on these ports cannot be interrupted and therefore, do not need
* atomics in ISRs.
*/ */
#ifndef ATOMIC_H #ifndef ATOMIC_H
@ -59,7 +67,7 @@
* ATOMIC_ENTER_CRITICAL(). * ATOMIC_ENTER_CRITICAL().
* *
*/ */
#if defined( portSET_INTERRUPT_MASK_FROM_ISR ) #if ( portHAS_NESTED_INTERRUPTS == 1 )
/* Nested interrupt scheme is supported in this port. */ /* Nested interrupt scheme is supported in this port. */
#define ATOMIC_ENTER_CRITICAL() \ #define ATOMIC_ENTER_CRITICAL() \

View file

@ -47,8 +47,8 @@
typedef void * CoRoutineHandle_t; typedef void * CoRoutineHandle_t;
/* Defines the prototype to which co-routine functions must conform. */ /* Defines the prototype to which co-routine functions must conform. */
typedef void (* crCOROUTINE_CODE)( CoRoutineHandle_t, typedef void (* crCOROUTINE_CODE)( CoRoutineHandle_t xHandle,
UBaseType_t ); UBaseType_t uxIndex );
typedef struct corCoRoutineControlBlock typedef struct corCoRoutineControlBlock
{ {

View file

@ -807,9 +807,9 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
/* For internal use only. */ /* For internal use only. */
void vEventGroupSetBitsCallback( void * pvEventGroup, void vEventGroupSetBitsCallback( void * pvEventGroup,
const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION; uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION;
void vEventGroupClearBitsCallback( void * pvEventGroup, void vEventGroupClearBitsCallback( void * pvEventGroup,
const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION; uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION;
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )

View file

@ -151,7 +151,7 @@ struct xLIST_ITEM
struct xLIST * configLIST_VOLATILE pxContainer; /**< Pointer to the list in which this list item is placed (if any). */ struct xLIST * configLIST_VOLATILE pxContainer; /**< Pointer to the list in which this list item is placed (if any). */
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
}; };
typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */ typedef struct xLIST_ITEM ListItem_t;
#if ( configUSE_MINI_LIST_ITEM == 1 ) #if ( configUSE_MINI_LIST_ITEM == 1 )
struct xMINI_LIST_ITEM struct xMINI_LIST_ITEM

View file

@ -229,14 +229,6 @@
#define xStreamBufferReceiveCompletedFromISR MPU_xStreamBufferReceiveCompletedFromISR #define xStreamBufferReceiveCompletedFromISR MPU_xStreamBufferReceiveCompletedFromISR
#endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */ #endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
/* Remove the privileged function macro, but keep the PRIVILEGED_DATA
* macro so applications can place data in privileged access sections
* (useful when using statically allocated objects). */
#define PRIVILEGED_FUNCTION
#define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) )
#define FREERTOS_SYSTEM_CALL
#if ( ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) ) #if ( ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
#define vGrantAccessToTask( xTask, xTaskToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xTaskToGrantAccess ) ) #define vGrantAccessToTask( xTask, xTaskToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xTaskToGrantAccess ) )
@ -265,15 +257,12 @@
#endif /* #if ( ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) ) */ #endif /* #if ( ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) ) */
#else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ #endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
/* Ensure API functions go in the privileged execution section. */
#define PRIVILEGED_FUNCTION __attribute__( ( section( "privileged_functions" ) ) ) #define PRIVILEGED_FUNCTION __attribute__( ( section( "privileged_functions" ) ) )
#define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) ) #define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) )
#define FREERTOS_SYSTEM_CALL __attribute__( ( section( "freertos_system_calls" ) ) ) #define FREERTOS_SYSTEM_CALL __attribute__( ( section( "freertos_system_calls" ) ) )
#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
#else /* portUSING_MPU_WRAPPERS */ #else /* portUSING_MPU_WRAPPERS */
#define PRIVILEGED_FUNCTION #define PRIVILEGED_FUNCTION

View file

@ -200,7 +200,7 @@ size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
* *
* This hook function is called when allocation failed. * This hook function is called when allocation failed.
*/ */
void vApplicationMallocFailedHook( void ); /*lint !e526 Symbol not defined as it is an application callback. */ void vApplicationMallocFailedHook( void );
#endif #endif
/* /*

View file

@ -33,7 +33,7 @@
* Defines the prototype to which task functions must conform. Defined in this * Defines the prototype to which task functions must conform. Defined in this
* file to ensure the type is known before portable.h is included. * file to ensure the type is known before portable.h is included.
*/ */
typedef void (* TaskFunction_t)( void * ); typedef void (* TaskFunction_t)( void * arg );
/* Converts a time in milliseconds to a time in ticks. This macro can be /* Converts a time in milliseconds to a time in ticks. This macro can be
* overridden by a macro of the same name defined in FreeRTOSConfig.h in case the * overridden by a macro of the same name defined in FreeRTOSConfig.h in case the

View file

@ -1187,7 +1187,10 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
* // has a priority higher than or equal to the priority of the currently * // has a priority higher than or equal to the priority of the currently
* // executing task (the task this interrupt interrupted). Perform a context * // executing task (the task this interrupt interrupted). Perform a context
* // switch so this interrupt returns directly to the unblocked task. * // switch so this interrupt returns directly to the unblocked task.
* portYIELD_FROM_ISR(); // or portEND_SWITCHING_ISR() depending on the port. * // The macro used is port specific and will be either
* // portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - refer to the documentation
* // page for the port being used.
* portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
* } * }
* } * }
* @endcode * @endcode
@ -1260,8 +1263,11 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
* // Now the buffer is empty we can switch context if necessary. * // Now the buffer is empty we can switch context if necessary.
* if( xHigherPriorityTaskWoken ) * if( xHigherPriorityTaskWoken )
* { * {
* // Actual macro used here is port specific. * // As xHigherPriorityTaskWoken is now set to pdTRUE then a context
* portYIELD_FROM_ISR (); * // switch should be requested. The macro used is port specific and
* // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
* // refer to the documentation page for the port being used.
* portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
* } * }
* } * }
* @endcode * @endcode
@ -1337,11 +1343,14 @@ void vQueueDelete( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
* *
* } while( portINPUT_BYTE( BUFFER_COUNT ) ); * } while( portINPUT_BYTE( BUFFER_COUNT ) );
* *
* // Now the buffer is empty we can switch context if necessary. Note that the * // Now the buffer is empty we can switch context if necessary.
* // name of the yield function required is port specific.
* if( xHigherPriorityTaskWokenByPost ) * if( xHigherPriorityTaskWokenByPost )
* { * {
* portYIELD_FROM_ISR(); * // As xHigherPriorityTaskWokenByPost is now set to pdTRUE then a context
* // switch should be requested. The macro used is port specific and
* // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
* // refer to the documentation page for the port being used.
* portYIELD_FROM_ISR( xHigherPriorityTaskWokenByPost );
* } * }
* } * }
* @endcode * @endcode
@ -1455,6 +1464,8 @@ BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FU
BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
#if ( configUSE_CO_ROUTINES == 1 )
/* /*
* The functions defined above are for passing data to and from tasks. The * The functions defined above are for passing data to and from tasks. The
* functions below are the equivalents for passing data to and from * functions below are the equivalents for passing data to and from
@ -1464,40 +1475,55 @@ UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) PRIVILEG
* should not be called directly from application code. Instead use the macro * should not be called directly from application code. Instead use the macro
* wrappers defined within croutine.h. * wrappers defined within croutine.h.
*/ */
BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue,
const void * pvItemToQueue, const void * pvItemToQueue,
BaseType_t xCoRoutinePreviouslyWoken ); BaseType_t xCoRoutinePreviouslyWoken );
BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue,
void * pvBuffer, void * pvBuffer,
BaseType_t * pxTaskWoken ); BaseType_t * pxTaskWoken );
BaseType_t xQueueCRSend( QueueHandle_t xQueue, BaseType_t xQueueCRSend( QueueHandle_t xQueue,
const void * pvItemToQueue, const void * pvItemToQueue,
TickType_t xTicksToWait ); TickType_t xTicksToWait );
BaseType_t xQueueCRReceive( QueueHandle_t xQueue, BaseType_t xQueueCRReceive( QueueHandle_t xQueue,
void * pvBuffer, void * pvBuffer,
TickType_t xTicksToWait ); TickType_t xTicksToWait );
#endif /* if ( configUSE_CO_ROUTINES == 1 ) */
/* /*
* For internal use only. Use xSemaphoreCreateMutex(), * For internal use only. Use xSemaphoreCreateMutex(),
* xSemaphoreCreateCounting() or xSemaphoreGetMutexHolder() instead of calling * xSemaphoreCreateCounting() or xSemaphoreGetMutexHolder() instead of calling
* these functions directly. * these functions directly.
*/ */
QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION; QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType,
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType,
StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION; StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION;
QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, #endif
#if ( configUSE_COUNTING_SEMAPHORES == 1 )
QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount,
const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION; const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION;
QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, #endif
#if ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount,
const UBaseType_t uxInitialCount, const UBaseType_t uxInitialCount,
StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION; StaticQueue_t * pxStaticQueue ) PRIVILEGED_FUNCTION;
#endif
BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue,
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
TaskHandle_t xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION;
TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION; #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
TaskHandle_t xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION;
TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION;
#endif
/* /*
* For internal use only. Use xSemaphoreTakeMutexRecursive() or * For internal use only. Use xSemaphoreTakeRecursive() or
* xSemaphoreGiveMutexRecursive() instead of calling these functions directly. * xSemaphoreGiveRecursive() instead of calling these functions directly.
*/ */
BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex,
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
@ -1537,7 +1563,7 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION;
*/ */
#if ( configQUEUE_REGISTRY_SIZE > 0 ) #if ( configQUEUE_REGISTRY_SIZE > 0 )
void vQueueAddToRegistry( QueueHandle_t xQueue, void vQueueAddToRegistry( QueueHandle_t xQueue,
const char * pcQueueName ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ const char * pcQueueName ) PRIVILEGED_FUNCTION;
#endif #endif
/* /*
@ -1566,7 +1592,7 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION;
* returned. * returned.
*/ */
#if ( configQUEUE_REGISTRY_SIZE > 0 ) #if ( configQUEUE_REGISTRY_SIZE > 0 )
const char * pcQueueGetName( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ const char * pcQueueGetName( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
#endif #endif
/* /*
@ -1653,7 +1679,9 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) PRIVILEGED_FUNCTION;
* @return If the queue set is created successfully then a handle to the created * @return If the queue set is created successfully then a handle to the created
* queue set is returned. Otherwise NULL is returned. * queue set is returned. Otherwise NULL is returned.
*/ */
QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) PRIVILEGED_FUNCTION; #if ( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) PRIVILEGED_FUNCTION;
#endif
/* /*
* Adds a queue or semaphore to a queue set that was previously created by a * Adds a queue or semaphore to a queue set that was previously created by a
@ -1677,8 +1705,10 @@ QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) PRIVILE
* queue set because it is already a member of a different queue set then pdFAIL * queue set because it is already a member of a different queue set then pdFAIL
* is returned. * is returned.
*/ */
BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, #if ( configUSE_QUEUE_SETS == 1 )
BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
#endif
/* /*
* Removes a queue or semaphore from a queue set. A queue or semaphore can only * Removes a queue or semaphore from a queue set. A queue or semaphore can only
@ -1697,8 +1727,10 @@ BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
* then pdPASS is returned. If the queue was not in the queue set, or the * then pdPASS is returned. If the queue was not in the queue set, or the
* queue (or semaphore) was not empty, then pdFAIL is returned. * queue (or semaphore) was not empty, then pdFAIL is returned.
*/ */
BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, #if ( configUSE_QUEUE_SETS == 1 )
BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore,
QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
#endif
/* /*
* xQueueSelectFromSet() selects from the members of a queue set a queue or * xQueueSelectFromSet() selects from the members of a queue set a queue or
@ -1734,13 +1766,17 @@ BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore,
* in the queue set that is available, or NULL if no such queue or semaphore * in the queue set that is available, or NULL if no such queue or semaphore
* exists before before the specified block time expires. * exists before before the specified block time expires.
*/ */
QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, #if ( configUSE_QUEUE_SETS == 1 )
QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet,
const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
#endif
/* /*
* A version of xQueueSelectFromSet() that can be used from an ISR. * A version of xQueueSelectFromSet() that can be used from an ISR.
*/ */
QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION; #if ( configUSE_QUEUE_SETS == 1 )
QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
#endif
/* Not public API functions. */ /* Not public API functions. */
void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, void vQueueWaitForMessageRestricted( QueueHandle_t xQueue,
@ -1748,10 +1784,20 @@ void vQueueWaitForMessageRestricted( QueueHandle_t xQueue,
const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION; const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION;
BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xQueueGenericReset( QueueHandle_t xQueue,
BaseType_t xNewQueue ) PRIVILEGED_FUNCTION; BaseType_t xNewQueue ) PRIVILEGED_FUNCTION;
void vQueueSetQueueNumber( QueueHandle_t xQueue,
#if ( configUSE_TRACE_FACILITY == 1 )
void vQueueSetQueueNumber( QueueHandle_t xQueue,
UBaseType_t uxQueueNumber ) PRIVILEGED_FUNCTION; UBaseType_t uxQueueNumber ) PRIVILEGED_FUNCTION;
UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; #endif
uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
#endif
#if ( configUSE_TRACE_FACILITY == 1 )
uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
#endif
UBaseType_t uxQueueGetQueueItemSize( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; UBaseType_t uxQueueGetQueueItemSize( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
UBaseType_t uxQueueGetQueueLength( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION; UBaseType_t uxQueueGetQueueLength( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;

View file

@ -61,7 +61,8 @@
/* Is the currently saved stack pointer within the stack limit? */ \ /* Is the currently saved stack pointer within the stack limit? */ \
if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) \ if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) \
{ \ { \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \
} \ } \
} while( 0 ) } while( 0 )
@ -77,7 +78,8 @@
/* Is the currently saved stack pointer within the stack limit? */ \ /* Is the currently saved stack pointer within the stack limit? */ \
if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) \ if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) \
{ \ { \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \
} \ } \
} while( 0 ) } while( 0 )
@ -89,14 +91,15 @@
#define taskCHECK_FOR_STACK_OVERFLOW() \ #define taskCHECK_FOR_STACK_OVERFLOW() \
do { \ do { \
const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \ const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \
const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5; \ const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5U; \
\ \
if( ( pulStack[ 0 ] != ulCheckValue ) || \ if( ( pulStack[ 0 ] != ulCheckValue ) || \
( pulStack[ 1 ] != ulCheckValue ) || \ ( pulStack[ 1 ] != ulCheckValue ) || \
( pulStack[ 2 ] != ulCheckValue ) || \ ( pulStack[ 2 ] != ulCheckValue ) || \
( pulStack[ 3 ] != ulCheckValue ) ) \ ( pulStack[ 3 ] != ulCheckValue ) ) \
{ \ { \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \
} \ } \
} while( 0 ) } while( 0 )
@ -120,7 +123,8 @@
/* Has the extremity of the task stack ever been written over? */ \ /* Has the extremity of the task stack ever been written over? */ \
if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \
{ \ { \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \ char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \
} \ } \
} while( 0 ) } while( 0 )

View file

@ -911,6 +911,57 @@ BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer
BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer,
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
/**
* stream_buffer.h
*
* @code{c}
* UBaseType_t uxStreamBufferGetStreamBufferNotificationIndex( StreamBufferHandle_t xStreamBuffer );
* @endcode
*
* Get the task notification index used for the supplied stream buffer which can
* be set using vStreamBufferSetStreamBufferNotificationIndex. If the task
* notification index for the stream buffer is not changed using
* vStreamBufferSetStreamBufferNotificationIndex, this function returns the
* default value (tskDEFAULT_INDEX_TO_NOTIFY).
*
* @param xStreamBuffer The handle of the stream buffer for which the task
* notification index is retrieved.
*
* @return The task notification index for the stream buffer.
*
* \defgroup uxStreamBufferGetStreamBufferNotificationIndex uxStreamBufferGetStreamBufferNotificationIndex
* \ingroup StreamBufferManagement
*/
UBaseType_t uxStreamBufferGetStreamBufferNotificationIndex( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;
/**
* stream_buffer.h
*
* @code{c}
* void vStreamBufferSetStreamBufferNotificationIndex ( StreamBuffer_t xStreamBuffer, UBaseType_t uxNotificationIndex );
* @endcode
*
* Set the task notification index used for the supplied stream buffer.
* Successive calls to stream buffer APIs (like xStreamBufferSend or
* xStreamBufferReceive) for this stream buffer will use this new index for
* their task notifications.
*
* If this function is not called, the default index (tskDEFAULT_INDEX_TO_NOTIFY)
* is used for task notifications. It is recommended to call this function
* before attempting to send or receive data from the stream buffer to avoid
* inconsistencies.
*
* @param xStreamBuffer The handle of the stream buffer for which the task
* notification index is set.
*
* @param uxNotificationIndex The task notification index to set.
*
* \defgroup vStreamBufferSetStreamBufferNotificationIndex vStreamBufferSetStreamBufferNotificationIndex
* \ingroup StreamBufferManagement
*/
void vStreamBufferSetStreamBufferNotificationIndex( StreamBufferHandle_t xStreamBuffer,
UBaseType_t uxNotificationIndex ) PRIVILEGED_FUNCTION;
/* Functions below here are not part of the public API. */ /* Functions below here are not part of the public API. */
StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes, StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes, size_t xTriggerLevelBytes,
@ -919,14 +970,15 @@ StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes,
StreamBufferCallbackFunction_t pxSendCompletedCallback, StreamBufferCallbackFunction_t pxSendCompletedCallback,
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION; StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION;
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes, StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes,
size_t xTriggerLevelBytes, size_t xTriggerLevelBytes,
BaseType_t xIsMessageBuffer, BaseType_t xIsMessageBuffer,
uint8_t * const pucStreamBufferStorageArea, uint8_t * const pucStreamBufferStorageArea,
StaticStreamBuffer_t * const pxStaticStreamBuffer, StaticStreamBuffer_t * const pxStaticStreamBuffer,
StreamBufferCallbackFunction_t pxSendCompletedCallback, StreamBufferCallbackFunction_t pxSendCompletedCallback,
StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION; StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) PRIVILEGED_FUNCTION;
#endif
size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION;

View file

@ -96,7 +96,7 @@ typedef const struct tskTaskControlBlock * ConstTaskHandle_t;
* Defines the prototype to which the application task hook function must * Defines the prototype to which the application task hook function must
* conform. * conform.
*/ */
typedef BaseType_t (* TaskHookFunction_t)( void * ); typedef BaseType_t (* TaskHookFunction_t)( void * arg );
/* Task states returned by eTaskGetState. */ /* Task states returned by eTaskGetState. */
typedef enum typedef enum
@ -144,7 +144,7 @@ typedef struct xMEMORY_REGION
typedef struct xTASK_PARAMETERS typedef struct xTASK_PARAMETERS
{ {
TaskFunction_t pvTaskCode; TaskFunction_t pvTaskCode;
const char * pcName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ const char * pcName;
configSTACK_DEPTH_TYPE usStackDepth; configSTACK_DEPTH_TYPE usStackDepth;
void * pvParameters; void * pvParameters;
UBaseType_t uxPriority; UBaseType_t uxPriority;
@ -160,7 +160,7 @@ typedef struct xTASK_PARAMETERS
typedef struct xTASK_STATUS typedef struct xTASK_STATUS
{ {
TaskHandle_t xHandle; /* The handle of the task to which the rest of the information in the structure relates. */ TaskHandle_t xHandle; /* The handle of the task to which the rest of the information in the structure relates. */
const char * pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ const char * pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */
UBaseType_t xTaskNumber; /* A number unique to the task. */ UBaseType_t xTaskNumber; /* A number unique to the task. */
eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */ eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */
UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */ UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */
@ -379,7 +379,7 @@ typedef enum
*/ */
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ const char * const pcName,
const configSTACK_DEPTH_TYPE usStackDepth, const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters, void * const pvParameters,
UBaseType_t uxPriority, UBaseType_t uxPriority,
@ -388,7 +388,7 @@ typedef enum
#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
BaseType_t xTaskCreateAffinitySet( TaskFunction_t pxTaskCode, BaseType_t xTaskCreateAffinitySet( TaskFunction_t pxTaskCode,
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ const char * const pcName,
const configSTACK_DEPTH_TYPE usStackDepth, const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters, void * const pvParameters,
UBaseType_t uxPriority, UBaseType_t uxPriority,
@ -506,7 +506,7 @@ typedef enum
*/ */
#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ const char * const pcName,
const uint32_t ulStackDepth, const uint32_t ulStackDepth,
void * const pvParameters, void * const pvParameters,
UBaseType_t uxPriority, UBaseType_t uxPriority,
@ -516,7 +516,7 @@ typedef enum
#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configNUMBER_OF_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
TaskHandle_t xTaskCreateStaticAffinitySet( TaskFunction_t pxTaskCode, TaskHandle_t xTaskCreateStaticAffinitySet( TaskFunction_t pxTaskCode,
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ const char * const pcName,
const uint32_t ulStackDepth, const uint32_t ulStackDepth,
void * const pvParameters, void * const pvParameters,
UBaseType_t uxPriority, UBaseType_t uxPriority,
@ -752,8 +752,10 @@ typedef enum
* \defgroup vTaskAllocateMPURegions vTaskAllocateMPURegions * \defgroup vTaskAllocateMPURegions vTaskAllocateMPURegions
* \ingroup Tasks * \ingroup Tasks
*/ */
void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, #if ( portUSING_MPU_WRAPPERS == 1 )
void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify,
const MemoryRegion_t * const pxRegions ) PRIVILEGED_FUNCTION; const MemoryRegion_t * const pxRegions ) PRIVILEGED_FUNCTION;
#endif
/** /**
* task. h * task. h
@ -960,7 +962,9 @@ BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
* \defgroup xTaskAbortDelay xTaskAbortDelay * \defgroup xTaskAbortDelay xTaskAbortDelay
* \ingroup TaskCtrl * \ingroup TaskCtrl
*/ */
BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; #if ( INCLUDE_xTaskAbortDelay == 1 )
BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
#endif
/** /**
* task. h * task. h
@ -1070,7 +1074,9 @@ UBaseType_t uxTaskBasePriorityGetFromISR( const TaskHandle_t xTask ) PRIVILEGED_
* state of the task might change between the function being called, and the * state of the task might change between the function being called, and the
* functions return value being tested by the calling task. * functions return value being tested by the calling task.
*/ */
eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; #if ( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) )
eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
#endif
/** /**
* task. h * task. h
@ -1128,10 +1134,12 @@ eTaskState eTaskGetState( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
* \defgroup vTaskGetInfo vTaskGetInfo * \defgroup vTaskGetInfo vTaskGetInfo
* \ingroup TaskCtrl * \ingroup TaskCtrl
*/ */
void vTaskGetInfo( TaskHandle_t xTask, #if ( configUSE_TRACE_FACILITY == 1 )
void vTaskGetInfo( TaskHandle_t xTask,
TaskStatus_t * pxTaskStatus, TaskStatus_t * pxTaskStatus,
BaseType_t xGetFreeStackSpace, BaseType_t xGetFreeStackSpace,
eTaskState eState ) PRIVILEGED_FUNCTION; eTaskState eState ) PRIVILEGED_FUNCTION;
#endif
/** /**
* task. h * task. h
@ -1737,7 +1745,7 @@ UBaseType_t uxTaskGetNumberOfTasks( void ) PRIVILEGED_FUNCTION;
* \defgroup pcTaskGetName pcTaskGetName * \defgroup pcTaskGetName pcTaskGetName
* \ingroup TaskUtils * \ingroup TaskUtils
*/ */
char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION;
/** /**
* task. h * task. h
@ -1755,7 +1763,9 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) PRIVILEGED_FUNCTION; /*lint !e
* \defgroup pcTaskGetHandle pcTaskGetHandle * \defgroup pcTaskGetHandle pcTaskGetHandle
* \ingroup TaskUtils * \ingroup TaskUtils
*/ */
TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ #if ( INCLUDE_xTaskGetHandle == 1 )
TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) PRIVILEGED_FUNCTION;
#endif
/** /**
* task. h * task. h
@ -1814,7 +1824,9 @@ TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) PRIVILEGED_FUNCTION; /
* actual spaces on the stack rather than bytes) since the task referenced by * actual spaces on the stack rather than bytes) since the task referenced by
* xTask was created. * xTask was created.
*/ */
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; #if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 )
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
#endif
/** /**
* task.h * task.h
@ -1843,7 +1855,9 @@ UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTIO
* actual spaces on the stack rather than bytes) since the task referenced by * actual spaces on the stack rather than bytes) since the task referenced by
* xTask was created. * xTask was created.
*/ */
configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; #if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 )
configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
#endif
/* When using trace macros it is sometimes necessary to include task.h before /* When using trace macros it is sometimes necessary to include task.h before
* FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been defined, * FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been defined,
@ -1922,6 +1936,9 @@ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVIL
* @param xTask the task that just exceeded its stack boundaries. * @param xTask the task that just exceeded its stack boundaries.
* @param pcTaskName A character string containing the name of the offending task. * @param pcTaskName A character string containing the name of the offending task.
*/ */
/* MISRA Ref 8.6.1 [External linkage] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-86 */
/* coverity[misra_c_2012_rule_8_6_violation] */
void vApplicationStackOverflowHook( TaskHandle_t xTask, void vApplicationStackOverflowHook( TaskHandle_t xTask,
char * pcTaskName ); char * pcTaskName );
@ -1940,6 +1957,9 @@ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVIL
* the overhead of a separate task. * the overhead of a separate task.
* NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, CALL A FUNCTION THAT MIGHT BLOCK. * NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, CALL A FUNCTION THAT MIGHT BLOCK.
*/ */
/* MISRA Ref 8.6.1 [External linkage] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-86 */
/* coverity[misra_c_2012_rule_8_6_violation] */
void vApplicationIdleHook( void ); void vApplicationIdleHook( void );
#endif #endif
@ -1955,7 +1975,10 @@ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVIL
* *
* This hook function is called in the system tick handler after any OS work is completed. * This hook function is called in the system tick handler after any OS work is completed.
*/ */
void vApplicationTickHook( void ); /*lint !e526 Symbol not defined as it is an application callback. */ /* MISRA Ref 8.6.1 [External linkage] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-86 */
/* coverity[misra_c_2012_rule_8_6_violation] */
void vApplicationTickHook( void );
#endif #endif
@ -1976,7 +1999,7 @@ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVIL
*/ */
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
StackType_t ** ppxIdleTaskStackBuffer, StackType_t ** ppxIdleTaskStackBuffer,
uint32_t * pulIdleTaskStackSize ); /*lint !e526 Symbol not defined as it is an application callback. */ uint32_t * pulIdleTaskStackSize );
/** /**
* task.h * task.h
@ -2023,31 +2046,35 @@ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVIL
* wants. The return value is the value returned by the task hook function * wants. The return value is the value returned by the task hook function
* registered by the user. * registered by the user.
*/ */
BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, #if ( configUSE_APPLICATION_TASK_TAG == 1 )
BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask,
void * pvParameter ) PRIVILEGED_FUNCTION; void * pvParameter ) PRIVILEGED_FUNCTION;
#endif
/** /**
* xTaskGetIdleTaskHandle() is only available if * xTaskGetIdleTaskHandle() is only available if
* INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h. * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h.
* *
* Simply returns the handle of the idle task. It is not valid to call * In single-core FreeRTOS, this function simply returns the handle of the idle
* xTaskGetIdleTaskHandle() before the scheduler has been started. * task. It is not valid to call xTaskGetIdleTaskHandle() before the scheduler
* has been started.
* *
* In the FreeRTOS SMP, there are a total of configNUMBER_OF_CORES idle tasks: * In the FreeRTOS SMP, there are a total of configNUMBER_OF_CORES idle tasks:
* 1. 1 Active idle task which does all the housekeeping. * 1. 1 Active idle task which does all the housekeeping.
* 2. ( configNUMBER_OF_CORES - 1 ) Passive idle tasks which do nothing. * 2. ( configNUMBER_OF_CORES - 1 ) Passive idle tasks which do nothing.
* These idle tasks are created to ensure that each core has an idle task to run when * These idle tasks are created to ensure that each core has an idle task to run when
* no other task is available to run. * no other task is available to run. Call xTaskGetIdleTaskHandle() or
* * xTaskGetIdleTaskHandleForCore() with xCoreID set to 0 to get the Active
* Set xCoreID to 0 to get the Active idle task handle. Set xCoreID to * idle task handle. Call xTaskGetIdleTaskHandleForCore() with xCoreID set to
* 1,2 ... ( configNUMBER_OF_CORES - 1 ) to get the Passive idle task * 1,2 ... ( configNUMBER_OF_CORES - 1 ) to get the Passive idle task handles.
* handles.
*/ */
#if ( configNUMBER_OF_CORES == 1 ) #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
#if ( configNUMBER_OF_CORES == 1 )
TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION; TaskHandle_t xTaskGetIdleTaskHandle( void ) PRIVILEGED_FUNCTION;
#else /* #if ( configNUMBER_OF_CORES == 1 ) */ #endif /* #if ( configNUMBER_OF_CORES == 1 ) */
TaskHandle_t xTaskGetIdleTaskHandle( BaseType_t xCoreID ) PRIVILEGED_FUNCTION;
#endif /* #if ( configNUMBER_OF_CORES == 1 ) */ TaskHandle_t xTaskGetIdleTaskHandleForCore( BaseType_t xCoreID ) PRIVILEGED_FUNCTION;
#endif /* #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) */
/** /**
* configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for * configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for
@ -2146,9 +2173,11 @@ BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask,
* } * }
* @endcode * @endcode
*/ */
UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, #if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
const UBaseType_t uxArraySize, const UBaseType_t uxArraySize,
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION; configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime ) PRIVILEGED_FUNCTION;
#endif
/** /**
* task. h * task. h
@ -2201,8 +2230,10 @@ UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
* \defgroup vTaskListTasks vTaskListTasks * \defgroup vTaskListTasks vTaskListTasks
* \ingroup TaskUtils * \ingroup TaskUtils
*/ */
void vTaskListTasks( char * pcWriteBuffer, #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) )
void vTaskListTasks( char * pcWriteBuffer,
size_t uxBufferLength ) PRIVILEGED_FUNCTION; size_t uxBufferLength ) PRIVILEGED_FUNCTION;
#endif
/** /**
* task. h * task. h
@ -2316,8 +2347,10 @@ void vTaskListTasks( char * pcWriteBuffer,
* \defgroup vTaskGetRunTimeStatistics vTaskGetRunTimeStatistics * \defgroup vTaskGetRunTimeStatistics vTaskGetRunTimeStatistics
* \ingroup TaskUtils * \ingroup TaskUtils
*/ */
void vTaskGetRunTimeStatistics( char * pcWriteBuffer, #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( configUSE_STATS_FORMATTING_FUNCTIONS > 0 ) && ( configUSE_TRACE_FACILITY == 1 ) )
size_t uxBufferLength ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ void vTaskGetRunTimeStatistics( char * pcWriteBuffer,
size_t uxBufferLength ) PRIVILEGED_FUNCTION;
#endif
/** /**
* task. h * task. h
@ -2414,8 +2447,10 @@ void vTaskGetRunTimeStatistics( char * pcWriteBuffer,
* \defgroup ulTaskGetRunTimeCounter ulTaskGetRunTimeCounter * \defgroup ulTaskGetRunTimeCounter ulTaskGetRunTimeCounter
* \ingroup TaskUtils * \ingroup TaskUtils
*/ */
configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; #if ( configGENERATE_RUN_TIME_STATS == 1 )
configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION; configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimeCounter( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
#endif
/** /**
* task. h * task. h
@ -2454,8 +2489,10 @@ configRUN_TIME_COUNTER_TYPE ulTaskGetRunTimePercent( const TaskHandle_t xTask )
* \defgroup ulTaskGetIdleRunTimeCounter ulTaskGetIdleRunTimeCounter * \defgroup ulTaskGetIdleRunTimeCounter ulTaskGetIdleRunTimeCounter
* \ingroup TaskUtils * \ingroup TaskUtils
*/ */
configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION; #if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ) PRIVILEGED_FUNCTION; configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION;
configRUN_TIME_COUNTER_TYPE ulTaskGetIdleRunTimePercent( void ) PRIVILEGED_FUNCTION;
#endif
/** /**
* task. h * task. h
@ -3537,7 +3574,9 @@ TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION;
/* /*
* Return the handle of the task running on specified core. * Return the handle of the task running on specified core.
*/ */
TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID ) PRIVILEGED_FUNCTION; #if ( configNUMBER_OF_CORES > 1 )
TaskHandle_t xTaskGetCurrentTaskHandleForCore( BaseType_t xCoreID ) PRIVILEGED_FUNCTION;
#endif
/* /*
* Shortcut used by the queue implementation to prevent unnecessary call to * Shortcut used by the queue implementation to prevent unnecessary call to
@ -3577,14 +3616,18 @@ void vTaskPriorityDisinheritAfterTimeout( TaskHandle_t const pxMutexHolder,
/* /*
* Get the uxTaskNumber assigned to the task referenced by the xTask parameter. * Get the uxTaskNumber assigned to the task referenced by the xTask parameter.
*/ */
UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) PRIVILEGED_FUNCTION; #if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxTaskGetTaskNumber( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
#endif
/* /*
* Set the uxTaskNumber of the task referenced by the xTask parameter to * Set the uxTaskNumber of the task referenced by the xTask parameter to
* uxHandle. * uxHandle.
*/ */
void vTaskSetTaskNumber( TaskHandle_t xTask, #if ( configUSE_TRACE_FACILITY == 1 )
void vTaskSetTaskNumber( TaskHandle_t xTask,
const UBaseType_t uxHandle ) PRIVILEGED_FUNCTION; const UBaseType_t uxHandle ) PRIVILEGED_FUNCTION;
#endif
/* /*
* Only available when configUSE_TICKLESS_IDLE is set to 1. * Only available when configUSE_TICKLESS_IDLE is set to 1.
@ -3594,7 +3637,9 @@ void vTaskSetTaskNumber( TaskHandle_t xTask,
* to date with the actual execution time by being skipped forward by a time * to date with the actual execution time by being skipped forward by a time
* equal to the idle period. * equal to the idle period.
*/ */
void vTaskStepTick( TickType_t xTicksToJump ) PRIVILEGED_FUNCTION; #if ( configUSE_TICKLESS_IDLE != 0 )
void vTaskStepTick( TickType_t xTicksToJump ) PRIVILEGED_FUNCTION;
#endif
/* /*
* Only available when configUSE_TICKLESS_IDLE is set to 1. * Only available when configUSE_TICKLESS_IDLE is set to 1.
@ -3610,7 +3655,9 @@ void vTaskStepTick( TickType_t xTicksToJump ) PRIVILEGED_FUNCTION;
* critical section between the timer being stopped and the sleep mode being * critical section between the timer being stopped and the sleep mode being
* entered to ensure it is ok to proceed into the sleep mode. * entered to ensure it is ok to proceed into the sleep mode.
*/ */
eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION; #if ( configUSE_TICKLESS_IDLE != 0 )
eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION;
#endif
/* /*
* For internal use only. Increment the mutex held count when a mutex is * For internal use only. Increment the mutex held count when a mutex is
@ -3628,7 +3675,9 @@ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNC
* For internal use only. Same as portYIELD_WITHIN_API() in single core FreeRTOS. * For internal use only. Same as portYIELD_WITHIN_API() in single core FreeRTOS.
* For SMP this is not defined by the port. * For SMP this is not defined by the port.
*/ */
void vTaskYieldWithinAPI( void ); #if ( configNUMBER_OF_CORES > 1 )
void vTaskYieldWithinAPI( void );
#endif
/* /*
* This function is only intended for use when implementing a port of the scheduler * This function is only intended for use when implementing a port of the scheduler
@ -3638,7 +3687,9 @@ void vTaskYieldWithinAPI( void );
* It should be used in the implementation of portENTER_CRITICAL if port is running a * It should be used in the implementation of portENTER_CRITICAL if port is running a
* multiple core FreeRTOS. * multiple core FreeRTOS.
*/ */
void vTaskEnterCritical( void ); #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) || ( configNUMBER_OF_CORES > 1 ) )
void vTaskEnterCritical( void );
#endif
/* /*
* This function is only intended for use when implementing a port of the scheduler * This function is only intended for use when implementing a port of the scheduler
@ -3648,7 +3699,9 @@ void vTaskEnterCritical( void );
* It should be used in the implementation of portEXIT_CRITICAL if port is running a * It should be used in the implementation of portEXIT_CRITICAL if port is running a
* multiple core FreeRTOS. * multiple core FreeRTOS.
*/ */
void vTaskExitCritical( void ); #if ( ( portCRITICAL_NESTING_IN_TCB == 1 ) || ( configNUMBER_OF_CORES > 1 ) )
void vTaskExitCritical( void );
#endif
/* /*
* This function is only intended for use when implementing a port of the scheduler * This function is only intended for use when implementing a port of the scheduler
@ -3656,7 +3709,9 @@ void vTaskExitCritical( void );
* should be used in the implementation of portENTER_CRITICAL_FROM_ISR if port is * should be used in the implementation of portENTER_CRITICAL_FROM_ISR if port is
* running a multiple core FreeRTOS. * running a multiple core FreeRTOS.
*/ */
UBaseType_t vTaskEnterCriticalFromISR( void ); #if ( configNUMBER_OF_CORES > 1 )
UBaseType_t vTaskEnterCriticalFromISR( void );
#endif
/* /*
* This function is only intended for use when implementing a port of the scheduler * This function is only intended for use when implementing a port of the scheduler
@ -3664,7 +3719,9 @@ UBaseType_t vTaskEnterCriticalFromISR( void );
* should be used in the implementation of portEXIT_CRITICAL_FROM_ISR if port is * should be used in the implementation of portEXIT_CRITICAL_FROM_ISR if port is
* running a multiple core FreeRTOS. * running a multiple core FreeRTOS.
*/ */
void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus ); #if ( configNUMBER_OF_CORES > 1 )
void vTaskExitCriticalFromISR( UBaseType_t uxSavedInterruptStatus );
#endif
#if ( portUSING_MPU_WRAPPERS == 1 ) #if ( portUSING_MPU_WRAPPERS == 1 )

View file

@ -34,10 +34,8 @@
#error "include FreeRTOS.h must appear in source files before include timers.h" #error "include FreeRTOS.h must appear in source files before include timers.h"
#endif #endif
/*lint -save -e537 This headers are only multiply included if the application code
* happens to also be including task.h. */
#include "task.h" #include "task.h"
/*lint -restore */
/* *INDENT-OFF* */ /* *INDENT-OFF* */
#ifdef __cplusplus #ifdef __cplusplus
@ -88,8 +86,8 @@ typedef void (* TimerCallbackFunction_t)( TimerHandle_t xTimer );
* Defines the prototype to which functions used with the * Defines the prototype to which functions used with the
* xTimerPendFunctionCallFromISR() function must conform. * xTimerPendFunctionCallFromISR() function must conform.
*/ */
typedef void (* PendedFunction_t)( void *, typedef void (* PendedFunction_t)( void * arg1,
uint32_t ); uint32_t arg2 );
/** /**
* TimerHandle_t xTimerCreate( const char * const pcTimerName, * TimerHandle_t xTimerCreate( const char * const pcTimerName,
@ -229,7 +227,7 @@ typedef void (* PendedFunction_t)( void *,
* @endverbatim * @endverbatim
*/ */
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
TimerHandle_t xTimerCreate( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ TimerHandle_t xTimerCreate( const char * const pcTimerName,
const TickType_t xTimerPeriodInTicks, const TickType_t xTimerPeriodInTicks,
const BaseType_t xAutoReload, const BaseType_t xAutoReload,
void * const pvTimerID, void * const pvTimerID,
@ -359,7 +357,7 @@ typedef void (* PendedFunction_t)( void *,
* @endverbatim * @endverbatim
*/ */
#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ TimerHandle_t xTimerCreateStatic( const char * const pcTimerName,
const TickType_t xTimerPeriodInTicks, const TickType_t xTimerPeriodInTicks,
const BaseType_t xAutoReload, const BaseType_t xAutoReload,
void * const pvTimerID, void * const pvTimerID,
@ -1198,10 +1196,12 @@ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) PRIVILEGED_FUNCTION;
* } * }
* @endverbatim * @endverbatim
*/ */
BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend, #if ( INCLUDE_xTimerPendFunctionCall == 1 )
BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend,
void * pvParameter1, void * pvParameter1,
uint32_t ulParameter2, uint32_t ulParameter2,
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
#endif
/** /**
* BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, * BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend,
@ -1235,10 +1235,12 @@ BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t xFunctionToPend,
* timer daemon task, otherwise pdFALSE is returned. * timer daemon task, otherwise pdFALSE is returned.
* *
*/ */
BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, #if ( INCLUDE_xTimerPendFunctionCall == 1 )
BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend,
void * pvParameter1, void * pvParameter1,
uint32_t ulParameter2, uint32_t ulParameter2,
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
#endif
/** /**
* const char * const pcTimerGetName( TimerHandle_t xTimer ); * const char * const pcTimerGetName( TimerHandle_t xTimer );
@ -1249,7 +1251,7 @@ BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend,
* *
* @return The name assigned to the timer specified by the xTimer parameter. * @return The name assigned to the timer specified by the xTimer parameter.
*/ */
const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
/** /**
* void vTimerSetReloadMode( TimerHandle_t xTimer, const BaseType_t xAutoReload ); * void vTimerSetReloadMode( TimerHandle_t xTimer, const BaseType_t xAutoReload );
@ -1408,6 +1410,9 @@ BaseType_t xTimerGenericCommandFromISR( TimerHandle_t xTimer,
* *
* This hook function is called form the timer task once when the task starts running. * This hook function is called form the timer task once when the task starts running.
*/ */
/* MISRA Ref 8.6.1 [External linkage] */
/* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-86 */
/* coverity[misra_c_2012_rule_8_6_violation] */
void vApplicationDaemonTaskStartupHook( void ); void vApplicationDaemonTaskStartupHook( void );
#endif #endif

13
list.c
View file

@ -37,11 +37,10 @@
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "list.h" #include "list.h"
/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified /* The MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be
* because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be
* defined for the header files above, but not in this file, in order to * defined for the header files above, but not in this file, in order to
* generate the correct privileged Vs unprivileged linkage and placement. */ * generate the correct privileged Vs unprivileged linkage and placement. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
/*----------------------------------------------------------- /*-----------------------------------------------------------
* PUBLIC LIST API documented in list.h * PUBLIC LIST API documented in list.h
@ -54,7 +53,7 @@ void vListInitialise( List_t * const pxList )
/* The list structure contains a list item which is used to mark the /* The list structure contains a list item which is used to mark the
* end of the list. To initialise the list the list end is inserted * end of the list. To initialise the list the list end is inserted
* as the only list entry. */ * as the only list entry. */
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) ); listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) );
@ -64,8 +63,8 @@ void vListInitialise( List_t * const pxList )
/* The list end next and previous pointers point to itself so we know /* The list end next and previous pointers point to itself so we know
* when the list is empty. */ * when the list is empty. */
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );
/* Initialize the remaining fields of xListEnd when it is a proper ListItem_t */ /* Initialize the remaining fields of xListEnd when it is a proper ListItem_t */
#if ( configUSE_MINI_LIST_ITEM == 0 ) #if ( configUSE_MINI_LIST_ITEM == 0 )
@ -190,7 +189,7 @@ void vListInsert( List_t * const pxList,
* configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
**********************************************************************/ **********************************************************************/
for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. *//*lint !e440 The iterator moves to a different value, not xValueOfInsertion. */ for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext )
{ {
/* There is nothing to do here, just iterating to the wanted /* There is nothing to do here, just iterating to the wanted
* insertion position. */ * insertion position. */

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -27,22 +27,22 @@
*/ */
/* /*
* Changes from V1.00: Changes from V1.00:
*
+ Call to taskYIELD() from within tick ISR has been replaced by the more + Call to taskYIELD() from within tick ISR has been replaced by the more
+ efficient portSWITCH_CONTEXT(). efficient portSWITCH_CONTEXT().
+ ISR function definitions renamed to include the prv prefix. + ISR function definitions renamed to include the prv prefix.
+
+ Changes from V2.6.1 Changes from V2.6.1
+
+ Replaced the sUsingPreemption variable with the configUSE_PREEMPTION + Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
+ macro to be consistent with the later ports. macro to be consistent with the later ports.
*/ */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the Flashlite 186 * Implementation of functions defined in portable.h for the Flashlite 186
* port. * port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
#include <dos.h> #include <dos.h>
#include <stdlib.h> #include <stdlib.h>
@ -69,16 +69,14 @@ static void prvSetTickFrequency( uint32_t ulTickRateHz );
static void prvExitFunction( void ); static void prvExitFunction( void );
/* The ISR used depends on whether the preemptive or cooperative scheduler /* The ISR used depends on whether the preemptive or cooperative scheduler
* is being used. */ is being used. */
#if ( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
/* Tick service routine used by the scheduler when preemptive scheduling is
/* Tick service routine used by the scheduler when preemptive scheduling is being used. */
* being used. */
static void __interrupt __far prvPreemptiveTick( void ); static void __interrupt __far prvPreemptiveTick( void );
#else #else
/* Tick service routine used by the scheduler when cooperative scheduling is
/* Tick service routine used by the scheduler when cooperative scheduling is being used. */
* being used. */
static void __interrupt __far prvNonPreemptiveTick( void ); static void __interrupt __far prvNonPreemptiveTick( void );
#endif #endif
@ -91,9 +89,9 @@ static void __interrupt __far prvYieldProcessor( void );
static BaseType_t xSchedulerRunning = pdFALSE; static BaseType_t xSchedulerRunning = pdFALSE;
/* Points to the original routine installed on the vector we use for manual /* Points to the original routine installed on the vector we use for manual
* context switches. This is then used to restore the original routine during context switches. This is then used to restore the original routine during
* prvExitFunction(). */ prvExitFunction(). */
static void( __interrupt __far * pxOldSwitchISR )(); static void ( __interrupt __far *pxOldSwitchISR )();
/* Used to restore the original DOS context when the scheduler is ended. */ /* Used to restore the original DOS context when the scheduler is ended. */
static jmp_buf xJumpBuf; static jmp_buf xJumpBuf;
@ -106,14 +104,14 @@ BaseType_t xPortStartScheduler( void )
/* This is called with interrupts already disabled. */ /* This is called with interrupts already disabled. */
/* Remember what was on the interrupts we are going to use /* Remember what was on the interrupts we are going to use
* so we can put them back later if required. */ so we can put them back later if required. */
pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER ); pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER );
/* Put our manual switch (yield) function on a known /* Put our manual switch (yield) function on a known
* vector. */ vector. */
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor ); _dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
#if ( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
{ {
/* Put our tick switch function on the timer interrupt. */ /* Put our tick switch function on the timer interrupt. */
_dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick ); _dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick );
@ -146,8 +144,8 @@ BaseType_t xPortStartScheduler( void )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* The ISR used depends on whether the preemptive or cooperative scheduler /* The ISR used depends on whether the preemptive or cooperative scheduler
* is being used. */ is being used. */
#if ( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
static void __interrupt __far prvPreemptiveTick( void ) static void __interrupt __far prvPreemptiveTick( void )
{ {
/* Get the scheduler to update the task states following the tick. */ /* Get the scheduler to update the task states following the tick. */
@ -160,15 +158,15 @@ BaseType_t xPortStartScheduler( void )
/* Reset the PIC ready for the next time. */ /* Reset the PIC ready for the next time. */
portRESET_PIC(); portRESET_PIC();
} }
#else /* if ( configUSE_PREEMPTION == 1 ) */ #else
static void __interrupt __far prvNonPreemptiveTick( void ) static void __interrupt __far prvNonPreemptiveTick( void )
{ {
/* Same as preemptive tick, but the cooperative scheduler is being used /* Same as preemptive tick, but the cooperative scheduler is being used
* so we don't have to switch in the context of the next task. */ so we don't have to switch in the context of the next task. */
xTaskIncrementTick(); xTaskIncrementTick();
portRESET_PIC(); portRESET_PIC();
} }
#endif /* if ( configUSE_PREEMPTION == 1 ) */ #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void __interrupt __far prvYieldProcessor( void ) static void __interrupt __far prvYieldProcessor( void )
@ -181,31 +179,30 @@ static void __interrupt __far prvYieldProcessor( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Jump back to the processor state prior to starting the /* Jump back to the processor state prior to starting the
* scheduler. This means we are not going to be using a scheduler. This means we are not going to be using a
* task stack frame so the task can be deleted. */ task stack frame so the task can be deleted. */
longjmp( xJumpBuf, 1 ); longjmp( xJumpBuf, 1 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvExitFunction( void ) static void prvExitFunction( void )
{ {
const uint16_t usTimerDisable = 0x0000; const uint16_t usTimerDisable = 0x0000;
uint16_t usTimer0Control; uint16_t usTimer0Control;
/* Interrupts should be disabled here anyway - but no /* Interrupts should be disabled here anyway - but no
* harm in making sure. */ harm in making sure. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
if( xSchedulerRunning == pdTRUE ) if( xSchedulerRunning == pdTRUE )
{ {
/* Put back the switch interrupt routines that was in place /* Put back the switch interrupt routines that was in place
* before the scheduler started. */ before the scheduler started. */
_dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR ); _dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR );
} }
/* Disable the timer used for the tick to ensure the scheduler is /* Disable the timer used for the tick to ensure the scheduler is
* not called before restoring interrupts. There was previously nothing not called before restoring interrupts. There was previously nothing
* on this timer so there is no old ISR to restore. */ on this timer so there is no old ISR to restore. */
portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerDisable ); portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerDisable );
/* Restart the DOS tick. */ /* Restart the DOS tick. */
@ -220,18 +217,18 @@ static void prvExitFunction( void )
static void prvSetTickFrequency( uint32_t ulTickRateHz ) static void prvSetTickFrequency( uint32_t ulTickRateHz )
{ {
const uint16_t usMaxCountRegister = 0xff5a; const uint16_t usMaxCountRegister = 0xff5a;
const uint16_t usTimerPriorityRegister = 0xff32; const uint16_t usTimerPriorityRegister = 0xff32;
const uint16_t usTimerEnable = 0xC000; const uint16_t usTimerEnable = 0xC000;
const uint16_t usRetrigger = 0x0001; const uint16_t usRetrigger = 0x0001;
const uint16_t usTimerHighPriority = 0x0000; const uint16_t usTimerHighPriority = 0x0000;
uint16_t usTimer0Control; uint16_t usTimer0Control;
/* ( CPU frequency / 4 ) / clock 2 max count [inpw( 0xff62 ) = 7] */ /* ( CPU frequency / 4 ) / clock 2 max count [inpw( 0xff62 ) = 7] */
const uint32_t ulClockFrequency = ( uint32_t ) 0x7f31a0UL; const uint32_t ulClockFrequency = ( uint32_t ) 0x7f31a0UL;
uint32_t ulTimerCount = ulClockFrequency / ulTickRateHz; uint32_t ulTimerCount = ulClockFrequency / ulTickRateHz;
portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerEnable | portTIMER_INTERRUPT_ENABLE | usRetrigger ); portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerEnable | portTIMER_INTERRUPT_ENABLE | usRetrigger );
portOUTPUT_WORD( usMaxCountRegister, ( uint16_t ) ulTimerCount ); portOUTPUT_WORD( usMaxCountRegister, ( uint16_t ) ulTimerCount );

View file

@ -52,7 +52,7 @@ typedef portSTACK_TYPE StackType_t;
typedef short BaseType_t; typedef short BaseType_t;
typedef unsigned short UBaseType_t; typedef unsigned short UBaseType_t;
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) #if( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
@ -64,22 +64,21 @@ typedef unsigned short UBaseType_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section handling. */ /* Critical section handling. */
#define portENTER_CRITICAL() \ #define portENTER_CRITICAL() __asm{ pushf } \
__asm { pushf } \ __asm{ cli } \
__asm { cli } \
#define portEXIT_CRITICAL() __asm { popf } #define portEXIT_CRITICAL() __asm{ popf }
#define portDISABLE_INTERRUPTS() __asm { cli } #define portDISABLE_INTERRUPTS() __asm{ cli }
#define portENABLE_INTERRUPTS() __asm { sti } #define portENABLE_INTERRUPTS() __asm{ sti }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portNOP() __asm { nop } #define portNOP() __asm{ nop }
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portSWITCH_INT_NUMBER 0x80 #define portSWITCH_INT_NUMBER 0x80
#define portYIELD() __asm { int portSWITCH_INT_NUMBER } #define portYIELD() __asm{ int portSWITCH_INT_NUMBER }
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 2 #define portBYTE_ALIGNMENT 2
#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */ #define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */
@ -94,7 +93,7 @@ typedef unsigned short UBaseType_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vTaskFunction, vParameters ) void vTaskFunction( void * pvParameters ) #define portTASK_FUNCTION_PROTO( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters )
#define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void * pvParameters ) #define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters )
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -27,16 +27,16 @@
*/ */
/* /*
* Changes from V2.6.1 Changes from V2.6.1
*
+ Replaced the sUsingPreemption variable with the configUSE_PREEMPTION + Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
+ macro to be consistent with the later ports. macro to be consistent with the later ports.
+
+ Changes from V4.0.1 Changes from V4.0.1
+
+ Add function prvSetTickFrequencyDefault() to set the DOS tick back to + Add function prvSetTickFrequencyDefault() to set the DOS tick back to
+ its proper value when the scheduler exits. its proper value when the scheduler exits.
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <dos.h> #include <dos.h>
@ -47,9 +47,9 @@
#include "portasm.h" #include "portasm.h"
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the industrial * Implementation of functions defined in portable.h for the industrial
* PC port. * PC port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/*lint -e950 Non ANSI reserved words okay in this file only. */ /*lint -e950 Non ANSI reserved words okay in this file only. */
@ -62,21 +62,19 @@ static void prvSetTickFrequency( uint32_t ulTickRateHz );
static void prvExitFunction( void ); static void prvExitFunction( void );
/* Either chain to the DOS tick (which itself clears the PIC) or clear the PIC /* Either chain to the DOS tick (which itself clears the PIC) or clear the PIC
* directly. We chain to the DOS tick as close as possible to the standard DOS directly. We chain to the DOS tick as close as possible to the standard DOS
* tick rate. */ tick rate. */
static void prvPortResetPIC( void ); static void prvPortResetPIC( void );
/* The ISR used depends on whether the preemptive or cooperative /* The ISR used depends on whether the preemptive or cooperative
* scheduler is being used. */ scheduler is being used. */
#if ( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
/* Tick service routine used by the scheduler when preemptive scheduling is
/* Tick service routine used by the scheduler when preemptive scheduling is being used. */
* being used. */
static void __interrupt __far prvPreemptiveTick( void ); static void __interrupt __far prvPreemptiveTick( void );
#else #else
/* Tick service routine used by the scheduler when cooperative scheduling is
/* Tick service routine used by the scheduler when cooperative scheduling is being used. */
* being used. */
static void __interrupt __far prvNonPreemptiveTick( void ); static void __interrupt __far prvNonPreemptiveTick( void );
#endif #endif
@ -84,7 +82,7 @@ static void prvPortResetPIC( void );
static void __interrupt __far prvYieldProcessor( void ); static void __interrupt __far prvYieldProcessor( void );
/* Set the tick frequency back so the floppy drive works correctly when the /* Set the tick frequency back so the floppy drive works correctly when the
* scheduler exits. */ scheduler exits. */
static void prvSetTickFrequencyDefault( void ); static void prvSetTickFrequencyDefault( void );
/*lint -e956 File scopes necessary here. */ /*lint -e956 File scopes necessary here. */
@ -96,10 +94,10 @@ static int16_t sDOSTickCounter;
static BaseType_t xSchedulerRunning = pdFALSE; static BaseType_t xSchedulerRunning = pdFALSE;
/* Points to the original routine installed on the vector we use for manual context switches. This is then used to restore the original routine during prvExitFunction(). */ /* Points to the original routine installed on the vector we use for manual context switches. This is then used to restore the original routine during prvExitFunction(). */
static void( __interrupt __far * pxOldSwitchISR )(); static void ( __interrupt __far *pxOldSwitchISR )();
/* Points to the original routine installed on the vector we use to chain to the DOS tick. This is then used to restore the original routine during prvExitFunction(). */ /* Points to the original routine installed on the vector we use to chain to the DOS tick. This is then used to restore the original routine during prvExitFunction(). */
static void( __interrupt __far * pxOldSwitchISRPlus1 )(); static void ( __interrupt __far *pxOldSwitchISRPlus1 )();
/* Used to restore the original DOS context when the scheduler is ended. */ /* Used to restore the original DOS context when the scheduler is ended. */
static jmp_buf xJumpBuf; static jmp_buf xJumpBuf;
@ -109,12 +107,12 @@ static jmp_buf xJumpBuf;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
pxISR pxOriginalTickISR; pxISR pxOriginalTickISR;
/* This is called with interrupts already disabled. */ /* This is called with interrupts already disabled. */
/* Remember what was on the interrupts we are going to use /* Remember what was on the interrupts we are going to use
* so we can put them back later if required. */ so we can put them back later if required. */
pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER ); pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER );
pxOriginalTickISR = _dos_getvect( portTIMER_INT_NUMBER ); pxOriginalTickISR = _dos_getvect( portTIMER_INT_NUMBER );
pxOldSwitchISRPlus1 = _dos_getvect( portSWITCH_INT_NUMBER + 1 ); pxOldSwitchISRPlus1 = _dos_getvect( portSWITCH_INT_NUMBER + 1 );
@ -122,16 +120,16 @@ BaseType_t xPortStartScheduler( void )
prvSetTickFrequency( configTICK_RATE_HZ ); prvSetTickFrequency( configTICK_RATE_HZ );
/* Put our manual switch (yield) function on a known /* Put our manual switch (yield) function on a known
* vector. */ vector. */
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor ); _dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
/* Put the old tick on a different interrupt number so we can /* Put the old tick on a different interrupt number so we can
* call it when we want. */ call it when we want. */
_dos_setvect( portSWITCH_INT_NUMBER + 1, pxOriginalTickISR ); _dos_setvect( portSWITCH_INT_NUMBER + 1, pxOriginalTickISR );
/* The ISR used depends on whether the preemptive or cooperative /* The ISR used depends on whether the preemptive or cooperative
* scheduler is being used. */ scheduler is being used. */
#if ( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
{ {
/* Put our tick switch function on the timer interrupt. */ /* Put our tick switch function on the timer interrupt. */
_dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick ); _dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick );
@ -144,8 +142,8 @@ BaseType_t xPortStartScheduler( void )
#endif #endif
/* Setup a counter that is used to call the DOS interrupt as close /* Setup a counter that is used to call the DOS interrupt as close
* to it's original frequency as can be achieved given our chosen tick to it's original frequency as can be achieved given our chosen tick
* frequency. */ frequency. */
sDOSTickCounter = portTICKS_PER_DOS_TICK; sDOSTickCounter = portTICKS_PER_DOS_TICK;
/* Clean up function if we want to return to DOS. */ /* Clean up function if we want to return to DOS. */
@ -167,8 +165,8 @@ BaseType_t xPortStartScheduler( void )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* The ISR used depends on whether the preemptive or cooperative /* The ISR used depends on whether the preemptive or cooperative
* scheduler is being used. */ scheduler is being used. */
#if ( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
static void __interrupt __far prvPreemptiveTick( void ) static void __interrupt __far prvPreemptiveTick( void )
{ {
/* Get the scheduler to update the task states following the tick. */ /* Get the scheduler to update the task states following the tick. */
@ -181,15 +179,15 @@ BaseType_t xPortStartScheduler( void )
/* Reset the PIC ready for the next time. */ /* Reset the PIC ready for the next time. */
prvPortResetPIC(); prvPortResetPIC();
} }
#else /* if ( configUSE_PREEMPTION == 1 ) */ #else
static void __interrupt __far prvNonPreemptiveTick( void ) static void __interrupt __far prvNonPreemptiveTick( void )
{ {
/* Same as preemptive tick, but the cooperative scheduler is being used /* Same as preemptive tick, but the cooperative scheduler is being used
* so we don't have to switch in the context of the next task. */ so we don't have to switch in the context of the next task. */
xTaskIncrementTick(); xTaskIncrementTick();
prvPortResetPIC(); prvPortResetPIC();
} }
#endif /* if ( configUSE_PREEMPTION == 1 ) */ #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void __interrupt __far prvYieldProcessor( void ) static void __interrupt __far prvYieldProcessor( void )
@ -202,22 +200,19 @@ static void __interrupt __far prvYieldProcessor( void )
static void prvPortResetPIC( void ) static void prvPortResetPIC( void )
{ {
/* We are going to call the DOS tick interrupt at as close a /* We are going to call the DOS tick interrupt at as close a
* frequency to the normal DOS tick as possible. */ frequency to the normal DOS tick as possible. */
/* WE SHOULD NOT DO THIS IF YIELD WAS CALLED. */ /* WE SHOULD NOT DO THIS IF YIELD WAS CALLED. */
--sDOSTickCounter; --sDOSTickCounter;
if( sDOSTickCounter <= 0 ) if( sDOSTickCounter <= 0 )
{ {
sDOSTickCounter = ( int16_t ) portTICKS_PER_DOS_TICK; sDOSTickCounter = ( int16_t ) portTICKS_PER_DOS_TICK;
__asm { __asm{ int portSWITCH_INT_NUMBER + 1 };
int portSWITCH_INT_NUMBER + 1
};
} }
else else
{ {
/* Reset the PIC as the DOS tick is not being called to /* Reset the PIC as the DOS tick is not being called to
* do it. */ do it. */
__asm __asm
{ {
mov al, 20H mov al, 20H
@ -230,20 +225,19 @@ static void prvPortResetPIC( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Jump back to the processor state prior to starting the /* Jump back to the processor state prior to starting the
* scheduler. This means we are not going to be using a scheduler. This means we are not going to be using a
* task stack frame so the task can be deleted. */ task stack frame so the task can be deleted. */
longjmp( xJumpBuf, 1 ); longjmp( xJumpBuf, 1 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvExitFunction( void ) static void prvExitFunction( void )
{ {
void( __interrupt __far * pxOriginalTickISR )(); void ( __interrupt __far *pxOriginalTickISR )();
/* Interrupts should be disabled here anyway - but no /* Interrupts should be disabled here anyway - but no
* harm in making sure. */ harm in making sure. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
if( xSchedulerRunning == pdTRUE ) if( xSchedulerRunning == pdTRUE )
{ {
/* Set the DOS tick back onto the timer ticker. */ /* Set the DOS tick back onto the timer ticker. */
@ -252,29 +246,28 @@ static void prvExitFunction( void )
prvSetTickFrequencyDefault(); prvSetTickFrequencyDefault();
/* Put back the switch interrupt routines that was in place /* Put back the switch interrupt routines that was in place
* before the scheduler started. */ before the scheduler started. */
_dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR ); _dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR );
_dos_setvect( portSWITCH_INT_NUMBER + 1, pxOldSwitchISRPlus1 ); _dos_setvect( portSWITCH_INT_NUMBER + 1, pxOldSwitchISRPlus1 );
} }
/* The tick timer is back how DOS wants it. We can re-enable /* The tick timer is back how DOS wants it. We can re-enable
* interrupts without the scheduler being called. */ interrupts without the scheduler being called. */
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSetTickFrequency( uint32_t ulTickRateHz ) static void prvSetTickFrequency( uint32_t ulTickRateHz )
{ {
const uint16_t usPIT_MODE = ( uint16_t ) 0x43; const uint16_t usPIT_MODE = ( uint16_t ) 0x43;
const uint16_t usPIT0 = ( uint16_t ) 0x40; const uint16_t usPIT0 = ( uint16_t ) 0x40;
const uint32_t ulPIT_CONST = ( uint32_t ) 1193180UL; const uint32_t ulPIT_CONST = ( uint32_t ) 1193180UL;
const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36; const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36;
uint32_t ulOutput; uint32_t ulOutput;
/* Setup the 8245 to tick at the wanted frequency. */ /* Setup the 8245 to tick at the wanted frequency. */
portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 ); portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 );
ulOutput = ulPIT_CONST / ulTickRateHz; ulOutput = ulPIT_CONST / ulTickRateHz;
portOUTPUT_BYTE( usPIT0, ( uint16_t ) ( ulOutput & ( uint32_t ) 0xff ) ); portOUTPUT_BYTE( usPIT0, ( uint16_t )( ulOutput & ( uint32_t ) 0xff ) );
ulOutput >>= 8; ulOutput >>= 8;
portOUTPUT_BYTE( usPIT0, ( uint16_t ) ( ulOutput & ( uint32_t ) 0xff ) ); portOUTPUT_BYTE( usPIT0, ( uint16_t ) ( ulOutput & ( uint32_t ) 0xff ) );
} }
@ -282,13 +275,13 @@ static void prvSetTickFrequency( uint32_t ulTickRateHz )
static void prvSetTickFrequencyDefault( void ) static void prvSetTickFrequencyDefault( void )
{ {
const uint16_t usPIT_MODE = ( uint16_t ) 0x43; const uint16_t usPIT_MODE = ( uint16_t ) 0x43;
const uint16_t usPIT0 = ( uint16_t ) 0x40; const uint16_t usPIT0 = ( uint16_t ) 0x40;
const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36; const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36;
portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 ); portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 );
portOUTPUT_BYTE( usPIT0, 0 ); portOUTPUT_BYTE( usPIT0,0 );
portOUTPUT_BYTE( usPIT0, 0 ); portOUTPUT_BYTE( usPIT0,0 );
} }

View file

@ -52,7 +52,7 @@ typedef portSTACK_TYPE StackType_t;
typedef short BaseType_t; typedef short BaseType_t;
typedef unsigned short UBaseType_t; typedef unsigned short UBaseType_t;
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) #if( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
@ -64,22 +64,21 @@ typedef unsigned short UBaseType_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section management. */ /* Critical section management. */
#define portENTER_CRITICAL() \ #define portENTER_CRITICAL() __asm{ pushf } \
__asm { pushf } \ __asm{ cli } \
__asm { cli } \
#define portEXIT_CRITICAL() __asm { popf } #define portEXIT_CRITICAL() __asm{ popf }
#define portDISABLE_INTERRUPTS() __asm { cli } #define portDISABLE_INTERRUPTS() __asm{ cli }
#define portENABLE_INTERRUPTS() __asm { sti } #define portENABLE_INTERRUPTS() __asm{ sti }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portNOP() __asm { nop } #define portNOP() __asm{ nop }
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portSWITCH_INT_NUMBER 0x80 #define portSWITCH_INT_NUMBER 0x80
#define portYIELD() __asm { int portSWITCH_INT_NUMBER } #define portYIELD() __asm{ int portSWITCH_INT_NUMBER }
#define portDOS_TICK_RATE ( 18.20648 ) #define portDOS_TICK_RATE ( 18.20648 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portTICKS_PER_DOS_TICK ( ( uint16_t ) ( ( ( portDOUBLE ) configTICK_RATE_HZ / portDOS_TICK_RATE ) + 0.5 ) ) #define portTICKS_PER_DOS_TICK ( ( uint16_t ) ( ( ( portDOUBLE ) configTICK_RATE_HZ / portDOS_TICK_RATE ) + 0.5 ) )
@ -94,7 +93,7 @@ typedef unsigned short UBaseType_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vTaskFunction, pvParameters ) void vTaskFunction( void * pvParameters ) #define portTASK_FUNCTION_PROTO( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters )
#define portTASK_FUNCTION( vTaskFunction, pvParameters ) void vTaskFunction( void * pvParameters ) #define portTASK_FUNCTION( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters )
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -48,16 +48,16 @@ void portSWITCH_CONTEXT( void );
void portFIRST_CONTEXT( void ); void portFIRST_CONTEXT( void );
/* There are slightly different versions depending on whether you are building /* There are slightly different versions depending on whether you are building
* to include debugger information. If debugger information is used then there to include debugger information. If debugger information is used then there
* are a couple of extra bytes left of the ISR stack (presumably for use by the are a couple of extra bytes left of the ISR stack (presumably for use by the
* debugger). The true stack pointer is then stored in the bp register. We add debugger). The true stack pointer is then stored in the bp register. We add
* 2 to the stack pointer to remove the extra bytes before we restore our context. */ 2 to the stack pointer to remove the extra bytes before we restore our context. */
#define portSWITCH_CONTEXT() \ #define portSWITCH_CONTEXT() \
asm { mov ax, seg pxCurrentTCB } \ asm { mov ax, seg pxCurrentTCB } \
asm { mov ds, ax } \ asm { mov ds, ax } \
asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */ \ asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */ \
asm { mov es : 0x2[ bx ], ss } \ asm { mov es:0x2[ bx ], ss } \
asm { mov es:[ bx ], sp } \ asm { mov es:[ bx ], sp } \
asm { call far ptr vTaskSwitchContext } /* Perform the switch. */ \ asm { call far ptr vTaskSwitchContext } /* Perform the switch. */ \
asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */ \ asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */ \
@ -84,4 +84,4 @@ void portFIRST_CONTEXT( void );
__asm { iret } __asm { iret }
#endif /* ifndef PORT_ASM_H */ #endif

View file

@ -27,16 +27,16 @@
*/ */
/* /*
* Changes from V1.00: Changes from V1.00:
*
+ pxPortInitialiseStack() now initialises the stack of new tasks to the + pxPortInitialiseStack() now initialises the stack of new tasks to the
+ same format used by the compiler. This allows the compiler generated same format used by the compiler. This allows the compiler generated
+ interrupt mechanism to be used for context switches. interrupt mechanism to be used for context switches.
+
+ Changes from V2.6.1 Changes from V2.6.1
+
+ Move usPortCheckFreeStackSpace() to tasks.c. + Move usPortCheckFreeStackSpace() to tasks.c.
*/ */
#include <dos.h> #include <dos.h>
@ -46,14 +46,12 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* See header file for description. */ /* See header file for description. */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
StackType_t DS_Reg = 0; StackType_t DS_Reg = 0;
/* Place a few bytes of known values on the bottom of the stack. /* Place a few bytes of known values on the bottom of the stack.
* This is just useful for debugging. */ This is just useful for debugging. */
*pxTopOfStack = 0x1111; *pxTopOfStack = 0x1111;
pxTopOfStack--; pxTopOfStack--;
@ -70,8 +68,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
/*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */ /*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */
/* We are going to start the scheduler using a return from interrupt /* We are going to start the scheduler using a return from interrupt
* instruction to load the program counter, so first there would be the instruction to load the program counter, so first there would be the
* function call with parameters preamble. */ function call with parameters preamble. */
*pxTopOfStack = FP_SEG( pvParameters ); *pxTopOfStack = FP_SEG( pvParameters );
pxTopOfStack--; pxTopOfStack--;
@ -91,8 +89,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* The remaining registers would be pushed on the stack by our context /* The remaining registers would be pushed on the stack by our context
* switch function. These are loaded with values simply to make debugging switch function. These are loaded with values simply to make debugging
* easier. */ easier. */
*pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */ *pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */ *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */
@ -105,9 +103,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* We need the true data segment. */ /* We need the true data segment. */
__asm { __asm{ MOV DS_Reg, DS };
MOV DS_Reg, DS
};
*pxTopOfStack = DS_Reg; /* DS */ *pxTopOfStack = DS_Reg; /* DS */
pxTopOfStack--; pxTopOfStack--;

View file

@ -81,7 +81,6 @@ add_library(freertos_kernel_port STATIC
# ARMv6-M / Cortex-M0 Raspberry PI RP2040 port for GCC # ARMv6-M / Cortex-M0 Raspberry PI RP2040 port for GCC
$<$<STREQUAL:${FREERTOS_PORT},GCC_RP2040>: $<$<STREQUAL:${FREERTOS_PORT},GCC_RP2040>:
ThirdParty/GCC/RP2040/idle_task_static_memory.c
ThirdParty/GCC/RP2040/port.c> ThirdParty/GCC/RP2040/port.c>
# ARMv7-M ports for GCC # ARMv7-M ports for GCC
@ -89,11 +88,13 @@ add_library(freertos_kernel_port STATIC
GCC/ARM_CM3/port.c> GCC/ARM_CM3/port.c>
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM3_MPU>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM3_MPU>:
GCC/ARM_CM3_MPU/port.c> GCC/ARM_CM3_MPU/port.c
GCC/ARM_CM3_MPU/mpu_wrappers_v2_asm.c>
# ARMv7E-M ports for GCC # ARMv7E-M ports for GCC
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM4_MPU>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM4_MPU>:
GCC/ARM_CM4_MPU/port.c> GCC/ARM_CM4_MPU/port.c
GCC/ARM_CM4_MPU/mpu_wrappers_v2_asm.c>
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM4F>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM4F>:
GCC/ARM_CM4F/port.c> GCC/ARM_CM4F/port.c>
@ -104,7 +105,8 @@ add_library(freertos_kernel_port STATIC
# ARMv8-M ports for GCC # ARMv8-M ports for GCC
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM23_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM23_NONSECURE>:
GCC/ARM_CM23/non_secure/port.c GCC/ARM_CM23/non_secure/port.c
GCC/ARM_CM23/non_secure/portasm.c> GCC/ARM_CM23/non_secure/portasm.c
GCC/ARM_CM23/non_secure/mpu_wrappers_v2_asm.c>
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM23_SECURE>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM23_SECURE>:
GCC/ARM_CM23/secure/secure_context_port.c GCC/ARM_CM23/secure/secure_context_port.c
@ -114,11 +116,13 @@ add_library(freertos_kernel_port STATIC
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM23_NTZ_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM23_NTZ_NONSECURE>:
GCC/ARM_CM23_NTZ/non_secure/port.c GCC/ARM_CM23_NTZ/non_secure/port.c
GCC/ARM_CM23_NTZ/non_secure/portasm.c> GCC/ARM_CM23_NTZ/non_secure/portasm.c
GCC/ARM_CM23_NTZ/non_secure/mpu_wrappers_v2_asm.c>
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM33_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM33_NONSECURE>:
GCC/ARM_CM33/non_secure/port.c GCC/ARM_CM33/non_secure/port.c
GCC/ARM_CM33/non_secure/portasm.c> GCC/ARM_CM33/non_secure/portasm.c
GCC/ARM_CM33/non_secure/mpu_wrappers_v2_asm.c>
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM33_SECURE>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM33_SECURE>:
GCC/ARM_CM33/secure/secure_context_port.c GCC/ARM_CM33/secure/secure_context_port.c
@ -128,16 +132,19 @@ add_library(freertos_kernel_port STATIC
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM33_NTZ_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM33_NTZ_NONSECURE>:
GCC/ARM_CM33_NTZ/non_secure/port.c GCC/ARM_CM33_NTZ/non_secure/port.c
GCC/ARM_CM33_NTZ/non_secure/portasm.c> GCC/ARM_CM33_NTZ/non_secure/portasm.c
GCC/ARM_CM33_NTZ/non_secure/mpu_wrappers_v2_asm.c>
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM33_TFM>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM33_TFM>:
GCC/ARM_CM33_NTZ/non_secure/port.c GCC/ARM_CM33_NTZ/non_secure/port.c
GCC/ARM_CM33_NTZ/non_secure/portasm.c GCC/ARM_CM33_NTZ/non_secure/portasm.c
GCC/ARM_CM33_NTZ/non_secure/mpu_wrappers_v2_asm.c
ThirdParty/GCC/ARM_TFM/os_wrapper_freertos.c> ThirdParty/GCC/ARM_TFM/os_wrapper_freertos.c>
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM35P_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM35P_NONSECURE>:
GCC/ARM_CM35P/non_secure/port.c GCC/ARM_CM35P/non_secure/port.c
GCC/ARM_CM35P/non_secure/portasm.c> GCC/ARM_CM35P/non_secure/portasm.c
GCC/ARM_CM35P/non_secure/mpu_wrappers_v2_asm.c>
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM35P_SECURE>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM35P_SECURE>:
GCC/ARM_CM35P/secure/secure_context_port.c GCC/ARM_CM35P/secure/secure_context_port.c
@ -147,12 +154,14 @@ add_library(freertos_kernel_port STATIC
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM35P_NTZ_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM35P_NTZ_NONSECURE>:
GCC/ARM_CM35P_NTZ/non_secure/port.c GCC/ARM_CM35P_NTZ/non_secure/port.c
GCC/ARM_CM35P_NTZ/non_secure/portasm.c> GCC/ARM_CM35P_NTZ/non_secure/portasm.c
GCC/ARM_CM35P_NTZ/non_secure/mpu_wrappers_v2_asm.c>
# ARMv8.1-M ports for GCC # ARMv8.1-M ports for GCC
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM55_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM55_NONSECURE>:
GCC/ARM_CM55/non_secure/port.c GCC/ARM_CM55/non_secure/port.c
GCC/ARM_CM55/non_secure/portasm.c> GCC/ARM_CM55/non_secure/portasm.c
GCC/ARM_CM55/non_secure/mpu_wrappers_v2_asm.c>
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM55_SECURE>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM55_SECURE>:
GCC/ARM_CM55/secure/secure_context_port.c GCC/ARM_CM55/secure/secure_context_port.c
@ -162,16 +171,19 @@ add_library(freertos_kernel_port STATIC
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM55_NTZ_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM55_NTZ_NONSECURE>:
GCC/ARM_CM55_NTZ/non_secure/port.c GCC/ARM_CM55_NTZ/non_secure/port.c
GCC/ARM_CM55_NTZ/non_secure/portasm.c> GCC/ARM_CM55_NTZ/non_secure/portasm.c
GCC/ARM_CM55_NTZ/non_secure/mpu_wrappers_v2_asm.c>
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM55_TFM>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM55_TFM>:
GCC/ARM_CM55_NTZ/non_secure/port.c GCC/ARM_CM55_NTZ/non_secure/port.c
GCC/ARM_CM55_NTZ/non_secure/portasm.c GCC/ARM_CM55_NTZ/non_secure/portasm.c
GCC/ARM_CM55_NTZ/non_secure/mpu_wrappers_v2_asm.c
ThirdParty/GCC/ARM_TFM/os_wrapper_freertos.c> ThirdParty/GCC/ARM_TFM/os_wrapper_freertos.c>
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM85_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM85_NONSECURE>:
GCC/ARM_CM85/non_secure/port.c GCC/ARM_CM85/non_secure/port.c
GCC/ARM_CM85/non_secure/portasm.c> GCC/ARM_CM85/non_secure/portasm.c
GCC/ARM_CM85/non_secure/mpu_wrappers_v2_asm.c>
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM85_SECURE>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM85_SECURE>:
GCC/ARM_CM85/secure/secure_context_port.c GCC/ARM_CM85/secure/secure_context_port.c
@ -181,11 +193,13 @@ add_library(freertos_kernel_port STATIC
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM85_NTZ_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM85_NTZ_NONSECURE>:
GCC/ARM_CM85_NTZ/non_secure/port.c GCC/ARM_CM85_NTZ/non_secure/port.c
GCC/ARM_CM85_NTZ/non_secure/portasm.c> GCC/ARM_CM85_NTZ/non_secure/portasm.c
GCC/ARM_CM85_NTZ/non_secure/mpu_wrappers_v2_asm.c>
$<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM85_TFM>: $<$<STREQUAL:${FREERTOS_PORT},GCC_ARM_CM85_TFM>:
GCC/ARM_CM85_NTZ/non_secure/port.c GCC/ARM_CM85_NTZ/non_secure/port.c
GCC/ARM_CM85_NTZ/non_secure/portasm.c GCC/ARM_CM85_NTZ/non_secure/portasm.c
GCC/ARM_CM85_NTZ/non_secure/mpu_wrappers_v2_asm.c
ThirdParty/GCC/ARM_TFM/os_wrapper_freertos.c> ThirdParty/GCC/ARM_TFM/os_wrapper_freertos.c>
# ARMv7-R ports for GCC # ARMv7-R ports for GCC
@ -392,7 +406,8 @@ add_library(freertos_kernel_port STATIC
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM4F_MPU>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM4F_MPU>:
IAR/ARM_CM4F_MPU/port.c IAR/ARM_CM4F_MPU/port.c
IAR/ARM_CM4F_MPU/portasm.s> IAR/ARM_CM4F_MPU/portasm.s
IAR/ARM_CM4F_MPU/mpu_wrappers_v2_asm.S>
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM7>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM7>:
IAR/ARM_CM7/r0p1/port.c IAR/ARM_CM7/r0p1/port.c
@ -401,7 +416,8 @@ add_library(freertos_kernel_port STATIC
# ARMv8-M Ports for IAR EWARM # ARMv8-M Ports for IAR EWARM
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM23_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM23_NONSECURE>:
IAR/ARM_CM23/non_secure/port.c IAR/ARM_CM23/non_secure/port.c
IAR/ARM_CM23/non_secure/portasm.s> IAR/ARM_CM23/non_secure/portasm.s
IAR/ARM_CM23/non_secure/mpu_wrappers_v2_asm.S>
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM23_SECURE>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM23_SECURE>:
IAR/ARM_CM23/secure/secure_context_port_asm.s IAR/ARM_CM23/secure/secure_context_port_asm.s
@ -411,11 +427,13 @@ add_library(freertos_kernel_port STATIC
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM23_NTZ_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM23_NTZ_NONSECURE>:
IAR/ARM_CM23_NTZ/non_secure/port.c IAR/ARM_CM23_NTZ/non_secure/port.c
IAR/ARM_CM23_NTZ/non_secure/portasm.s> IAR/ARM_CM23_NTZ/non_secure/portasm.s
IAR/ARM_CM23_NTZ/non_secure/mpu_wrappers_v2_asm.S>
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM33_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM33_NONSECURE>:
IAR/ARM_CM33/non_secure/port.c IAR/ARM_CM33/non_secure/port.c
IAR/ARM_CM33/non_secure/portasm.s> IAR/ARM_CM33/non_secure/portasm.s
IAR/ARM_CM33/non_secure/mpu_wrappers_v2_asm.S>
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM33_SECURE>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM33_SECURE>:
IAR/ARM_CM33/secure/secure_context_port_asm.s IAR/ARM_CM33/secure/secure_context_port_asm.s
@ -425,11 +443,13 @@ add_library(freertos_kernel_port STATIC
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM33_NTZ_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM33_NTZ_NONSECURE>:
IAR/ARM_CM33_NTZ/non_secure/port.c IAR/ARM_CM33_NTZ/non_secure/port.c
IAR/ARM_CM33_NTZ/non_secure/portasm.s> IAR/ARM_CM33_NTZ/non_secure/portasm.s
IAR/ARM_CM33_NTZ/non_secure/mpu_wrappers_v2_asm.S>
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM35P_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM35P_NONSECURE>:
IAR/ARM_CM35P/non_secure/port.c IAR/ARM_CM35P/non_secure/port.c
IAR/ARM_CM35P/non_secure/portasm.s> IAR/ARM_CM35P/non_secure/portasm.s
IAR/ARM_CM35P/non_secure/mpu_wrappers_v2_asm.S>
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM35P_SECURE>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM35P_SECURE>:
IAR/ARM_CM35P/secure/secure_context_port_asm.s IAR/ARM_CM35P/secure/secure_context_port_asm.s
@ -439,12 +459,14 @@ add_library(freertos_kernel_port STATIC
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM35P_NTZ_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM35P_NTZ_NONSECURE>:
IAR/ARM_CM35P_NTZ/non_secure/port.c IAR/ARM_CM35P_NTZ/non_secure/port.c
IAR/ARM_CM35P_NTZ/non_secure/portasm.s> IAR/ARM_CM35P_NTZ/non_secure/portasm.s
IAR/ARM_CM35P_NTZ/non_secure/mpu_wrappers_v2_asm.S>
# ARMv8.1-M ports for IAR EWARM # ARMv8.1-M ports for IAR EWARM
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM55_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM55_NONSECURE>:
IAR/ARM_CM55/non_secure/port.c IAR/ARM_CM55/non_secure/port.c
IAR/ARM_CM55/non_secure/portasm.s> IAR/ARM_CM55/non_secure/portasm.s
IAR/ARM_CM55/non_secure/mpu_wrappers_v2_asm.S>
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM55_SECURE>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM55_SECURE>:
IAR/ARM_CM55/secure/secure_context_port_asm.s IAR/ARM_CM55/secure/secure_context_port_asm.s
@ -454,11 +476,13 @@ add_library(freertos_kernel_port STATIC
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM55_NTZ_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM55_NTZ_NONSECURE>:
IAR/ARM_CM55_NTZ/non_secure/port.c IAR/ARM_CM55_NTZ/non_secure/port.c
IAR/ARM_CM55_NTZ/non_secure/portasm.s> IAR/ARM_CM55_NTZ/non_secure/portasm.s
IAR/ARM_CM55_NTZ/non_secure/mpu_wrappers_v2_asm.S>
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM85_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM85_NONSECURE>:
IAR/ARM_CM85/non_secure/port.c IAR/ARM_CM85/non_secure/port.c
IAR/ARM_CM85/non_secure/portasm.s> IAR/ARM_CM85/non_secure/portasm.s
IAR/ARM_CM85/non_secure/mpu_wrappers_v2_asm.S>
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM85_SECURE>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM85_SECURE>:
IAR/ARM_CM85/secure/secure_context_port_asm.s IAR/ARM_CM85/secure/secure_context_port_asm.s
@ -468,7 +492,8 @@ add_library(freertos_kernel_port STATIC
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM85_NTZ_NONSECURE>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CM85_NTZ_NONSECURE>:
IAR/ARM_CM85_NTZ/non_secure/port.c IAR/ARM_CM85_NTZ/non_secure/port.c
IAR/ARM_CM85_NTZ/non_secure/portasm.s> IAR/ARM_CM85_NTZ/non_secure/portasm.s
IAR/ARM_CM85_NTZ/non_secure/mpu_wrappers_v2_asm.S>
# ARMv7-R Ports for IAR EWARM # ARMv7-R Ports for IAR EWARM
$<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CRX_NOGIC>: $<$<STREQUAL:${FREERTOS_PORT},IAR_ARM_CRX_NOGIC>:
@ -660,7 +685,8 @@ add_library(freertos_kernel_port STATIC
# ARMv7E-M ports for ARM RVDS / armcc # ARMv7E-M ports for ARM RVDS / armcc
$<$<STREQUAL:${FREERTOS_PORT},RVDS_ARM_CM4_MPU>: $<$<STREQUAL:${FREERTOS_PORT},RVDS_ARM_CM4_MPU>:
RVDS/ARM_CM4_MPU/port.c> RVDS/ARM_CM4_MPU/port.c
RVDS/ARM_CM4_MPU/mpu_wrappers_v2_asm.c>
$<$<STREQUAL:${FREERTOS_PORT},RVDS_ARM_CM4F>: $<$<STREQUAL:${FREERTOS_PORT},RVDS_ARM_CM4F>:
RVDS/ARM_CM4F/port.c> RVDS/ARM_CM4F/port.c>
@ -724,7 +750,10 @@ if( FREERTOS_PORT MATCHES "GCC_ARM_CM(3|4)_MPU" OR
FREERTOS_PORT MATCHES "IAR_ARM_CM(23|33|55|85)_NTZ_NONSECURE" OR FREERTOS_PORT MATCHES "IAR_ARM_CM(23|33|55|85)_NTZ_NONSECURE" OR
FREERTOS_PORT MATCHES "IAR_ARM_CM(23|33|55|85)_NONSECURE" FREERTOS_PORT MATCHES "IAR_ARM_CM(23|33|55|85)_NONSECURE"
) )
target_sources(freertos_kernel_port PRIVATE Common/mpu_wrappers.c) target_sources(freertos_kernel_port PRIVATE
Common/mpu_wrappers.c
Common/mpu_wrappers_v2.c
)
endif() endif()
target_include_directories(freertos_kernel_port PUBLIC target_include_directories(freertos_kernel_port PUBLIC

View file

@ -34,7 +34,7 @@
#define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 ) #define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 )
/* Supervisor mode set. */ /* Supervisor mode set. */
#define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000 ) #define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000)
/* The clock prescale into the timer peripheral. */ /* The clock prescale into the timer peripheral. */
#define portPRESCALE_VALUE ( ( uint8_t ) 10 ) #define portPRESCALE_VALUE ( ( uint8_t ) 10 )
@ -46,23 +46,20 @@ asm void interrupt VectorNumber_VL1swi vPortYieldISR( void );
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
/* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This /* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This
* will be set to 0 prior to the first task being started. */ will be set to 0 prior to the first task being started. */
static uint32_t ulCriticalNesting = 0x9999UL; static uint32_t ulCriticalNesting = 0x9999UL;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
uint32_t ulOriginalA5;
__asm { uint32_t ulOriginalA5;
MOVE.L A5, ulOriginalA5
}; __asm{ MOVE.L A5, ulOriginalA5 };
*pxTopOfStack = ( StackType_t ) 0xDEADBEEF; *pxTopOfStack = (StackType_t) 0xDEADBEEF;
pxTopOfStack--; pxTopOfStack--;
/* Exception stack frame starts with the return address. */ /* Exception stack frame starts with the return address. */
@ -87,7 +84,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
extern void vPortStartFirstTask( void ); extern void vPortStartFirstTask( void );
ulCriticalNesting = 0UL; ulCriticalNesting = 0UL;
@ -110,7 +107,7 @@ static void prvSetupTimerInterrupt( void )
RTCMOD = portRTC_CLOCK_HZ / configTICK_RATE_HZ; RTCMOD = portRTC_CLOCK_HZ / configTICK_RATE_HZ;
/* Enable the RTC to generate interrupts - interrupts are already disabled /* Enable the RTC to generate interrupts - interrupts are already disabled
* when this code executes. */ when this code executes. */
RTCSC_RTIE = 1; RTCSC_RTIE = 1;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -126,20 +123,19 @@ void vPortEnterCritical( void )
if( ulCriticalNesting == 0UL ) if( ulCriticalNesting == 0UL )
{ {
/* Guard against context switches being pended simultaneously with a /* Guard against context switches being pended simultaneously with a
* critical section being entered. */ critical section being entered. */
do do
{ {
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
if( INTC_FRC == 0UL ) if( INTC_FRC == 0UL )
{ {
break; break;
} }
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} while( 1 ); } while( 1 );
} }
ulCriticalNesting++; ulCriticalNesting++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -147,7 +143,6 @@ void vPortEnterCritical( void )
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
ulCriticalNesting--; ulCriticalNesting--;
if( ulCriticalNesting == 0 ) if( ulCriticalNesting == 0 )
{ {
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
@ -157,7 +152,7 @@ void vPortExitCritical( void )
void vPortYieldHandler( void ) void vPortYieldHandler( void )
{ {
uint32_t ulSavedInterruptMask; uint32_t ulSavedInterruptMask;
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR(); ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
{ {
@ -171,7 +166,7 @@ void vPortYieldHandler( void )
void interrupt VectorNumber_Vrtc vPortTickISR( void ) void interrupt VectorNumber_Vrtc vPortTickISR( void )
{ {
uint32_t ulSavedInterruptMask; uint32_t ulSavedInterruptMask;
/* Clear the interrupt. */ /* Clear the interrupt. */
RTCSC |= RTCSC_RTIF_MASK; RTCSC |= RTCSC_RTIF_MASK;

View file

@ -59,7 +59,7 @@ typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) #if( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
@ -102,10 +102,11 @@ extern void vPortClearInterruptMaskFromISR( UBaseType_t );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) __attribute__( ( noreturn ) ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) __attribute__((noreturn))
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portEND_SWITCHING_ISR( xSwitchRequired ) \ #define portEND_SWITCHING_ISR( xSwitchRequired ) \
do \ do \
{ \ { \

View file

@ -34,38 +34,36 @@
#define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 ) #define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 )
/* Supervisor mode set. */ /* Supervisor mode set. */
#define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000 ) #define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000)
/* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This /* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This
* will be set to 0 prior to the first task being started. */ will be set to 0 prior to the first task being started. */
static uint32_t ulCriticalNesting = 0x9999UL; static uint32_t ulCriticalNesting = 0x9999UL;
#define portSAVE_CONTEXT() \ #define portSAVE_CONTEXT() \
lea.l( -60, % sp ), % sp; \ lea.l (-60, %sp), %sp; \
movem.l % d0 - % fp, ( % sp ); \ movem.l %d0-%fp, (%sp); \
move.l pxCurrentTCB, % a0; \ move.l pxCurrentTCB, %a0; \
move.l % sp, ( % a0 ); move.l %sp, (%a0);
#define portRESTORE_CONTEXT() \ #define portRESTORE_CONTEXT() \
move.l pxCurrentTCB, % a0; \ move.l pxCurrentTCB, %a0; \
move.l( % a0 ), % sp; \ move.l (%a0), %sp; \
movem.l( % sp ), % d0 - % fp; \ movem.l (%sp), %d0-%fp; \
lea.l % sp@( 60 ), % sp; \ lea.l %sp@(60), %sp; \
rte rte
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
*pxTopOfStack = ( StackType_t ) pvParameters; *pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xDEADBEEF; *pxTopOfStack = (StackType_t) 0xDEADBEEF;
pxTopOfStack--; pxTopOfStack--;
/* Exception stack frame starts with the return address. */ /* Exception stack frame starts with the return address. */
@ -84,7 +82,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
extern void vPortStartFirstTask( void ); extern void vPortStartFirstTask( void );
ulCriticalNesting = 0UL; ulCriticalNesting = 0UL;
@ -109,20 +107,19 @@ void vPortEnterCritical( void )
if( ulCriticalNesting == 0UL ) if( ulCriticalNesting == 0UL )
{ {
/* Guard against context switches being pended simultaneously with a /* Guard against context switches being pended simultaneously with a
* critical section being entered. */ critical section being entered. */
do do
{ {
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
if( MCF_INTC0_INTFRCH == 0UL ) if( MCF_INTC0_INTFRCH == 0UL )
{ {
break; break;
} }
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} while( 1 ); } while( 1 );
} }
ulCriticalNesting++; ulCriticalNesting++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -130,7 +127,6 @@ void vPortEnterCritical( void )
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
ulCriticalNesting--; ulCriticalNesting--;
if( ulCriticalNesting == 0 ) if( ulCriticalNesting == 0 )
{ {
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
@ -140,7 +136,7 @@ void vPortExitCritical( void )
void vPortYieldHandler( void ) void vPortYieldHandler( void )
{ {
uint32_t ulSavedInterruptMask; uint32_t ulSavedInterruptMask;
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR(); ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
/* Note this will clear all forced interrupts - this is done for speed. */ /* Note this will clear all forced interrupts - this is done for speed. */

View file

@ -58,7 +58,7 @@ typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) #if( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
@ -101,8 +101,8 @@ extern void vPortClearInterruptMaskFromISR( UBaseType_t );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) __attribute__( ( noreturn ) ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) __attribute__((noreturn))
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portEND_SWITCHING_ISR( xSwitchRequired ) \ #define portEND_SWITCHING_ISR( xSwitchRequired ) \

View file

@ -32,8 +32,8 @@
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the HCS12 port. * Implementation of functions defined in portable.h for the HCS12 port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* /*
@ -43,29 +43,29 @@
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
/* Interrupt service routines have to be in non-banked memory - as does the /* Interrupt service routines have to be in non-banked memory - as does the
* scheduler startup function. */ scheduler startup function. */
#pragma CODE_SEG __NEAR_SEG NON_BANKED #pragma CODE_SEG __NEAR_SEG NON_BANKED
/* Manual context switch function. This is the SWI ISR. */ /* Manual context switch function. This is the SWI ISR. */
void interrupt vPortYield( void ); void interrupt vPortYield( void );
/* Tick context switch function. This is the timer ISR. */ /* Tick context switch function. This is the timer ISR. */
void interrupt vPortTickInterrupt( void ); void interrupt vPortTickInterrupt( void );
/* Simply called by xPortStartScheduler(). xPortStartScheduler() does not /* Simply called by xPortStartScheduler(). xPortStartScheduler() does not
* start the scheduler directly because the header file containing the start the scheduler directly because the header file containing the
* xPortStartScheduler() prototype is part of the common kernel code, and xPortStartScheduler() prototype is part of the common kernel code, and
* therefore cannot use the CODE_SEG pragma. */ therefore cannot use the CODE_SEG pragma. */
static BaseType_t xBankedStartScheduler( void ); static BaseType_t xBankedStartScheduler( void );
#pragma CODE_SEG DEFAULT #pragma CODE_SEG DEFAULT
/* Calls to portENTER_CRITICAL() can be nested. When they are nested the /* Calls to portENTER_CRITICAL() can be nested. When they are nested the
* critical section should not be left (i.e. interrupts should not be re-enabled) critical section should not be left (i.e. interrupts should not be re-enabled)
* until the nesting depth reaches 0. This variable simply tracks the nesting until the nesting depth reaches 0. This variable simply tracks the nesting
* depth. Each task maintains it's own critical nesting depth variable so depth. Each task maintains it's own critical nesting depth variable so
* uxCriticalNesting is saved and restored from the task stack during a context uxCriticalNesting is saved and restored from the task stack during a context
* switch. */ switch. */
volatile UBaseType_t uxCriticalNesting = 0xff; volatile UBaseType_t uxCriticalNesting = 0xff;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -73,33 +73,31 @@ volatile UBaseType_t uxCriticalNesting = 0xff;
/* /*
* See header file for description. * See header file for description.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
/* /*
* Place a few bytes of known values on the bottom of the stack. Place a few bytes of known values on the bottom of the stack.
* This can be uncommented to provide useful stack markers when debugging. This can be uncommented to provide useful stack markers when debugging.
*
* pxTopOfStack = ( StackType_t ) 0x11; *pxTopOfStack = ( StackType_t ) 0x11;
* pxTopOfStack--; pxTopOfStack--;
* pxTopOfStack = ( StackType_t ) 0x22; *pxTopOfStack = ( StackType_t ) 0x22;
* pxTopOfStack--; pxTopOfStack--;
* pxTopOfStack = ( StackType_t ) 0x33; *pxTopOfStack = ( StackType_t ) 0x33;
* pxTopOfStack--; pxTopOfStack--;
*/ */
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
* expected by the portRESTORE_CONTEXT() macro. In this case the stack as expected by the portRESTORE_CONTEXT() macro. In this case the stack as
* expected by the HCS12 RTI instruction. */ expected by the HCS12 RTI instruction. */
/* The address of the task function is placed in the stack byte at a time. */ /* The address of the task function is placed in the stack byte at a time. */
*pxTopOfStack = ( StackType_t ) *( ( ( StackType_t * ) ( &pxCode ) ) + 1 ); *pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pxCode) ) + 1 );
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) *( ( ( StackType_t * ) ( &pxCode ) ) + 0 ); *pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pxCode) ) + 0 );
pxTopOfStack--; pxTopOfStack--;
/* Next are all the registers that form part of the task context. */ /* Next are all the registers that form part of the task context. */
@ -117,15 +115,15 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* A register contains parameter high byte. */ /* A register contains parameter high byte. */
*pxTopOfStack = ( StackType_t ) *( ( ( StackType_t * ) ( &pvParameters ) ) + 0 ); *pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 0 );
pxTopOfStack--; pxTopOfStack--;
/* B register contains parameter low byte. */ /* B register contains parameter low byte. */
*pxTopOfStack = ( StackType_t ) *( ( ( StackType_t * ) ( &pvParameters ) ) + 1 ); *pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 1 );
pxTopOfStack--; pxTopOfStack--;
/* CCR: Note that when the task starts interrupts will be enabled since /* CCR: Note that when the task starts interrupts will be enabled since
* "I" bit of CCR is cleared */ "I" bit of CCR is cleared */
*pxTopOfStack = ( StackType_t ) 0x00; *pxTopOfStack = ( StackType_t ) 0x00;
pxTopOfStack--; pxTopOfStack--;
@ -136,7 +134,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
#endif #endif
/* Finally the critical nesting depth is initialised with 0 (not within /* Finally the critical nesting depth is initialised with 0 (not within
* a critical section). */ a critical section). */
*pxTopOfStack = ( StackType_t ) 0x00; *pxTopOfStack = ( StackType_t ) 0x00;
return pxTopOfStack; return pxTopOfStack;
@ -159,10 +157,10 @@ static void prvSetupTimerInterrupt( void )
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* xPortStartScheduler() does not start the scheduler directly because /* xPortStartScheduler() does not start the scheduler directly because
* the header file containing the xPortStartScheduler() prototype is part the header file containing the xPortStartScheduler() prototype is part
* of the common kernel code, and therefore cannot use the CODE_SEG pragma. of the common kernel code, and therefore cannot use the CODE_SEG pragma.
* Instead it simply calls the locally defined xBankedStartScheduler() - Instead it simply calls the locally defined xBankedStartScheduler() -
* which does use the CODE_SEG pragma. */ which does use the CODE_SEG pragma. */
return xBankedStartScheduler(); return xBankedStartScheduler();
} }
@ -173,7 +171,7 @@ BaseType_t xPortStartScheduler( void )
static BaseType_t xBankedStartScheduler( void ) static BaseType_t xBankedStartScheduler( void )
{ {
/* Configure the timer that will generate the RTOS tick. Interrupts are /* Configure the timer that will generate the RTOS tick. Interrupts are
* disabled when this function is called. */ disabled when this function is called. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Restore the context of the first task. */ /* Restore the context of the first task. */
@ -224,15 +222,15 @@ void interrupt vPortTickInterrupt( void )
TFLG1 = 1; TFLG1 = 1;
/* Restore the context of a task - which may be a different task /* Restore the context of a task - which may be a different task
* to that interrupted. */ to that interrupted. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
} }
#else /* if configUSE_PREEMPTION == 1 */ #else
{ {
xTaskIncrementTick(); xTaskIncrementTick();
TFLG1 = 1; TFLG1 = 1;
} }
#endif /* if configUSE_PREEMPTION == 1 */ #endif
} }
#pragma CODE_SEG DEFAULT #pragma CODE_SEG DEFAULT

View file

@ -53,7 +53,7 @@ typedef portSTACK_TYPE StackType_t;
typedef signed char BaseType_t; typedef signed char BaseType_t;
typedef unsigned char UBaseType_t; typedef unsigned char UBaseType_t;
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) #if( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
@ -83,12 +83,12 @@ typedef unsigned char UBaseType_t;
* directly. Each task maintains its own nesting count. * directly. Each task maintains its own nesting count.
*/ */
#define portENTER_CRITICAL() \ #define portENTER_CRITICAL() \
{ \ { \
extern volatile UBaseType_t uxCriticalNesting; \ extern volatile UBaseType_t uxCriticalNesting; \
\ \
portDISABLE_INTERRUPTS(); \ portDISABLE_INTERRUPTS(); \
uxCriticalNesting++; \ uxCriticalNesting++; \
} }
/* /*
* Interrupts are disabled so we can access the nesting count directly. If the * Interrupts are disabled so we can access the nesting count directly. If the
@ -96,7 +96,7 @@ typedef unsigned char UBaseType_t;
* section and interrupts can be re-enabled. * section and interrupts can be re-enabled.
*/ */
#define portEXIT_CRITICAL() \ #define portEXIT_CRITICAL() \
{ \ { \
extern volatile UBaseType_t uxCriticalNesting; \ extern volatile UBaseType_t uxCriticalNesting; \
\ \
uxCriticalNesting--; \ uxCriticalNesting--; \
@ -104,7 +104,7 @@ typedef unsigned char UBaseType_t;
{ \ { \
portENABLE_INTERRUPTS(); \ portENABLE_INTERRUPTS(); \
} \ } \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
@ -120,8 +120,7 @@ typedef unsigned char UBaseType_t;
*/ */
#ifdef BANKED_MODEL #ifdef BANKED_MODEL
/*
/*
* Load the stack pointer for the task, then pull the critical nesting * Load the stack pointer for the task, then pull the critical nesting
* count and PPAGE register from the stack. The remains of the * count and PPAGE register from the stack. The remains of the
* context are restored by the RTI instruction. * context are restored by the RTI instruction.
@ -139,7 +138,7 @@ typedef unsigned char UBaseType_t;
__asm( "staa 0x30" ); /* 0x30 = PPAGE */ \ __asm( "staa 0x30" ); /* 0x30 = PPAGE */ \
} }
/* /*
* By the time this macro is called the processor has already stacked the * By the time this macro is called the processor has already stacked the
* registers. Simply stack the nesting count and PPAGE value, then save * registers. Simply stack the nesting count and PPAGE value, then save
* the task stack pointer. * the task stack pointer.
@ -156,9 +155,9 @@ typedef unsigned char UBaseType_t;
__asm( "ldx pxCurrentTCB" ); \ __asm( "ldx pxCurrentTCB" ); \
__asm( "sts 0, x" ); \ __asm( "sts 0, x" ); \
} }
#else /* ifdef BANKED_MODEL */ #else
/* /*
* These macros are as per the BANKED versions above, but without saving * These macros are as per the BANKED versions above, but without saving
* and restoring the PPAGE register. * and restoring the PPAGE register.
*/ */
@ -184,7 +183,7 @@ typedef unsigned char UBaseType_t;
__asm( "ldx pxCurrentTCB" ); \ __asm( "ldx pxCurrentTCB" ); \
__asm( "sts 0, x" ); \ __asm( "sts 0, x" ); \
} }
#endif /* ifdef BANKED_MODEL */ #endif
/* /*
* Utility macro to call macros above in correct order in order to perform a * Utility macro to call macros above in correct order in order to perform a
@ -199,7 +198,7 @@ typedef unsigned char UBaseType_t;
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -75,9 +75,9 @@
/* Save the floating point context, if any. */ /* Save the floating point context, if any. */
FMRXNE R1, FPSCR FMRXNE R1, FPSCR
PUSHNE {R1}
VPUSHNE {D0-D15} VPUSHNE {D0-D15}
VPUSHNE {D16-D31} VPUSHNE {D16-D31}
PUSHNE {R1}
/* Save ulPortTaskHasFPUContext itself. */ /* Save ulPortTaskHasFPUContext itself. */
PUSH {R3} PUSH {R3}
@ -106,9 +106,9 @@
CMP R1, #0 CMP R1, #0
/* Restore the floating point context, if any. */ /* Restore the floating point context, if any. */
POPNE {R0}
VPOPNE {D16-D31} VPOPNE {D16-D31}
VPOPNE {D0-D15} VPOPNE {D0-D15}
POPNE {R0}
VMSRNE FPSCR, R0 VMSRNE FPSCR, R0
/* Restore the critical section nesting depth. */ /* Restore the critical section nesting depth. */
@ -145,8 +145,15 @@
FreeRTOS_SWI_Handler: FreeRTOS_SWI_Handler:
/* Save the context of the current task and select a new task to run. */ /* Save the context of the current task and select a new task to run. */
portSAVE_CONTEXT portSAVE_CONTEXT
/* Ensure bit 2 of the stack pointer is clear. */
MOV r2, sp
AND r2, r2, #4
SUB sp, sp, r2
LDR R0, vTaskSwitchContextConst LDR R0, vTaskSwitchContextConst
BLX R0 BLX R0
portRESTORE_CONTEXT portRESTORE_CONTEXT
@ -256,7 +263,13 @@ switch_before_exit:
/* Call the function that selects the new task to execute. /* Call the function that selects the new task to execute.
vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD
instructions, or 8 byte aligned stack allocated data. LR does not need instructions, or 8 byte aligned stack allocated data. LR does not need
saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */ saving as a new LR will be loaded by portRESTORE_CONTEXT anyway.
Ensure bit 2 of the stack pointer is clear. r2 holds the bit 2 value for
future use. */
MOV r2, sp
AND r2, r2, #4
SUB sp, sp, r2
LDR R0, vTaskSwitchContextConst LDR R0, vTaskSwitchContextConst
BLX R0 BLX R0

View file

@ -34,6 +34,9 @@
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
/* Prototype of all Interrupt Service Routines (ISRs). */
typedef void ( * portISR_t )( void );
/* Constants required to manipulate the NVIC. */ /* Constants required to manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
@ -51,6 +54,10 @@
#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL ) #define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL ) #define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
/* Constants used to check the installation of the FreeRTOS interrupt handlers. */
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portVECTOR_INDEX_PENDSV ( 14 )
/* Constants required to set up the initial stack. */ /* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 ) #define portINITIAL_XPSR ( 0x01000000 )
@ -200,9 +207,9 @@ void vPortSVCHandler( void )
void vPortStartFirstTask( void ) void vPortStartFirstTask( void )
{ {
/* The MSP stack is not reset as, unlike on M3/4 parts, there is no vector /* Don't reset the MSP stack as is done on CM3/4 devices. The vector table
* table offset register that can be used to locate the initial stack value. * in some CM0 devices cannot be modified and thus may not hold the
* Not all M0 parts have the application vector table at address 0. */ * application's initial MSP value. */
__asm volatile ( __asm volatile (
" .syntax unified \n" " .syntax unified \n"
" ldr r2, pxCurrentTCBConst2 \n" /* Obtain location of pxCurrentTCB. */ " ldr r2, pxCurrentTCBConst2 \n" /* Obtain location of pxCurrentTCB. */
@ -231,7 +238,42 @@ void vPortStartFirstTask( void )
*/ */
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the function xPortPendSVHandler for PendSV
* interrupt.
* 2. Indirect Routing - Install separate handler for PendSV interrupt and
* route program control from that handler to xPortPendSVHandler function.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
/* Point pxVectorTable to the interrupt vector table. Systems without
* a VTOR register provide the value zero in the VTOR register and
* the vector table itself is located at the address 0x00000000. */
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handler for PendSV interrupt. We do not check the installation of the
* SysTick handler because the application may choose to drive the RTOS
* tick using a timer other than the SysTick timer by overriding the
* weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handler. For help installing the FreeRTOS handler, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == xPortPendSVHandler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
/* Make PendSV and SysTick the lowest priority interrupts. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -34,10 +34,14 @@
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
/* Prototype of all Interrupt Service Routines (ISRs). */
typedef void ( * portISR_t )( void );
/* Constants required to manipulate the core. Registers first... */ /* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xe000ed1c ) )
#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) #define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
/* ...then bits in the registers. */ /* ...then bits in the registers. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
@ -52,6 +56,11 @@
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL )
/* Constants used to check the installation of the FreeRTOS interrupt handlers. */
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xE000ED08 ) )
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/* Constants required to check the validity of an interrupt priority. */ /* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
@ -259,6 +268,40 @@ static void prvPortStartFirstTask( void )
*/ */
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions vPortSVCHandler and
* xPortPendSVHandler for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* vPortSVCHandler and xPortPendSVHandler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == vPortSVCHandler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == xPortPendSVHandler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
volatile uint8_t ucOriginalPriority; volatile uint8_t ucOriginalPriority;
@ -343,9 +386,11 @@ BaseType_t xPortStartScheduler( void )
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* Make PendSV and SysTick the lowest priority interrupts. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
* here already. */ * here already. */

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -58,6 +58,9 @@
#define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 1 #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 1
#endif #endif
/* Prototype of all Interrupt Service Routines (ISRs). */
typedef void ( * portISR_t )( void );
/* Constants required to access and manipulate the NVIC. */ /* Constants required to access and manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
@ -87,7 +90,6 @@
#define portMIN_INTERRUPT_PRIORITY ( 255UL ) #define portMIN_INTERRUPT_PRIORITY ( 255UL )
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL )
#define portNVIC_SVC_PRI ( ( ( uint32_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL ) << 24UL )
/* Constants required to set up the initial stack. */ /* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 ) #define portINITIAL_XPSR ( 0x01000000 )
@ -95,6 +97,11 @@
#define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 ) #define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 )
#define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 ) #define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 )
/* Constants used to check the installation of the FreeRTOS interrupt handlers. */
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xE000ED08 ) )
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/* Constants required to check the validity of an interrupt priority. */ /* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
@ -414,7 +421,6 @@ void vSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
switch( ucSVCNumber ) switch( ucSVCNumber )
{ {
case portSVC_START_SCHEDULER: case portSVC_START_SCHEDULER:
portNVIC_SHPR2_REG |= portNVIC_SVC_PRI;
prvRestoreContextOfFirstTask(); prvRestoreContextOfFirstTask();
break; break;
@ -737,6 +743,40 @@ static void prvRestoreContextOfFirstTask( void )
*/ */
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions vPortSVCHandler and
* xPortPendSVHandler for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* vPortSVCHandler and xPortPendSVHandler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == vPortSVCHandler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == xPortPendSVHandler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
volatile uint8_t ucOriginalPriority; volatile uint8_t ucOriginalPriority;
@ -821,11 +861,12 @@ BaseType_t xPortStartScheduler( void )
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* Make PendSV and SysTick the same priority as the kernel, and the SVC /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* handler higher priority so it can be used to exit a critical section (where * the highest priority. */
* lower priorities are masked). */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
/* Configure the regions in the MPU that are common to all tasks. */ /* Configure the regions in the MPU that are common to all tasks. */
prvSetupMPU(); prvSetupMPU();
@ -1054,12 +1095,28 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void )
static void prvSetupMPU( void ) static void prvSetupMPU( void )
{ {
#if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */
extern uint32_t * __privileged_functions_start__;
extern uint32_t * __privileged_functions_end__;
extern uint32_t * __FLASH_segment_start__;
extern uint32_t * __FLASH_segment_end__;
extern uint32_t * __privileged_data_start__;
extern uint32_t * __privileged_data_end__;
#else
/* Declaration when these variable are exported from linker scripts. */
extern uint32_t __privileged_functions_start__[]; extern uint32_t __privileged_functions_start__[];
extern uint32_t __privileged_functions_end__[]; extern uint32_t __privileged_functions_end__[];
extern uint32_t __FLASH_segment_start__[]; extern uint32_t __FLASH_segment_start__[];
extern uint32_t __FLASH_segment_end__[]; extern uint32_t __FLASH_segment_end__[];
extern uint32_t __privileged_data_start__[]; extern uint32_t __privileged_data_start__[];
extern uint32_t __privileged_data_end__[]; extern uint32_t __privileged_data_end__[];
#endif /* if defined( __ARMCC_VERSION ) */
/* Ensure that the device has the expected MPU type */
configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
/* Check the expected MPU is present. */ /* Check the expected MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE ) if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
@ -1188,10 +1245,22 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
StackType_t * pxBottomOfStack, StackType_t * pxBottomOfStack,
uint32_t ulStackDepth ) uint32_t ulStackDepth )
{ {
#if defined( __ARMCC_VERSION )
/* Declaration when these variable are defined in code instead of being
* exported from linker scripts. */
extern uint32_t * __SRAM_segment_start__;
extern uint32_t * __SRAM_segment_end__;
extern uint32_t * __privileged_data_start__;
extern uint32_t * __privileged_data_end__;
#else
/* Declaration when these variable are exported from linker scripts. */
extern uint32_t __SRAM_segment_start__[]; extern uint32_t __SRAM_segment_start__[];
extern uint32_t __SRAM_segment_end__[]; extern uint32_t __SRAM_segment_end__[];
extern uint32_t __privileged_data_start__[]; extern uint32_t __privileged_data_start__[];
extern uint32_t __privileged_data_end__[]; extern uint32_t __privileged_data_end__[];
#endif /* if defined( __ARMCC_VERSION ) */
int32_t lIndex; int32_t lIndex;
uint32_t ul; uint32_t ul;
@ -1311,7 +1380,15 @@ BaseType_t xPortIsAuthorizedToAccessBuffer( const void * pvBuffer,
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -86,6 +86,15 @@ typedef unsigned long UBaseType_t;
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL ) #define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL ) #define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
/* MPU settings that can be overriden in FreeRTOSConfig.h. */
#ifndef configTOTAL_MPU_REGIONS
/* Define to 8 for backward compatibility. */
#define configTOTAL_MPU_REGIONS ( 8UL )
#elif( configTOTAL_MPU_REGIONS != 8UL )
/* The Cortex M3 only supports 8 MPU regions. For more information refer to:
* https://developer.arm.com/documentation/dui0552/a/cortex-m3-peripherals/optional-memory-protection-unit */
#error configTOTAL_MPU_REGIONS must be 8 for this port.
#endif /* configTOTAL_MPU_REGIONS Check */
#define portSTACK_REGION ( 3UL ) #define portSTACK_REGION ( 3UL )
#define portGENERAL_PERIPHERALS_REGION ( 4UL ) #define portGENERAL_PERIPHERALS_REGION ( 4UL )
#define portUNPRIVILEGED_FLASH_REGION ( 5UL ) #define portUNPRIVILEGED_FLASH_REGION ( 5UL )

View file

@ -38,10 +38,14 @@
#error This port can only be used when the project options are configured to enable hardware floating point support. #error This port can only be used when the project options are configured to enable hardware floating point support.
#endif #endif
/* Prototype of all Interrupt Service Routines (ISRs). */
typedef void ( * portISR_t )( void );
/* Constants required to manipulate the core. Registers first... */ /* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xe000ed1c ) )
#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) #define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
/* ...then bits in the registers. */ /* ...then bits in the registers. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
@ -62,6 +66,11 @@
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL )
/* Constants used to check the installation of the FreeRTOS interrupt handlers. */
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xE000ED08 ) )
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/* Constants required to check the validity of an interrupt priority. */ /* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
@ -302,6 +311,40 @@ BaseType_t xPortStartScheduler( void )
configASSERT( portCPUID != portCORTEX_M7_r0p1_ID ); configASSERT( portCPUID != portCORTEX_M7_r0p1_ID );
configASSERT( portCPUID != portCORTEX_M7_r0p0_ID ); configASSERT( portCPUID != portCORTEX_M7_r0p0_ID );
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions vPortSVCHandler and
* xPortPendSVHandler for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* vPortSVCHandler and xPortPendSVHandler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == vPortSVCHandler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == xPortPendSVHandler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
volatile uint8_t ucOriginalPriority; volatile uint8_t ucOriginalPriority;
@ -386,9 +429,11 @@ BaseType_t xPortStartScheduler( void )
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* Make PendSV and SysTick the lowest priority interrupts. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
* here already. */ * here already. */

View file

@ -62,6 +62,9 @@
#define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 1 #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 1
#endif #endif
/* Prototype of all Interrupt Service Routines (ISRs). */
typedef void ( * portISR_t )( void );
/* Constants required to access and manipulate the NVIC. */ /* Constants required to access and manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
@ -97,7 +100,6 @@
#define portMIN_INTERRUPT_PRIORITY ( 255UL ) #define portMIN_INTERRUPT_PRIORITY ( 255UL )
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL )
#define portNVIC_SVC_PRI ( ( ( uint32_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL ) << 24UL )
/* Constants required to manipulate the VFP. */ /* Constants required to manipulate the VFP. */
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34UL ) /* Floating point context control register. */ #define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34UL ) /* Floating point context control register. */
@ -109,6 +111,11 @@
#define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 ) #define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 )
#define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 ) #define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 )
/* Constants used to check the installation of the FreeRTOS interrupt handlers. */
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xE000ED08 ) )
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/* Constants required to check the validity of an interrupt priority. */ /* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
@ -448,7 +455,6 @@ void vSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
switch( ucSVCNumber ) switch( ucSVCNumber )
{ {
case portSVC_START_SCHEDULER: case portSVC_START_SCHEDULER:
portNVIC_SHPR2_REG |= portNVIC_SVC_PRI;
prvRestoreContextOfFirstTask(); prvRestoreContextOfFirstTask();
break; break;
@ -823,6 +829,40 @@ BaseType_t xPortStartScheduler( void )
configASSERT( portCPUID != portCORTEX_M7_r0p0_ID ); configASSERT( portCPUID != portCORTEX_M7_r0p0_ID );
#endif #endif
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions vPortSVCHandler and
* xPortPendSVHandler for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* vPortSVCHandler and xPortPendSVHandler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == vPortSVCHandler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == xPortPendSVHandler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
volatile uint8_t ucOriginalPriority; volatile uint8_t ucOriginalPriority;
@ -907,11 +947,11 @@ BaseType_t xPortStartScheduler( void )
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* Make PendSV and SysTick the same priority as the kernel, and the SVC /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* handler higher priority so it can be used to exit a critical section (where * the highest priority. */
* lower priorities are masked). */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
/* Configure the regions in the MPU that are common to all tasks. */ /* Configure the regions in the MPU that are common to all tasks. */
prvSetupMPU(); prvSetupMPU();
@ -1483,7 +1523,15 @@ BaseType_t xPortIsAuthorizedToAccessBuffer( const void * pvBuffer,
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -38,10 +38,14 @@
#error This port can only be used when the project options are configured to enable hardware floating point support. #error This port can only be used when the project options are configured to enable hardware floating point support.
#endif #endif
/* Prototype of all Interrupt Service Routines (ISRs). */
typedef void ( * portISR_t )( void );
/* Constants required to manipulate the core. Registers first... */ /* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xe000ed1c ) )
#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) #define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
/* ...then bits in the registers. */ /* ...then bits in the registers. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
@ -56,6 +60,11 @@
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL )
/* Constants used to check the installation of the FreeRTOS interrupt handlers. */
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xE000ED08 ) )
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/* Constants required to check the validity of an interrupt priority. */ /* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
@ -290,6 +299,40 @@ static void prvPortStartFirstTask( void )
*/ */
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions vPortSVCHandler and
* xPortPendSVHandler for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* vPortSVCHandler and xPortPendSVHandler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == vPortSVCHandler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == xPortPendSVHandler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
volatile uint8_t ucOriginalPriority; volatile uint8_t ucOriginalPriority;
@ -374,9 +417,11 @@ BaseType_t xPortStartScheduler( void )
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* Make PendSV and SysTick the lowest priority interrupts. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
* here already. */ * here already. */

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -296,8 +296,8 @@ static void prvSetupTimerInterrupt( void )
* the context is saved at the start of vPortYieldFromTick(). The tick * the context is saved at the start of vPortYieldFromTick(). The tick
* count is incremented after the context is saved. * count is incremented after the context is saved.
*/ */
interrupt( TIMERA0_VECTOR ) prvTickISR( void ) __attribute__( ( naked ) ); interrupt( TIMERA0_VECTOR ) void prvTickISR( void ) __attribute__( ( naked ) );
interrupt( TIMERA0_VECTOR ) prvTickISR( void ) interrupt( TIMERA0_VECTOR ) void prvTickISR( void )
{ {
/* Save the context of the interrupted task. */ /* Save the context of the interrupted task. */
portSAVE_CONTEXT(); portSAVE_CONTEXT();
@ -320,8 +320,8 @@ static void prvSetupTimerInterrupt( void )
* tick count. We don't need to switch context, this can only be done by * tick count. We don't need to switch context, this can only be done by
* manual calls to taskYIELD(); * manual calls to taskYIELD();
*/ */
interrupt( TIMERA0_VECTOR ) prvTickISR( void ); interrupt( TIMERA0_VECTOR ) void prvTickISR( void );
interrupt( TIMERA0_VECTOR ) prvTickISR( void ) interrupt( TIMERA0_VECTOR ) void prvTickISR( void )
{ {
xTaskIncrementTick(); xTaskIncrementTick();
} }

View file

@ -53,6 +53,7 @@
#define portSHORT int #define portSHORT int
#define portSTACK_TYPE uint16_t #define portSTACK_TYPE uint16_t
#define portBASE_TYPE short #define portBASE_TYPE short
#define portPOINTER_SIZE_TYPE uint16_t
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef short BaseType_t; typedef short BaseType_t;
@ -118,6 +119,11 @@ extern void vPortYield( void ) __attribute__( ( naked ) );
#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 )
/* GCC used to define these but doesn't any more */
#define interrupt(vector) __attribute__((__interrupt__(vector)))
#define wakeup __attribute__((__wakeup__))
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */

View file

@ -111,9 +111,6 @@ extern void vTaskSwitchContext( void );
/* Critical section management. */ /* Critical section management. */
#define portCRITICAL_NESTING_IN_TCB 0 #define portCRITICAL_NESTING_IN_TCB 0
#define portSET_INTERRUPT_MASK_FROM_ISR() 0
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue
#define portDISABLE_INTERRUPTS() __asm volatile ( "csrc mstatus, 8" ) #define portDISABLE_INTERRUPTS() __asm volatile ( "csrc mstatus, 8" )
#define portENABLE_INTERRUPTS() __asm volatile ( "csrs mstatus, 8" ) #define portENABLE_INTERRUPTS() __asm volatile ( "csrs mstatus, 8" )

View file

@ -1,158 +1,109 @@
; /* ;/*
* ; * FreeRTOS Kernel <DEVELOPMENT BRANCH> ; * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* ; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. ; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* ; * ; *
* ; * SPDX-License-Identifier: MIT ; * SPDX-License-Identifier: MIT
* ; * ; *
* ; * Permission is hereby granted, free of charge, to any person obtaining a copy of ; * 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 ; * this software and associated documentation files (the "Software"), to deal in
* ; * the Software without restriction, including without limitation the rights to ; * the Software without restriction, including without limitation the rights to
* ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of ; * 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, ; * the Software, and to permit persons to whom the Software is furnished to do so,
* ; * subject to the following conditions: ; * subject to the following conditions:
* ; * ; *
* ; * The above copyright notice and this permission notice shall be included in all ; * The above copyright notice and this permission notice shall be included in all
* ; * copies or substantial portions of the Software. ; * copies or substantial portions of the Software.
* ; * ; *
* ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ; * 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 ; * 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 ; * 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. ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* ; * ; *
* ; * https://www.FreeRTOS.org ; * https://www.FreeRTOS.org
* ; * https://github.com/FreeRTOS ; * https://github.com/FreeRTOS
* ; * ; *
* ; */ ; */
EXTERN vTaskSwitchContext EXTERN vTaskSwitchContext
EXTERN ulCriticalNesting EXTERN ulCriticalNesting
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN ulPortTaskHasFPUContext EXTERN ulPortTaskHasFPUContext
EXTERN ulAsmAPIPriorityMask EXTERN ulAsmAPIPriorityMask
portSAVE_CONTEXT macro portSAVE_CONTEXT macro
; ; Save the LR and SPSR onto the system mode stack before switching to
Save the LR and SPSR onto the system mode stack before switching to ; system mode to save the remaining system mode registers
; SRSDB sp!, #SYS_MODE
system mode to save the remaining system mode registers CPS #SYS_MODE
SRSDB sp !, # SYS_MODE PUSH {R0-R12, R14}
CPS # SYS_MODE
PUSH {
R0 - R12, R14
}
; ; Push the critical nesting count
Push the critical nesting count LDR R2, =ulCriticalNesting
LDR R2, = ulCriticalNesting LDR R1, [R2]
LDR R1, [ R2 ] PUSH {R1}
PUSH {
R1
}
; ; Does the task have a floating point context that needs saving? If
Does the task have a floating point context that needs saving ? If ; ulPortTaskHasFPUContext is 0 then no.
; LDR R2, =ulPortTaskHasFPUContext
ulPortTaskHasFPUContext is 0 then no. LDR R3, [R2]
LDR R2, = ulPortTaskHasFPUContext CMP R3, #0
LDR R3, [ R2 ]
CMP R3, # 0
;
Save the floating point context,
if any
FMRXNE R1, FPSCR
VPUSHNE {
D0 - D15
}
; Save the floating point context, if any
FMRXNE R1, FPSCR
VPUSHNE {D0-D15}
#if configFPU_D32 == 1 #if configFPU_D32 == 1
VPUSHNE { VPUSHNE {D16-D31}
D16 - D31 #endif ; configFPU_D32
} PUSHNE {R1}
#endif; configFPU_D32
PUSHNE {
R1
}
; ; Save ulPortTaskHasFPUContext itself
Save ulPortTaskHasFPUContext itself PUSH {R3}
PUSH {
R3
}
; ; Save the stack pointer in the TCB
Save the stack pointer in the TCB LDR R0, =pxCurrentTCB
LDR R0, = pxCurrentTCB LDR R1, [R0]
LDR R1, [ R0 ] STR SP, [R1]
STR SP, [ R1 ]
endm endm
; /**********************************************************************/ ; /**********************************************************************/
portRESTORE_CONTEXT macro portRESTORE_CONTEXT macro
; ; Set the SP to point to the stack of the task being restored.
Set the SP to point to the stack of the task being restored. LDR R0, =pxCurrentTCB
LDR R0, = pxCurrentTCB LDR R1, [R0]
LDR R1, [ R0 ] LDR SP, [R1]
LDR SP, [ R1 ]
; ; Is there a floating point context to restore? If the restored
Is there a floating point context to restore ? If the restored ; ulPortTaskHasFPUContext is zero then no.
; LDR R0, =ulPortTaskHasFPUContext
ulPortTaskHasFPUContext is zero then no. POP {R1}
LDR R0, = ulPortTaskHasFPUContext STR R1, [R0]
POP { CMP R1, #0
R1
}
STR R1, [ R0 ]
CMP R1, # 0
;
Restore the floating point context,
if any
POPNE {
R0
}
; Restore the floating point context, if any
POPNE {R0}
#if configFPU_D32 == 1 #if configFPU_D32 == 1
VPOPNE { VPOPNE {D16-D31}
D16 - D31 #endif ; configFPU_D32
} VPOPNE {D0-D15}
#endif; configFPU_D32 VMSRNE FPSCR, R0
VPOPNE {
D0 - D15
}
VMSRNE FPSCR, R0
; ; Restore the critical section nesting depth
Restore the critical section nesting depth LDR R0, =ulCriticalNesting
LDR R0, = ulCriticalNesting POP {R1}
POP { STR R1, [R0]
R1
}
STR R1, [ R0 ]
; ; Restore all system mode registers other than the SP (which is already
Restore all system mode registers other than the SP( which is already ; being used)
; POP {R0-R12, R14}
being used )
POP
{
R0 - R12, R14
}
Return to the task code, loading CPSR on the way.CPSR has the interrupt ; Return to the task code, loading CPSR on the way. CPSR has the interrupt
; ; enable bit set appropriately for the task about to execute.
enable bit set appropriately RFEIA sp!
for the task about to execute. endm
RFEIA sp !
endm

View file

@ -1,160 +1,111 @@
; /* ;/*
* ; * FreeRTOS Kernel <DEVELOPMENT BRANCH> ; * FreeRTOS Kernel <DEVELOPMENT BRANCH>
* ; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. ; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* ; * ; *
* ; * SPDX-License-Identifier: MIT ; * SPDX-License-Identifier: MIT
* ; * ; *
* ; * Permission is hereby granted, free of charge, to any person obtaining a copy of ; * 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 ; * this software and associated documentation files (the "Software"), to deal in
* ; * the Software without restriction, including without limitation the rights to ; * the Software without restriction, including without limitation the rights to
* ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of ; * 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, ; * the Software, and to permit persons to whom the Software is furnished to do so,
* ; * subject to the following conditions: ; * subject to the following conditions:
* ; * ; *
* ; * The above copyright notice and this permission notice shall be included in all ; * The above copyright notice and this permission notice shall be included in all
* ; * copies or substantial portions of the Software. ; * copies or substantial portions of the Software.
* ; * ; *
* ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ; * 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 ; * 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 ; * 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. ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* ; * ; *
* ; * https://www.FreeRTOS.org ; * https://www.FreeRTOS.org
* ; * https://github.com/FreeRTOS ; * https://github.com/FreeRTOS
* ; * ; *
* ; */ ; */
EXTERN vTaskSwitchContext EXTERN vTaskSwitchContext
EXTERN ulCriticalNesting EXTERN ulCriticalNesting
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN ulPortTaskHasFPUContext EXTERN ulPortTaskHasFPUContext
EXTERN ulAsmAPIPriorityMask EXTERN ulAsmAPIPriorityMask
portSAVE_CONTEXT macro portSAVE_CONTEXT macro
; ; Save the LR and SPSR onto the system mode stack before switching to
Save the LR and SPSR onto the system mode stack before switching to ; system mode to save the remaining system mode registers
; SRSDB sp!, #SYS_MODE
system mode to save the remaining system mode registers CPS #SYS_MODE
SRSDB sp !, # SYS_MODE PUSH {R0-R12, R14}
CPS # SYS_MODE
PUSH {
R0 - R12, R14
}
; ; Push the critical nesting count
Push the critical nesting count LDR R2, =ulCriticalNesting
LDR R2, = ulCriticalNesting LDR R1, [R2]
LDR R1, [ R2 ] PUSH {R1}
PUSH {
R1
}
; ; Does the task have a floating point context that needs saving? If
Does the task have a floating point context that needs saving ? If ; ulPortTaskHasFPUContext is 0 then no.
; LDR R2, =ulPortTaskHasFPUContext
ulPortTaskHasFPUContext is 0 then no. LDR R3, [R2]
LDR R2, = ulPortTaskHasFPUContext CMP R3, #0
LDR R3, [ R2 ]
CMP R3, # 0
; ; Save the floating point context, if any
Save the floating point context, FMRXNE R1, FPSCR
VPUSHNE {D0-D15}
VPUSHNE {D16-D31}
PUSHNE {R1}
if any ; Save ulPortTaskHasFPUContext itself
FMRXNE R1, FPSCR PUSH {R3}
VPUSHNE {
D0 - D15
}
VPUSHNE { ; Save the stack pointer in the TCB
D16 - D31 LDR R0, =pxCurrentTCB
} LDR R1, [R0]
PUSHNE { STR SP, [R1]
R1
}
; endm
Save ulPortTaskHasFPUContext itself
PUSH {
R3
}
;
Save the stack pointer in the TCB
LDR R0, = pxCurrentTCB
LDR R1, [ R0 ]
STR SP, [ R1 ]
endm
; /**********************************************************************/ ; /**********************************************************************/
portRESTORE_CONTEXT macro portRESTORE_CONTEXT macro
; ; Set the SP to point to the stack of the task being restored.
Set the SP to point to the stack of the task being restored. LDR R0, =pxCurrentTCB
LDR R0, = pxCurrentTCB LDR R1, [R0]
LDR R1, [ R0 ] LDR SP, [R1]
LDR SP, [ R1 ]
; ; Is there a floating point context to restore? If the restored
Is there a floating point context to restore ? If the restored ; ulPortTaskHasFPUContext is zero then no.
; LDR R0, =ulPortTaskHasFPUContext
ulPortTaskHasFPUContext is zero then no. POP {R1}
LDR R0, = ulPortTaskHasFPUContext STR R1, [R0]
POP { CMP R1, #0
R1
}
STR R1, [ R0 ]
CMP R1, # 0
; ; Restore the floating point context, if any
Restore the floating point context, POPNE {R0}
VPOPNE {D16-D31}
VPOPNE {D0-D15}
VMSRNE FPSCR, R0
if any ; Restore the critical section nesting depth
POPNE { LDR R0, =ulCriticalNesting
R0 POP {R1}
} STR R1, [R0]
VPOPNE { ; Ensure the priority mask is correct for the critical nesting depth
D16 - D31 LDR R2, =portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS
} CMP R1, #0
VPOPNE { MOVEQ R4, #255
D0 - D15 LDRNE R4, =( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT )
} STR R4, [r2]
VMSRNE FPSCR, R0
; ; Restore all system mode registers other than the SP (which is already
Restore the critical section nesting depth ; being used)
LDR R0, = ulCriticalNesting POP {R0-R12, R14}
POP {
R1
}
STR R1, [ R0 ]
; ; Return to the task code, loading CPSR on the way.
Ensure the priority mask is correct RFEIA sp!
for the critical nesting depth endm
LDR R2, = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS
CMP R1, # 0
MOVEQ R4, # 255
LDRNE R4, = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT )
STR R4, [ r2 ]
;
Restore all system mode registers other than the SP( which is already
;
being used )
POP
{
R0 - R12, R14
}
Return to the task code, loading CPSR on the way.
RFEIA sp !
endm

View file

@ -37,6 +37,9 @@
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
/* Prototype of all Interrupt Service Routines (ISRs). */
typedef void ( * portISR_t )( void );
/* Constants required to manipulate the NVIC. */ /* Constants required to manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
@ -53,6 +56,10 @@
#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL ) #define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL ) #define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
/* Constants used to check the installation of the FreeRTOS interrupt handlers. */
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portVECTOR_INDEX_PENDSV ( 14 )
/* Constants required to set up the initial stack. */ /* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 ) #define portINITIAL_XPSR ( 0x01000000 )
@ -121,6 +128,10 @@ extern void vPortStartFirstTask( void );
*/ */
static void prvTaskExitError( void ); static void prvTaskExitError( void );
/*
* FreeRTOS handlers implemented in assembly.
*/
extern void xPortPendSVHandler( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
@ -168,6 +179,41 @@ static void prvTaskExitError( void )
*/ */
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the function xPortPendSVHandler for PendSV
* interrupt.
* 2. Indirect Routing - Install separate handler for PendSV interrupt and
* route program control from that handler to xPortPendSVHandler function.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
/* Point pxVectorTable to the interrupt vector table. Systems without
* a VTOR register provide the value zero in the VTOR register and
* the vector table itself is located at the address 0x00000000. */
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handler for PendSV interrupt. We do not check the installation of the
* SysTick handler because the application may choose to drive the RTOS
* tick using a timer other than the SysTick timer by overriding the
* weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handler. For help installing the FreeRTOS handler, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == xPortPendSVHandler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
/* Make PendSV and SysTick the lowest priority interrupts. */ /* Make PendSV and SysTick the lowest priority interrupts. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;

View file

@ -91,15 +91,15 @@ xPortPendSVHandler:
vPortSVCHandler; vPortSVCHandler;
/* This function is no longer used, but retained for backward /* This function is no longer used, but retained for backward
compatibility. */ * compatibility. */
bx lr bx lr
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vPortStartFirstTask vPortStartFirstTask
/* The MSP stack is not reset as, unlike on M3/4 parts, there is no vector /* Don't reset the MSP stack as is done on CM3/4 devices. The vector table
table offset register that can be used to locate the initial stack value. * in some CM0 devices cannot be modified and thus may not hold the
Not all M0 parts have the application vector table at address 0. */ * application's initial MSP value. */
ldr r3, =pxCurrentTCB /* Obtain location of pxCurrentTCB. */ ldr r3, =pxCurrentTCB /* Obtain location of pxCurrentTCB. */
ldr r1, [r3] ldr r1, [r3]

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -41,10 +41,14 @@
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http: /*www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http: /*www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
#endif #endif
/* Prototype of all Interrupt Service Routines (ISRs). */
typedef void ( * portISR_t )( void );
/* Constants required to manipulate the core. Registers first... */ /* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xe000ed1c ) )
#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) #define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
/* ...then bits in the registers. */ /* ...then bits in the registers. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
@ -59,6 +63,11 @@
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL )
/* Constants used to check the installation of the FreeRTOS interrupt handlers. */
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xE000ED08 ) )
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/* Constants required to check the validity of an interrupt priority. */ /* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
@ -121,6 +130,11 @@ extern void vPortStartFirstTask( void );
*/ */
static void prvTaskExitError( void ); static void prvTaskExitError( void );
/*
* FreeRTOS handlers implemented in assembly.
*/
extern void vPortSVCHandler( void );
extern void xPortPendSVHandler( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Each task maintains its own interrupt status in the critical nesting /* Each task maintains its own interrupt status in the critical nesting
@ -208,6 +222,40 @@ static void prvTaskExitError( void )
*/ */
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions vPortSVCHandler and
* xPortPendSVHandler for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* vPortSVCHandler and xPortPendSVHandler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == vPortSVCHandler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == xPortPendSVHandler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
volatile uint8_t ucOriginalPriority; volatile uint8_t ucOriginalPriority;
@ -292,9 +340,11 @@ BaseType_t xPortStartScheduler( void )
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* Make PendSV and SysTick the lowest priority interrupts. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
* here already. */ * here already. */

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -45,10 +45,14 @@
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http: /*www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http: /*www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
#endif #endif
/* Prototype of all Interrupt Service Routines (ISRs). */
typedef void ( * portISR_t )( void );
/* Constants required to manipulate the core. Registers first... */ /* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xe000ed1c ) )
#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) #define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
/* ...then bits in the registers. */ /* ...then bits in the registers. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
@ -69,6 +73,11 @@
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL )
/* Constants used to check the installation of the FreeRTOS interrupt handlers. */
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xE000ED08 ) )
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/* Constants required to check the validity of an interrupt priority. */ /* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
@ -141,6 +150,11 @@ extern void vPortEnableVFP( void );
*/ */
static void prvTaskExitError( void ); static void prvTaskExitError( void );
/*
* FreeRTOS handlers implemented in assembly.
*/
extern void vPortSVCHandler( void );
extern void xPortPendSVHandler( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Each task maintains its own interrupt status in the critical nesting /* Each task maintains its own interrupt status in the critical nesting
@ -246,6 +260,40 @@ BaseType_t xPortStartScheduler( void )
configASSERT( portCPUID != portCORTEX_M7_r0p1_ID ); configASSERT( portCPUID != portCORTEX_M7_r0p1_ID );
configASSERT( portCPUID != portCORTEX_M7_r0p0_ID ); configASSERT( portCPUID != portCORTEX_M7_r0p0_ID );
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions vPortSVCHandler and
* xPortPendSVHandler for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* vPortSVCHandler and xPortPendSVHandler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == vPortSVCHandler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == xPortPendSVHandler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
volatile uint8_t ucOriginalPriority; volatile uint8_t ucOriginalPriority;
@ -330,9 +378,11 @@ BaseType_t xPortStartScheduler( void )
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* Make PendSV and SysTick the lowest priority interrupts. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
* here already. */ * here already. */

View file

@ -69,6 +69,9 @@
#define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 1 #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 1
#endif #endif
/* Prototype of all Interrupt Service Routines (ISRs). */
typedef void ( * portISR_t )( void );
/* Constants required to manipulate the core. Registers first... */ /* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
@ -108,7 +111,11 @@
#define portMIN_INTERRUPT_PRIORITY ( 255UL ) #define portMIN_INTERRUPT_PRIORITY ( 255UL )
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL )
#define portNVIC_SVC_PRI ( ( ( uint32_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL ) << 24UL )
/* Constants used to check the installation of the FreeRTOS interrupt handlers. */
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xE000ED08 ) )
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/* Constants required to check the validity of an interrupt priority. */ /* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
@ -282,6 +289,11 @@ BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
*/ */
void vPortSwitchToUserMode( void ); void vPortSwitchToUserMode( void );
/*
* FreeRTOS handlers implemented in assembly.
*/
extern void vPortSVCHandler( void ) PRIVILEGED_FUNCTION;
extern void xPortPendSVHandler( void ) PRIVILEGED_FUNCTION;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Each task maintains its own interrupt status in the critical nesting /* Each task maintains its own interrupt status in the critical nesting
@ -384,7 +396,6 @@ void vPortSVCHandler_C( uint32_t * pulParam ) /* PRIVILEGED_FUNCTION */
switch( ucSVCNumber ) switch( ucSVCNumber )
{ {
case portSVC_START_SCHEDULER: case portSVC_START_SCHEDULER:
portNVIC_SHPR2_REG |= portNVIC_SVC_PRI;
vPortRestoreContextOfFirstTask(); vPortRestoreContextOfFirstTask();
break; break;
@ -713,6 +724,40 @@ BaseType_t xPortStartScheduler( void )
configASSERT( portCPUID != portCORTEX_M7_r0p0_ID ); configASSERT( portCPUID != portCORTEX_M7_r0p0_ID );
#endif #endif
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions vPortSVCHandler and
* xPortPendSVHandler for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* vPortSVCHandler and xPortPendSVHandler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == vPortSVCHandler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == xPortPendSVHandler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
volatile uint8_t ucOriginalPriority; volatile uint8_t ucOriginalPriority;
@ -797,9 +842,11 @@ BaseType_t xPortStartScheduler( void )
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* Make PendSV and SysTick the lowest priority interrupts. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
/* Configure the regions in the MPU that are common to all tasks. */ /* Configure the regions in the MPU that are common to all tasks. */
prvSetupMPU(); prvSetupMPU();
@ -1206,7 +1253,15 @@ BaseType_t xPortIsAuthorizedToAccessBuffer( const void * pvBuffer,
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -45,10 +45,14 @@
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http: /*www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http: /*www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
#endif #endif
/* Prototype of all Interrupt Service Routines (ISRs). */
typedef void ( * portISR_t )( void );
/* Constants required to manipulate the core. Registers first... */ /* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) ) #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xe000ed1c ) )
#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) #define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
/* ...then bits in the registers. */ /* ...then bits in the registers. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
@ -63,6 +67,11 @@
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL )
/* Constants used to check the installation of the FreeRTOS interrupt handlers. */
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xE000ED08 ) )
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/* Constants required to check the validity of an interrupt priority. */ /* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
@ -135,6 +144,11 @@ extern void vPortEnableVFP( void );
*/ */
static void prvTaskExitError( void ); static void prvTaskExitError( void );
/*
* FreeRTOS handlers implemented in assembly.
*/
extern void vPortSVCHandler( void );
extern void xPortPendSVHandler( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Each task maintains its own interrupt status in the critical nesting /* Each task maintains its own interrupt status in the critical nesting
@ -234,6 +248,40 @@ static void prvTaskExitError( void )
*/ */
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions vPortSVCHandler and
* xPortPendSVHandler for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* vPortSVCHandler and xPortPendSVHandler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == vPortSVCHandler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == xPortPendSVHandler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
volatile uint8_t ucOriginalPriority; volatile uint8_t ucOriginalPriority;
@ -318,9 +366,11 @@ BaseType_t xPortStartScheduler( void )
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* Make PendSV and SysTick the lowest priority interrupts. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
* here already. */ * here already. */

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -80,6 +80,12 @@
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to manipulate the NVIC. * @brief Constants required to manipulate the NVIC.
*/ */
@ -101,10 +107,18 @@
/** /**
* @brief Constants required to manipulate the SCB. * @brief Constants required to manipulate the SCB.
*/ */
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/
/** /**
* @brief Constants required to check the validity of an interrupt priority. * @brief Constants required to check the validity of an interrupt priority.
*/ */
@ -1598,9 +1612,42 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{ {
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{ {
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0; volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
@ -1609,11 +1656,8 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible. * ensure interrupt entry is as fast and simple as possible.
* *
* Save the interrupt priority value that is about to be clobbered. */ * First, determine the number of priority bits available. Write to all
ulOriginalPriority = portNVIC_SHPR2_REG; * possible bits in the priority setting for SVCall. */
/* Determine the number of priority bits available. First write to all
* possible bits. */
portNVIC_SHPR2_REG = 0xFF000000; portNVIC_SHPR2_REG = 0xFF000000;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
/* Calculate the maximum acceptable priority group value for the number /* Calculate the maximum acceptable priority group value for the number
* of bits read back. */ * of bits read back. */
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{ {
ulImplementedPrioBits++; ulImplementedPrioBits++;
@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */ * register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
} }
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */ /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
#if ( configENABLE_MPU == 1 ) #if ( configENABLE_MPU == 1 )
{ {
@ -1865,7 +1906,15 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG ) if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

View file

@ -31,54 +31,54 @@
portSAVE_CONTEXT macro portSAVE_CONTEXT macro
IMPORT pxCurrentTCB IMPORT pxCurrentTCB
IMPORT usCriticalNesting IMPORT usCriticalNesting
/* Save the remaining registers. */ /* Save the remaining registers. */
push r4 push r4
push r5 push r5
push r6 push r6
push r7 push r7
push r8 push r8
push r9 push r9
push r10 push r10
push r11 push r11
push r12 push r12
push r13 push r13
push r14 push r14
push r15 push r15
mov.w &usCriticalNesting, r14 mov.w &usCriticalNesting, r14
push r14 push r14
mov.w &pxCurrentTCB, r12 mov.w &pxCurrentTCB, r12
mov.w r1, 0 ( r12 ) mov.w r1, 0(r12)
endm endm
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
portRESTORE_CONTEXT macro portRESTORE_CONTEXT macro
mov.w & pxCurrentTCB, r12 mov.w &pxCurrentTCB, r12
mov.w @r12, r1 mov.w @r12, r1
pop r15 pop r15
mov.w r15, &usCriticalNesting mov.w r15, &usCriticalNesting
pop r15 pop r15
pop r14 pop r14
pop r13 pop r13
pop r12 pop r12
pop r11 pop r11
pop r10 pop r10
pop r9 pop r9
pop r8 pop r8
pop r7 pop r7
pop r6 pop r6
pop r5 pop r5
pop r4 pop r4
/* The last thing on the stack will be the status register. /* The last thing on the stack will be the status register.
* Ensure the power down bits are clear ready for the next * Ensure the power down bits are clear ready for the next
* time this power down register is popped from the stack. */ * time this power down register is popped from the stack. */
bic.w # 0xf0, 0 ( SP ) bic.w #0xf0, 0(SP)
reti reti
endm endm
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#endif /* ifndef PORTASM_H */ #endif /* ifndef PORTASM_H */

View file

@ -113,9 +113,6 @@ extern void vTaskSwitchContext( void );
/* Critical section management. */ /* Critical section management. */
#define portCRITICAL_NESTING_IN_TCB 0 #define portCRITICAL_NESTING_IN_TCB 0
#define portSET_INTERRUPT_MASK_FROM_ISR() 0
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue
#define portDISABLE_INTERRUPTS() __disable_interrupt() #define portDISABLE_INTERRUPTS() __disable_interrupt()
#define portENABLE_INTERRUPTS() __enable_interrupt() #define portENABLE_INTERRUPTS() __enable_interrupt()

View file

@ -28,9 +28,9 @@
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the Tern EE 186 * Implementation of functions defined in portable.h for the Tern EE 186
* port. * port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Library includes. */ /* Library includes. */
#include <embedded.h> #include <embedded.h>
@ -55,16 +55,14 @@
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
/* The ISR used depends on whether the preemptive or cooperative scheduler /* The ISR used depends on whether the preemptive or cooperative scheduler
* is being used. */ is being used. */
#if ( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
/* Tick service routine used by the scheduler when preemptive scheduling is
/* Tick service routine used by the scheduler when preemptive scheduling is being used. */
* being used. */
static void __interrupt __far prvPreemptiveTick( void ); static void __interrupt __far prvPreemptiveTick( void );
#else #else
/* Tick service routine used by the scheduler when cooperative scheduling is
/* Tick service routine used by the scheduler when cooperative scheduling is being used. */
* being used. */
static void __interrupt __far prvNonPreemptiveTick( void ); static void __interrupt __far prvNonPreemptiveTick( void );
#endif #endif
@ -72,20 +70,18 @@ static void prvSetupTimerInterrupt( void );
static void __interrupt __far prvYieldProcessor( void ); static void __interrupt __far prvYieldProcessor( void );
/* The timer initialisation functions leave interrupts enabled, /* The timer initialisation functions leave interrupts enabled,
* which is not what we want. This ISR is installed temporarily in case which is not what we want. This ISR is installed temporarily in case
* the timer fires before we get a change to disable interrupts again. */ the timer fires before we get a change to disable interrupts again. */
static void __interrupt __far prvDummyISR( void ); static void __interrupt __far prvDummyISR( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* See header file for description. */ /* See header file for description. */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
StackType_t DS_Reg = 0; StackType_t DS_Reg = 0;
/* Place a few bytes of known values on the bottom of the stack. /* Place a few bytes of known values on the bottom of the stack.
* This is just useful for debugging. */ This is just useful for debugging. */
*pxTopOfStack = 0x1111; *pxTopOfStack = 0x1111;
pxTopOfStack--; pxTopOfStack--;
@ -95,8 +91,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* We are going to start the scheduler using a return from interrupt /* We are going to start the scheduler using a return from interrupt
* instruction to load the program counter, so first there would be the instruction to load the program counter, so first there would be the
* function call with parameters preamble. */ function call with parameters preamble. */
*pxTopOfStack = FP_SEG( pvParameters ); *pxTopOfStack = FP_SEG( pvParameters );
pxTopOfStack--; pxTopOfStack--;
@ -116,8 +112,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* The remaining registers would be pushed on the stack by our context /* The remaining registers would be pushed on the stack by our context
* switch function. These are loaded with values simply to make debugging switch function. These are loaded with values simply to make debugging
* easier. */ easier. */
*pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */ *pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */ *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */
@ -130,9 +126,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* We need the true data segment. */ /* We need the true data segment. */
__asm { __asm{ MOV DS_Reg, DS };
MOV DS_Reg, DS
};
*pxTopOfStack = DS_Reg; /* DS */ *pxTopOfStack = DS_Reg; /* DS */
pxTopOfStack--; pxTopOfStack--;
@ -151,7 +145,7 @@ BaseType_t xPortStartScheduler( void )
/* This is called with interrupts already disabled. */ /* This is called with interrupts already disabled. */
/* Put our manual switch (yield) function on a known /* Put our manual switch (yield) function on a known
* vector. */ vector. */
setvect( portSWITCH_INT_NUMBER, prvYieldProcessor ); setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
/* Setup the tick interrupt. */ /* Setup the tick interrupt. */
@ -168,15 +162,15 @@ BaseType_t xPortStartScheduler( void )
static void __interrupt __far prvDummyISR( void ) static void __interrupt __far prvDummyISR( void )
{ {
/* The timer initialisation functions leave interrupts enabled, /* The timer initialisation functions leave interrupts enabled,
* which is not what we want. This ISR is installed temporarily in case which is not what we want. This ISR is installed temporarily in case
* the timer fires before we get a change to disable interrupts again. */ the timer fires before we get a change to disable interrupts again. */
outport( portEIO_REGISTER, portCLEAR_INTERRUPT ); outport( portEIO_REGISTER, portCLEAR_INTERRUPT );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* The ISR used depends on whether the preemptive or cooperative scheduler /* The ISR used depends on whether the preemptive or cooperative scheduler
* is being used. */ is being used. */
#if ( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
static void __interrupt __far prvPreemptiveTick( void ) static void __interrupt __far prvPreemptiveTick( void )
{ {
/* Get the scheduler to update the task states following the tick. */ /* Get the scheduler to update the task states following the tick. */
@ -189,17 +183,17 @@ static void __interrupt __far prvDummyISR( void )
/* Reset interrupt. */ /* Reset interrupt. */
outport( portEIO_REGISTER, portCLEAR_INTERRUPT ); outport( portEIO_REGISTER, portCLEAR_INTERRUPT );
} }
#else /* if ( configUSE_PREEMPTION == 1 ) */ #else
static void __interrupt __far prvNonPreemptiveTick( void ) static void __interrupt __far prvNonPreemptiveTick( void )
{ {
/* Same as preemptive tick, but the cooperative scheduler is being used /* Same as preemptive tick, but the cooperative scheduler is being used
* so we don't have to switch in the context of the next task. */ so we don't have to switch in the context of the next task. */
xTaskIncrementTick(); xTaskIncrementTick();
/* Reset interrupt. */ /* Reset interrupt. */
outport( portEIO_REGISTER, portCLEAR_INTERRUPT ); outport( portEIO_REGISTER, portCLEAR_INTERRUPT );
} }
#endif /* if ( configUSE_PREEMPTION == 1 ) */ #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void __interrupt __far prvYieldProcessor( void ) static void __interrupt __far prvYieldProcessor( void )
@ -217,25 +211,23 @@ void vPortEndScheduler( void )
static void prvSetupTimerInterrupt( void ) static void prvSetupTimerInterrupt( void )
{ {
const uint16_t usTimerACompare = portTIMER_COMPARE, usTimerAMode = portENABLE_TIMER_AND_INTERRUPT; const uint16_t usTimerACompare = portTIMER_COMPARE, usTimerAMode = portENABLE_TIMER_AND_INTERRUPT;
const uint16_t usT2_IRQ = 0x13; const uint16_t usT2_IRQ = 0x13;
/* Configure the timer, the dummy handler is used here as the init /* Configure the timer, the dummy handler is used here as the init
* function leaves interrupts enabled. */ function leaves interrupts enabled. */
t2_init( usTimerAMode, usTimerACompare, prvDummyISR ); t2_init( usTimerAMode, usTimerACompare, prvDummyISR );
/* Disable interrupts again before installing the real handlers. */ /* Disable interrupts again before installing the real handlers. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
#if ( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
/* Tick service routine used by the scheduler when preemptive scheduling is /* Tick service routine used by the scheduler when preemptive scheduling is
* being used. */ being used. */
setvect( usT2_IRQ, prvPreemptiveTick ); setvect( usT2_IRQ, prvPreemptiveTick );
#else #else
/* Tick service routine used by the scheduler when cooperative scheduling is /* Tick service routine used by the scheduler when cooperative scheduling is
* being used. */ being used. */
setvect( usT2_IRQ, prvNonPreemptiveTick ); setvect( usT2_IRQ, prvNonPreemptiveTick );
#endif #endif
} }

View file

@ -48,7 +48,7 @@ void portFIRST_CONTEXT( void );
asm { mov ax, seg pxCurrentTCB } \ asm { mov ax, seg pxCurrentTCB } \
asm { mov ds, ax } \ asm { mov ds, ax } \
asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */ \ asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */ \
asm { mov es : 0x2[ bx ], ss } \ asm { mov es:0x2[ bx ], ss } \
asm { mov es:[ bx ], sp } \ asm { mov es:[ bx ], sp } \
asm { call far ptr vTaskSwitchContext } /* Perform the switch. */ \ asm { call far ptr vTaskSwitchContext } /* Perform the switch. */ \
asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */ \ asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */ \

View file

@ -59,7 +59,7 @@ typedef short BaseType_t;
typedef unsigned short UBaseType_t; typedef unsigned short UBaseType_t;
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) #if( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
@ -71,22 +71,21 @@ typedef unsigned short UBaseType_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section handling. */ /* Critical section handling. */
#define portENTER_CRITICAL() \ #define portENTER_CRITICAL() __asm{ pushf } \
__asm { pushf } \ __asm{ cli } \
__asm { cli } \
#define portEXIT_CRITICAL() __asm { popf } #define portEXIT_CRITICAL() __asm{ popf }
#define portDISABLE_INTERRUPTS() __asm { cli } #define portDISABLE_INTERRUPTS() __asm{ cli }
#define portENABLE_INTERRUPTS() __asm { sti } #define portENABLE_INTERRUPTS() __asm{ sti }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portNOP() __asm { nop } #define portNOP() __asm{ nop }
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portSWITCH_INT_NUMBER 0x80 #define portSWITCH_INT_NUMBER 0x80
#define portYIELD() __asm { int portSWITCH_INT_NUMBER } #define portYIELD() __asm{ int portSWITCH_INT_NUMBER }
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 2 #define portBYTE_ALIGNMENT 2
#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */ #define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */
@ -100,8 +99,8 @@ typedef unsigned short UBaseType_t;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vTaskFunction, vParameters ) void vTaskFunction( void * pvParameters ) #define portTASK_FUNCTION_PROTO( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters )
#define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void * pvParameters ) #define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters )
/* *INDENT-OFF* */ /* *INDENT-OFF* */
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -28,9 +28,9 @@
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the Tern EE 186 * Implementation of functions defined in portable.h for the Tern EE 186
* port. * port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Library includes. */ /* Library includes. */
#include <embedded.h> #include <embedded.h>
@ -57,16 +57,14 @@
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
/* The ISR used depends on whether the preemptive or cooperative scheduler /* The ISR used depends on whether the preemptive or cooperative scheduler
* is being used. */ is being used. */
#if ( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
/* Tick service routine used by the scheduler when preemptive scheduling is
/* Tick service routine used by the scheduler when preemptive scheduling is being used. */
* being used. */
static void __interrupt __far prvPreemptiveTick( void ); static void __interrupt __far prvPreemptiveTick( void );
#else #else
/* Tick service routine used by the scheduler when cooperative scheduling is
/* Tick service routine used by the scheduler when cooperative scheduling is being used. */
* being used. */
static void __interrupt __far prvNonPreemptiveTick( void ); static void __interrupt __far prvNonPreemptiveTick( void );
#endif #endif
@ -75,19 +73,15 @@ static void __interrupt __far prvYieldProcessor( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* See header file for description. */ /* See header file for description. */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
StackType_t DS_Reg = 0; StackType_t DS_Reg = 0;
/* We need the true data segment. */ /* We need the true data segment. */
__asm { __asm{ MOV DS_Reg, DS };
MOV DS_Reg, DS
};
/* Place a few bytes of known values on the bottom of the stack. /* Place a few bytes of known values on the bottom of the stack.
* This is just useful for debugging. */ This is just useful for debugging. */
*pxTopOfStack = 0x1111; *pxTopOfStack = 0x1111;
pxTopOfStack--; pxTopOfStack--;
@ -97,8 +91,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* We are going to start the scheduler using a return from interrupt /* We are going to start the scheduler using a return from interrupt
* instruction to load the program counter, so first there would be the instruction to load the program counter, so first there would be the
* function call with parameters preamble. */ function call with parameters preamble. */
*pxTopOfStack = FP_OFF( pvParameters ); *pxTopOfStack = FP_OFF( pvParameters );
pxTopOfStack--; pxTopOfStack--;
@ -114,8 +108,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* The remaining registers would be pushed on the stack by our context /* The remaining registers would be pushed on the stack by our context
* switch function. These are loaded with values simply to make debugging switch function. These are loaded with values simply to make debugging
* easier. */ easier. */
*pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */ *pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */ *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */
@ -144,7 +138,7 @@ BaseType_t xPortStartScheduler( void )
/* This is called with interrupts already disabled. */ /* This is called with interrupts already disabled. */
/* Put our manual switch (yield) function on a known /* Put our manual switch (yield) function on a known
* vector. */ vector. */
setvect( portSWITCH_INT_NUMBER, prvYieldProcessor ); setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
/* Setup the tick interrupt. */ /* Setup the tick interrupt. */
@ -159,8 +153,8 @@ BaseType_t xPortStartScheduler( void )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* The ISR used depends on whether the preemptive or cooperative scheduler /* The ISR used depends on whether the preemptive or cooperative scheduler
* is being used. */ is being used. */
#if ( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
static void __interrupt __far prvPreemptiveTick( void ) static void __interrupt __far prvPreemptiveTick( void )
{ {
/* Get the scheduler to update the task states following the tick. */ /* Get the scheduler to update the task states following the tick. */
@ -173,17 +167,17 @@ BaseType_t xPortStartScheduler( void )
/* Reset interrupt. */ /* Reset interrupt. */
outport( portEIO_REGISTER, portCLEAR_INTERRUPT ); outport( portEIO_REGISTER, portCLEAR_INTERRUPT );
} }
#else /* if ( configUSE_PREEMPTION == 1 ) */ #else
static void __interrupt __far prvNonPreemptiveTick( void ) static void __interrupt __far prvNonPreemptiveTick( void )
{ {
/* Same as preemptive tick, but the cooperative scheduler is being used /* Same as preemptive tick, but the cooperative scheduler is being used
* so we don't have to switch in the context of the next task. */ so we don't have to switch in the context of the next task. */
xTaskIncrementTick(); xTaskIncrementTick();
/* Reset interrupt. */ /* Reset interrupt. */
outport( portEIO_REGISTER, portCLEAR_INTERRUPT ); outport( portEIO_REGISTER, portCLEAR_INTERRUPT );
} }
#endif /* if ( configUSE_PREEMPTION == 1 ) */ #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void __interrupt __far prvYieldProcessor( void ) static void __interrupt __far prvYieldProcessor( void )
@ -201,21 +195,19 @@ void vPortEndScheduler( void )
static void prvSetupTimerInterrupt( void ) static void prvSetupTimerInterrupt( void )
{ {
const uint32_t ulCompareValue = portTIMER_COMPARE; const uint32_t ulCompareValue = portTIMER_COMPARE;
uint16_t usTimerCompare; uint16_t usTimerCompare;
usTimerCompare = ( uint16_t ) ( ulCompareValue >> 4 ); usTimerCompare = ( uint16_t ) ( ulCompareValue >> 4 );
t2_init( portENABLE_TIMER, portPRESCALE_VALUE, NULL ); t2_init( portENABLE_TIMER, portPRESCALE_VALUE, NULL );
#if ( configUSE_PREEMPTION == 1 ) #if( configUSE_PREEMPTION == 1 )
/* Tick service routine used by the scheduler when preemptive scheduling is /* Tick service routine used by the scheduler when preemptive scheduling is
* being used. */ being used. */
t1_init( portENABLE_TIMER_AND_INTERRUPT, usTimerCompare, usTimerCompare, prvPreemptiveTick ); t1_init( portENABLE_TIMER_AND_INTERRUPT, usTimerCompare, usTimerCompare, prvPreemptiveTick );
#else #else
/* Tick service routine used by the scheduler when cooperative scheduling is /* Tick service routine used by the scheduler when cooperative scheduling is
* being used. */ being used. */
t1_init( portENABLE_TIMER_AND_INTERRUPT, usTimerCompare, usTimerCompare, prvNonPreemptiveTick ); t1_init( portENABLE_TIMER_AND_INTERRUPT, usTimerCompare, usTimerCompare, prvNonPreemptiveTick );
#endif #endif
} }

View file

@ -48,15 +48,15 @@ void portEND_SWITCHING_ISR( void );
void portFIRST_CONTEXT( void ); void portFIRST_CONTEXT( void );
#define portEND_SWITCHING_ISR() \ #define portEND_SWITCHING_ISR() \
asm { mov bx, [ pxCurrentTCB ] } \ asm { mov bx, [pxCurrentTCB] } \
asm { mov word ptr[ bx ], sp } \ asm { mov word ptr [bx], sp } \
asm { call far ptr vTaskSwitchContext } \ asm { call far ptr vTaskSwitchContext } \
asm { mov bx, [ pxCurrentTCB ] } \ asm { mov bx, [pxCurrentTCB] } \
asm { mov sp, [ bx ] } asm { mov sp, [bx] }
#define portFIRST_CONTEXT() \ #define portFIRST_CONTEXT() \
asm { mov bx, [ pxCurrentTCB ] } \ asm { mov bx, [pxCurrentTCB] } \
asm { mov sp, [ bx ] } \ asm { mov sp, [bx] } \
asm { pop bp } \ asm { pop bp } \
asm { pop di } \ asm { pop di } \
asm { pop si } \ asm { pop si } \
@ -69,4 +69,4 @@ void portFIRST_CONTEXT( void );
asm { iret } asm { iret }
#endif /* ifndef PORT_ASM_H */ #endif

View file

@ -59,9 +59,9 @@ typedef short BaseType_t;
typedef unsigned short UBaseType_t; typedef unsigned short UBaseType_t;
typedef void ( __interrupt __far * pxISR )(); typedef void ( __interrupt __far *pxISR )();
#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) #if( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS )
@ -73,22 +73,21 @@ typedef void ( __interrupt __far * pxISR )();
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section handling. */ /* Critical section handling. */
#define portENTER_CRITICAL() \ #define portENTER_CRITICAL() __asm{ pushf } \
__asm { pushf } \ __asm{ cli } \
__asm { cli } \
#define portEXIT_CRITICAL() __asm { popf } #define portEXIT_CRITICAL() __asm{ popf }
#define portDISABLE_INTERRUPTS() __asm { cli } #define portDISABLE_INTERRUPTS() __asm{ cli }
#define portENABLE_INTERRUPTS() __asm { sti } #define portENABLE_INTERRUPTS() __asm{ sti }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portNOP() __asm { nop } #define portNOP() __asm{ nop }
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portSWITCH_INT_NUMBER 0x80 #define portSWITCH_INT_NUMBER 0x80
#define portYIELD() __asm { int portSWITCH_INT_NUMBER } #define portYIELD() __asm{ int portSWITCH_INT_NUMBER }
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 2 #define portBYTE_ALIGNMENT 2
#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */ #define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */
@ -102,8 +101,8 @@ typedef void ( __interrupt __far * pxISR )();
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vTaskFunction, vParameters ) void vTaskFunction( void * pvParameters ) #define portTASK_FUNCTION_PROTO( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters )
#define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void * pvParameters ) #define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters )
/* *INDENT-OFF* */ /* *INDENT-OFF* */
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -51,6 +51,9 @@
#define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 1 #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 1
#endif #endif
/* Prototype of all Interrupt Service Routines (ISRs). */
typedef void ( * portISR_t )( void );
/* Constants required to access and manipulate the NVIC. */ /* Constants required to access and manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
@ -87,7 +90,6 @@
#define portMIN_INTERRUPT_PRIORITY ( 255UL ) #define portMIN_INTERRUPT_PRIORITY ( 255UL )
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL )
#define portNVIC_SVC_PRI ( ( ( uint32_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL ) << 24UL )
/* Constants required to manipulate the VFP. */ /* Constants required to manipulate the VFP. */
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34UL ) /* Floating point context control register. */ #define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34UL ) /* Floating point context control register. */
@ -99,6 +101,11 @@
#define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 ) #define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 )
#define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 ) #define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 )
/* Constants used to check the installation of the FreeRTOS interrupt handlers. */
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xE000ED08 ) )
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/* Constants required to check the validity of an interrupt priority. */ /* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
@ -386,7 +393,6 @@ void vSVCHandler_C( uint32_t * pulParam )
switch( ucSVCNumber ) switch( ucSVCNumber )
{ {
case portSVC_START_SCHEDULER: case portSVC_START_SCHEDULER:
portNVIC_SHPR2_REG |= portNVIC_SVC_PRI;
prvRestoreContextOfFirstTask(); prvRestoreContextOfFirstTask();
break; break;
@ -822,6 +828,40 @@ BaseType_t xPortStartScheduler( void )
configASSERT( portCPUID != portCORTEX_M7_r0p0_ID ); configASSERT( portCPUID != portCORTEX_M7_r0p0_ID );
#endif #endif
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions vPortSVCHandler and
* xPortPendSVHandler for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* vPortSVCHandler and xPortPendSVHandler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == vPortSVCHandler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == xPortPendSVHandler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
{ {
volatile uint8_t ucOriginalPriority; volatile uint8_t ucOriginalPriority;
@ -907,10 +947,11 @@ BaseType_t xPortStartScheduler( void )
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* Make PendSV and SysTick the same priority as the kernel, and the SVC /* Make PendSV and SysTick the same priority as the kernel, and the SVC
* handler higher priority so it can be used to exit a critical section (where * handler highest priority so it can be used to exit a critical section
* lower priorities are masked). */ * (where lower priorities are masked). */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;
/* Configure the regions in the MPU that are common to all tasks. */ /* Configure the regions in the MPU that are common to all tasks. */
prvSetupMPU(); prvSetupMPU();
@ -1196,6 +1237,7 @@ __asm void vPortEnableVFP( void )
orr r1, r1, #( 0xf << 20 ) /* Enable CP10 and CP11 coprocessors, then save back. */ orr r1, r1, #( 0xf << 20 ) /* Enable CP10 and CP11 coprocessors, then save back. */
str r1, [ r0 ] str r1, [ r0 ]
bx r14 bx r14
nop
/* *INDENT-ON* */ /* *INDENT-ON* */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -1466,7 +1508,16 @@ BaseType_t xPortIsAuthorizedToAccessBuffer( const void * pvBuffer,
BaseType_t xAccessGranted = pdFALSE; BaseType_t xAccessGranted = pdFALSE;
const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */ const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
if( xSchedulerRunning == pdFALSE )
{
/* Grant access to all the kernel objects before the scheduler
* is started. It is necessary because there is no task running
* yet and therefore, we cannot use the permissions of any
* task. */
xAccessGranted = pdTRUE;
}
else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
{ {
xAccessGranted = pdTRUE; xAccessGranted = pdTRUE;
} }

@ -1 +1 @@
Subproject commit d4cccca2971d6ffca581564f8142069cb854bd15 Subproject commit f051e9bff812aa3c10c5417e064671a1c4eeb314

View file

@ -51,6 +51,10 @@
*----------------------------------------------------------*/ *----------------------------------------------------------*/
#include "portmacro.h" #include "portmacro.h"
#ifdef __linux__
#define __USE_GNU
#endif
#include <errno.h> #include <errno.h>
#include <pthread.h> #include <pthread.h>
#include <signal.h> #include <signal.h>
@ -60,6 +64,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <sys/times.h> #include <sys/times.h>
#include <time.h> #include <time.h>
#include <unistd.h>
#ifdef __APPLE__ #ifdef __APPLE__
#include <mach/mach_vm.h> #include <mach/mach_vm.h>
@ -68,6 +73,7 @@
/* Scheduler includes. */ /* Scheduler includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "list.h"
#include "timers.h" #include "timers.h"
#include "utils/wait_for_event.h" #include "utils/wait_for_event.h"
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -81,6 +87,7 @@ typedef struct THREAD
void * pvParams; void * pvParams;
BaseType_t xDying; BaseType_t xDying;
struct event * ev; struct event * ev;
ListItem_t xThreadListItem;
} Thread_t; } Thread_t;
/* /*
@ -101,9 +108,11 @@ static sigset_t xAllSignals;
static sigset_t xSchedulerOriginalSignalMask; static sigset_t xSchedulerOriginalSignalMask;
static pthread_t hMainThread = ( pthread_t ) NULL; static pthread_t hMainThread = ( pthread_t ) NULL;
static volatile BaseType_t uxCriticalNesting; static volatile BaseType_t uxCriticalNesting;
/*-----------------------------------------------------------*/
static BaseType_t xSchedulerEnd = pdFALSE; static BaseType_t xSchedulerEnd = pdFALSE;
static pthread_t hTimerTickThread;
static bool xTimerTickThreadShouldRun;
static uint64_t prvStartTimeNs;
static List_t xThreadList;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSetupSignalsAndSchedulerPolicy( void ); static void prvSetupSignalsAndSchedulerPolicy( void );
@ -127,6 +136,17 @@ void prvFatalError( const char * pcCall,
fprintf( stderr, "%s: %s\n", pcCall, strerror( iErrno ) ); fprintf( stderr, "%s: %s\n", pcCall, strerror( iErrno ) );
abort(); abort();
} }
/*-----------------------------------------------------------*/
static void prvPortSetCurrentThreadName(char * pxThreadName)
{
#ifdef __APPLE__
pthread_setname_np(pxThreadName);
#else
pthread_setname_np(pthread_self(), pxThreadName);
#endif
}
/*-----------------------------------------------------------*/
/* /*
* See header file for description. * See header file for description.
@ -163,19 +183,27 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
thread->pvParams = pvParameters; thread->pvParams = pvParameters;
thread->xDying = pdFALSE; thread->xDying = pdFALSE;
/* Ensure ulStackSize is at least PTHREAD_STACK_MIN */
ulStackSize = (ulStackSize < PTHREAD_STACK_MIN) ? PTHREAD_STACK_MIN : ulStackSize;
pthread_attr_init( &xThreadAttributes ); pthread_attr_init( &xThreadAttributes );
iRet = pthread_attr_setstack( &xThreadAttributes, pxEndOfStack, ulStackSize ); iRet = pthread_attr_setstacksize( &xThreadAttributes, ulStackSize );
if( iRet != 0 ) if( iRet != 0 )
{ {
fprintf( stderr, "[WARN] pthread_attr_setstack failed with return value: %d. Default stack will be used.\n", iRet ); fprintf( stderr, "[WARN] pthread_attr_setstacksize failed with return value: %d. Default stack size will be used.\n", iRet );
fprintf( stderr, "[WARN] Increase the stack size to PTHREAD_STACK_MIN.\n" );
} }
thread->ev = event_create(); thread->ev = event_create();
vListInitialiseItem( &thread->xThreadListItem );
listSET_LIST_ITEM_OWNER( &thread->xThreadListItem, thread );
vPortEnterCritical(); vPortEnterCritical();
/* Add the new thread in xThreadList. */
vListInsertEnd( &xThreadList, &thread->xThreadListItem );
iRet = pthread_create( &thread->pthread, &xThreadAttributes, iRet = pthread_create( &thread->pthread, &xThreadAttributes,
prvWaitForStart, thread ); prvWaitForStart, thread );
@ -206,8 +234,11 @@ BaseType_t xPortStartScheduler( void )
{ {
int iSignal; int iSignal;
sigset_t xSignals; sigset_t xSignals;
ListItem_t * pxIterator;
const ListItem_t * pxEndMarker;
hMainThread = pthread_self(); hMainThread = pthread_self();
prvPortSetCurrentThreadName("Scheduler");
/* Start the timer that generates the tick ISR(SIGALRM). /* Start the timer that generates the tick ISR(SIGALRM).
* Interrupts are disabled here already. */ * Interrupts are disabled here already. */
@ -231,15 +262,28 @@ BaseType_t xPortStartScheduler( void )
sigwait( &xSignals, &iSignal ); sigwait( &xSignals, &iSignal );
} }
/* Cancel the Idle task and free its resources */ /* Cancel all the running thread. */
#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) pxEndMarker = listGET_END_MARKER( &xThreadList );
vPortCancelThread( xTaskGetIdleTaskHandle() );
#endif
#if ( configUSE_TIMERS == 1 ) for( pxIterator = listGET_HEAD_ENTRY( &xThreadList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) )
/* Cancel the Timer task and free its resources */ {
vPortCancelThread( xTimerGetTimerDaemonTaskHandle() ); Thread_t * pxThread = ( Thread_t * ) listGET_LIST_ITEM_OWNER( pxIterator );
#endif /* configUSE_TIMERS */
pthread_cancel( pxThread->pthread );
event_signal( pxThread->ev );
pthread_join( pxThread->pthread, NULL );
event_delete( pxThread->ev );
}
/*
* clear out the variable that is used to end the scheduler, otherwise
* subsequent scheduler restarts will end immediately.
*/
xSchedulerEnd = pdFALSE;
/* Reset the pthread_once_t structure. This is required if the port
* starts the scheduler again. */
hSigSetupThread = PTHREAD_ONCE_INIT;
/* Restore original signal mask. */ /* Restore original signal mask. */
( void ) pthread_sigmask( SIG_SETMASK, &xSchedulerOriginalSignalMask, NULL ); ( void ) pthread_sigmask( SIG_SETMASK, &xSchedulerOriginalSignalMask, NULL );
@ -250,30 +294,15 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
struct itimerval itimer; /* Stop the timer tick thread. */
struct sigaction sigtick; xTimerTickThreadShouldRun = false;
Thread_t * xCurrentThread; pthread_join( hTimerTickThread, NULL );
/* Stop the timer and ignore any pending SIGALRMs that would end
* up running on the main thread when it is resumed. */
itimer.it_value.tv_sec = 0;
itimer.it_value.tv_usec = 0;
itimer.it_interval.tv_sec = 0;
itimer.it_interval.tv_usec = 0;
( void ) setitimer( ITIMER_REAL, &itimer, NULL );
sigtick.sa_flags = 0;
sigtick.sa_handler = SIG_IGN;
sigemptyset( &sigtick.sa_mask );
sigaction( SIGALRM, &sigtick, NULL );
/* Signal the scheduler to exit its loop. */ /* Signal the scheduler to exit its loop. */
xSchedulerEnd = pdTRUE; xSchedulerEnd = pdTRUE;
( void ) pthread_kill( hMainThread, SIG_RESUME ); ( void ) pthread_kill( hMainThread, SIG_RESUME );
xCurrentThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); pthread_exit( NULL );
prvSuspendSelf( xCurrentThread );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -359,45 +388,41 @@ static uint64_t prvGetTimeNs( void )
return ( uint64_t ) t.tv_sec * ( uint64_t ) 1000000000UL + ( uint64_t ) t.tv_nsec; return ( uint64_t ) t.tv_sec * ( uint64_t ) 1000000000UL + ( uint64_t ) t.tv_nsec;
} }
/*-----------------------------------------------------------*/
static uint64_t prvStartTimeNs;
/* commented as part of the code below in vPortSystemTickHandler, /* commented as part of the code below in vPortSystemTickHandler,
* to adjust timing according to full demo requirements */ * to adjust timing according to full demo requirements */
/* static uint64_t prvTickCount; */ /* static uint64_t prvTickCount; */
static void * prvTimerTickHandler( void * arg )
{
( void ) arg;
prvPortSetCurrentThreadName("Scheduler timer");
while( xTimerTickThreadShouldRun )
{
/*
* signal to the active task to cause tick handling or
* preemption (if enabled)
*/
Thread_t * thread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
pthread_kill( thread->pthread, SIGALRM );
usleep( portTICK_RATE_MICROSECONDS );
}
return NULL;
}
/*-----------------------------------------------------------*/
/* /*
* Setup the systick timer to generate the tick interrupts at the required * Setup the systick timer to generate the tick interrupts at the required
* frequency. * frequency.
*/ */
void prvSetupTimerInterrupt( void ) void prvSetupTimerInterrupt( void )
{ {
struct itimerval itimer; xTimerTickThreadShouldRun = true;
int iRet; pthread_create( &hTimerTickThread, NULL, prvTimerTickHandler, NULL );
/* Initialise the structure with the current timer information. */
iRet = getitimer( ITIMER_REAL, &itimer );
if( iRet == -1 )
{
prvFatalError( "getitimer", errno );
}
/* Set the interval between timer events. */
itimer.it_interval.tv_sec = 0;
itimer.it_interval.tv_usec = portTICK_RATE_MICROSECONDS;
/* Set the current count-down. */
itimer.it_value.tv_sec = 0;
itimer.it_value.tv_usec = portTICK_RATE_MICROSECONDS;
/* Set-up the timer interrupt. */
iRet = setitimer( ITIMER_REAL, &itimer, NULL );
if( iRet == -1 )
{
prvFatalError( "setitimer", errno );
}
prvStartTimeNs = prvGetTimeNs(); prvStartTimeNs = prvGetTimeNs();
} }
@ -454,15 +479,22 @@ void vPortThreadDying( void * pxTaskToDelete,
pxThread->xDying = pdTRUE; pxThread->xDying = pdTRUE;
} }
/*-----------------------------------------------------------*/
void vPortCancelThread( void * pxTaskToDelete ) void vPortCancelThread( void * pxTaskToDelete )
{ {
Thread_t * pxThreadToCancel = prvGetThreadFromTask( pxTaskToDelete ); Thread_t * pxThreadToCancel = prvGetThreadFromTask( pxTaskToDelete );
/* Remove the thread from xThreadList. */
vPortEnterCritical();
uxListRemove( &pxThreadToCancel->xThreadListItem );
vPortExitCritical();
/* /*
* The thread has already been suspended so it can be safely cancelled. * The thread has already been suspended so it can be safely cancelled.
*/ */
pthread_cancel( pxThreadToCancel->pthread ); pthread_cancel( pxThreadToCancel->pthread );
event_signal( pxThreadToCancel->ev );
pthread_join( pxThreadToCancel->pthread, NULL ); pthread_join( pxThreadToCancel->pthread, NULL );
event_delete( pxThreadToCancel->ev ); event_delete( pxThreadToCancel->ev );
} }
@ -478,6 +510,9 @@ static void * prvWaitForStart( void * pvParams )
uxCriticalNesting = 0; uxCriticalNesting = 0;
vPortEnableInterrupts(); vPortEnableInterrupts();
/* Set thread name */
prvPortSetCurrentThreadName(pcTaskGetName(xTaskGetCurrentTaskHandle()));
/* Call the task's entry point. */ /* Call the task's entry point. */
pxThread->pxCode( pxThread->pvParams ); pxThread->pxCode( pxThread->pvParams );
@ -538,6 +573,7 @@ static void prvSuspendSelf( Thread_t * thread )
* - A thread with all signals blocked with pthread_sigmask(). * - A thread with all signals blocked with pthread_sigmask().
*/ */
event_wait( thread->ev ); event_wait( thread->ev );
pthread_testcancel();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -558,6 +594,9 @@ static void prvSetupSignalsAndSchedulerPolicy( void )
hMainThread = pthread_self(); hMainThread = pthread_self();
/* Setup thread list to record all the task which are not deleted. */
vListInitialise( &xThreadList );
/* Initialise common signal masks. */ /* Initialise common signal masks. */
sigfillset( &xAllSignals ); sigfillset( &xAllSignals );

View file

@ -1,52 +0,0 @@
/*
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: MIT AND BSD-3-Clause
*
* 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
*/
#include "FreeRTOS.h"
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
StackType_t ** ppxIdleTaskStackBuffer,
uint32_t * pulIdleTaskStackSize )
{
/* If the buffers to be provided to the Idle task are declared inside this
* function then they must be declared static - otherwise they will be allocated on
* the stack and so not exists after this function exits. */
static StaticTask_t xIdleTaskTCB;
static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
/* Pass out a pointer to the StaticTask_t structure in which the Idle task's
* state will be stored. */
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
/* Pass out the array that will be used as the Idle task's stack. */
*ppxIdleTaskStackBuffer = uxIdleTaskStack;
/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
* Note that, as the array is necessarily of type StackType_t,
* configMINIMAL_STACK_SIZE is specified in words, not bytes. */
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}

View file

@ -46,9 +46,9 @@ target_compile_definitions(FreeRTOS-Kernel INTERFACE
add_library(FreeRTOS-Kernel-Static INTERFACE) add_library(FreeRTOS-Kernel-Static INTERFACE)
target_compile_definitions(FreeRTOS-Kernel-Static INTERFACE target_compile_definitions(FreeRTOS-Kernel-Static INTERFACE
configSUPPORT_STATIC_ALLOCATION=1 configSUPPORT_STATIC_ALLOCATION=1
configKERNEL_PROVIDED_STATIC_MEMORY=1
) )
target_sources(FreeRTOS-Kernel-Static INTERFACE ${CMAKE_CURRENT_LIST_DIR}/idle_task_static_memory.c)
target_link_libraries(FreeRTOS-Kernel-Static INTERFACE FreeRTOS-Kernel) target_link_libraries(FreeRTOS-Kernel-Static INTERFACE FreeRTOS-Kernel)
add_library(FreeRTOS-Kernel-Heap1 INTERFACE) add_library(FreeRTOS-Kernel-Heap1 INTERFACE)

@ -1 +1 @@
Subproject commit d38f59dbcdfabbe71361764e194e1ad6202f902c Subproject commit da0185fbf1215706af66d020a67edf912193979a

View file

@ -37,39 +37,34 @@
/* Defined in portasm.h */ /* Defined in portasm.h */
extern void _frxt_tick_timer_init( void ); extern void _frxt_tick_timer_init(void);
/* Defined in xtensa_context.S */ /* Defined in xtensa_context.S */
extern void _xt_coproc_init( void ); extern void _xt_coproc_init(void);
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* We require the address of the pxCurrentTCB variable, but don't want to know /* We require the address of the pxCurrentTCB variable, but don't want to know
* any details of its type. */ any details of its type. */
typedef void TCB_t; typedef void TCB_t;
extern volatile TCB_t * volatile pxCurrentTCB; extern volatile TCB_t * volatile pxCurrentTCB;
unsigned port_xSchedulerRunning = 0; /* Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting */ unsigned port_xSchedulerRunning = 0; // Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting
unsigned port_interruptNesting = 0; /* Interrupt nesting level */ unsigned port_interruptNesting = 0; // Interrupt nesting level
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* User exception dispatcher when exiting */ // User exception dispatcher when exiting
void _xt_user_exit( void ); void _xt_user_exit(void);
/* /*
* Stack initialization * Stack initialization
*/ */
#if portUSING_MPU_WRAPPERS #if portUSING_MPU_WRAPPERS
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged )
TaskFunction_t pxCode,
void * pvParameters,
BaseType_t xRunPrivileged )
#else #else
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
#endif #endif
{ {
StackType_t * sp; StackType_t * sp;
@ -134,14 +129,14 @@ void _xt_user_exit( void );
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the Xtensa port will get stopped. If required simply /* It is unlikely that the Xtensa port will get stopped. If required simply
* disable the tick interrupt here. */ disable the tick interrupt here. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* Interrupts are disabled at this point and stack contains PS with enabled interrupts when task context is restored */ // Interrupts are disabled at this point and stack contains PS with enabled interrupts when task context is restored
#if XCHAL_CP_NUM > 0 #if XCHAL_CP_NUM > 0
/* Initialize co-processor management for tasks. Leave CPENABLE alone. */ /* Initialize co-processor management for tasks. Leave CPENABLE alone. */
@ -155,14 +150,14 @@ BaseType_t xPortStartScheduler( void )
_frxt_tick_timer_init(); _frxt_tick_timer_init();
#if XT_USE_THREAD_SAFE_CLIB #if XT_USE_THREAD_SAFE_CLIB
/* Init C library */ // Init C library
vPortClibInit(); vPortClibInit();
#endif #endif
port_xSchedulerRunning = 1; port_xSchedulerRunning = 1;
/* Cannot be directly called from C; never returns */ // Cannot be directly called from C; never returns
__asm__ volatile ( "call0 _frxt_dispatch\n" ); __asm__ volatile ("call0 _frxt_dispatch\n");
/* Should not get here. */ /* Should not get here. */
return pdTRUE; return pdTRUE;
@ -195,13 +190,13 @@ BaseType_t xPortSysTickHandler( void )
* Used to set coprocessor area in stack. Current hack is to reuse MPU pointer for coprocessor area. * Used to set coprocessor area in stack. Current hack is to reuse MPU pointer for coprocessor area.
*/ */
#if portUSING_MPU_WRAPPERS #if portUSING_MPU_WRAPPERS
void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
const struct xMEMORY_REGION * const xRegions, const struct xMEMORY_REGION * const xRegions,
StackType_t * pxBottomOfStack, StackType_t * pxBottomOfStack,
uint32_t ulStackDepth ) uint32_t ulStackDepth )
{ {
#if XCHAL_CP_NUM > 0 #if XCHAL_CP_NUM > 0
xMPUSettings->coproc_area = ( StackType_t * ) ( ( uint32_t ) ( pxBottomOfStack + ulStackDepth - 1 ) ); xMPUSettings->coproc_area = ( StackType_t * ) ( ( uint32_t ) ( pxBottomOfStack + ulStackDepth - 1 ));
xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) xMPUSettings->coproc_area ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) xMPUSettings->coproc_area ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( uint32_t ) xMPUSettings->coproc_area - XT_CP_SIZE ) & ~0xf ); xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( uint32_t ) xMPUSettings->coproc_area - XT_CP_SIZE ) & ~0xf );
@ -209,5 +204,5 @@ BaseType_t xPortSysTickHandler( void )
* clear the stack area after we return. This is done in pxPortInitialiseStack(). * clear the stack area after we return. This is done in pxPortInitialiseStack().
*/ */
#endif #endif
} }
#endif /* if portUSING_MPU_WRAPPERS */ #endif /* if portUSING_MPU_WRAPPERS */

View file

@ -42,7 +42,7 @@
#endif #endif
#define portbenchmarkINTERRUPT_DISABLE() #define portbenchmarkINTERRUPT_DISABLE()
#define portbenchmarkINTERRUPT_RESTORE( newstate ) #define portbenchmarkINTERRUPT_RESTORE(newstate)
#define portbenchmarkIntLatency() #define portbenchmarkIntLatency()
#define portbenchmarkIntWait() #define portbenchmarkIntWait()
#define portbenchmarkReset() #define portbenchmarkReset()

Some files were not shown because too many files have changed in this diff Show more