mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-09-12 09:07:46 -04:00
Merge branch 'master' of https://github.com/FreeRTOS/FreeRTOS-Kernel
This commit is contained in:
commit
6948c79cda
52 changed files with 4417 additions and 230 deletions
36
.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal file
36
.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve our code.
|
||||||
|
title: "[BUG]"
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A concise description of what the bug is.
|
||||||
|
|
||||||
|
**Target**
|
||||||
|
- Development board: [e.g. HiFive11 RevB]
|
||||||
|
- Instruction Set Architecture: [e.g. RV32IMAC]
|
||||||
|
- IDE and version: [e.g. Freedom Studio 4.12.0.2019-08-2]
|
||||||
|
- Toolchain and version: [e.g. riscv64-unknown-elf-gcc-8.3.0-2019.08.0]
|
||||||
|
|
||||||
|
**Host**
|
||||||
|
- Host OS: [e.g. MacOS]
|
||||||
|
- Version: [e.g. Mojave 10.14.6]
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
- Use project ... and configure with ...
|
||||||
|
- Run on ... and could observe ...
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
|
e.g. code snippet to reproduce the issue.
|
||||||
|
e.g. stack trace, memory dump, debugger log, and many etc.
|
21
.github/ISSUE_TEMPLATE/documentation-issue.md
vendored
Normal file
21
.github/ISSUE_TEMPLATE/documentation-issue.md
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
name: Documentation issue
|
||||||
|
about: Create a report to help us improve our documentation.
|
||||||
|
title: "[DOC]"
|
||||||
|
labels: documentation
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the issue**
|
||||||
|
Please describe the issue and expected clarification in concise language.
|
||||||
|
|
||||||
|
**Reference**
|
||||||
|
Please attach the URL at which you are experiencing the issue.
|
||||||
|
|
||||||
|
**Screenshot**
|
||||||
|
If applicable, please attach screenshot.
|
||||||
|
|
||||||
|
**Browser**
|
||||||
|
- Browser: [e.g. Chrome]
|
||||||
|
- Version: [e.g. 80.0.3987.132]
|
12
.github/ISSUE_TEMPLATE/general-inquiry.md
vendored
Normal file
12
.github/ISSUE_TEMPLATE/general-inquiry.md
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
name: General inquiry
|
||||||
|
about: Free form communication.
|
||||||
|
title: "[Inquiry]"
|
||||||
|
labels: question
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
We do encourage you to take a look at [FreeRTOS official site](https://www.freertos.org) for general information and [FreeRTOS forum](https://forums.freertos.org) to access our community.
|
||||||
|
|
||||||
|
If still needed, could create a general inquiry report here.
|
16
.github/pull_request_template.md
vendored
Normal file
16
.github/pull_request_template.md
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<!--- Title -->
|
||||||
|
|
||||||
|
Description
|
||||||
|
-----------
|
||||||
|
<!--- Describe your changes in detail. -->
|
||||||
|
|
||||||
|
Test Steps
|
||||||
|
-----------
|
||||||
|
<!-- Describe the steps to reproduce. -->
|
||||||
|
|
||||||
|
Related Issue
|
||||||
|
-----------
|
||||||
|
<!-- If any, please provide issue ID. -->
|
||||||
|
|
||||||
|
|
||||||
|
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
|
8
GitHub-FreeRTOS-Kernel-Home.url
Normal file
8
GitHub-FreeRTOS-Kernel-Home.url
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[{000214A0-0000-0000-C000-000000000046}]
|
||||||
|
Prop3=19,2
|
||||||
|
[InternetShortcut]
|
||||||
|
URL=https://github.com/FreeRTOS/FreeRTOS-Kernel
|
||||||
|
IconIndex=0
|
||||||
|
IDList=
|
||||||
|
HotKey=0
|
||||||
|
|
5
SECURITY.md
Normal file
5
SECURITY.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security
|
||||||
|
via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/) or directly via email to aws-security@amazon.com.
|
||||||
|
Please do **not** create a public github issue.
|
|
@ -71,25 +71,32 @@
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to manipulate the NVIC.
|
* @brief Constants required to manipulate the NVIC.
|
||||||
*/
|
*/
|
||||||
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
|
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||||
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 )
|
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||||
#define portNVIC_SYSTICK_CURRENT_VALUE ( ( volatile uint32_t * ) 0xe000e018 )
|
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||||
#define portNVIC_INT_CTRL ( ( volatile uint32_t * ) 0xe000ed04 )
|
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
#define portNVIC_SYSPRI2 ( ( volatile uint32_t * ) 0xe000ed20 )
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
#define portNVIC_SYSTICK_CLK ( 0x00000004 )
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
#define portNVIC_SYSTICK_INT ( 0x00000002 )
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001 )
|
|
||||||
#define portNVIC_PENDSVSET ( 0x10000000 )
|
|
||||||
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||||
#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 )
|
||||||
|
#ifndef configSYSTICK_CLOCK_HZ
|
||||||
|
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||||
|
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
|
#else
|
||||||
|
/* The way the SysTick is clocked is not modified in case it is not the
|
||||||
|
* same a the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||||
|
#endif
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 )
|
||||||
#define portSCB_MEM_FAULT_ENABLE ( 1UL << 16UL )
|
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -169,15 +176,30 @@
|
||||||
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
||||||
|
|
||||||
/* Enable privileged access to unmapped region. */
|
/* Enable privileged access to unmapped region. */
|
||||||
#define portMPU_PRIV_BACKGROUND_ENABLE ( 1UL << 2UL )
|
#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL )
|
||||||
|
|
||||||
/* Enable MPU. */
|
/* Enable MPU. */
|
||||||
#define portMPU_ENABLE ( 1UL << 0UL )
|
#define portMPU_ENABLE_BIT ( 1UL << 0UL )
|
||||||
|
|
||||||
/* Expected value of the portMPU_TYPE register. */
|
/* Expected value of the portMPU_TYPE register. */
|
||||||
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum 24-bit number.
|
||||||
|
*
|
||||||
|
* It is needed because the systick is a 24-bit counter.
|
||||||
|
*/
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A fiddle factor to estimate the number of SysTick counts that would
|
||||||
|
* have occurred while the SysTick counter is stopped during tickless idle
|
||||||
|
* calculations.
|
||||||
|
*/
|
||||||
|
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to set up the initial stack.
|
* @brief Constants required to set up the initial stack.
|
||||||
*/
|
*/
|
||||||
|
@ -332,17 +354,211 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
|
||||||
*/
|
*/
|
||||||
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
||||||
#endif /* configENABLE_TRUSTZONE */
|
#endif /* configENABLE_TRUSTZONE */
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
/**
|
||||||
|
* @brief The number of SysTick increments that make up one tick period.
|
||||||
|
*/
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum number of tick periods that can be suppressed is
|
||||||
|
* limited by the 24 bit resolution of the SysTick timer.
|
||||||
|
*/
|
||||||
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compensate for the CPU cycles that pass while the SysTick is
|
||||||
|
* stopped (low power functionality only).
|
||||||
|
*/
|
||||||
|
static uint32_t ulStoppedTimerCompensation = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
__attribute__(( weak )) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||||
|
{
|
||||||
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
|
||||||
|
TickType_t xModifiableIdleTime;
|
||||||
|
|
||||||
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||||
|
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||||
|
{
|
||||||
|
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the SysTick momentarily. The time the SysTick is stopped for is
|
||||||
|
* accounted for as best it can be, but using the tickless mode will
|
||||||
|
* inevitably result in some tiny drift of the time maintained by the
|
||||||
|
* kernel with respect to calendar time. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||||
|
* tick periods. -1 is used because this code will execute part way
|
||||||
|
* through one of the tick periods. */
|
||||||
|
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||||
|
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||||
|
{
|
||||||
|
ulReloadValue -= ulStoppedTimerCompensation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||||
|
* method as that will mask interrupts that should exit sleep mode. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* If a context switch is pending or a task is waiting for the scheduler
|
||||||
|
* to be un-suspended then abandon the low power entry. */
|
||||||
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
* this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
* periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||||
|
* above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the new reload value. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||||
|
|
||||||
|
/* Clear the SysTick count flag and set the count value back to
|
||||||
|
* zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||||
|
* set its parameter to 0 to indicate that its implementation
|
||||||
|
* contains its own wait for interrupt or wait for event
|
||||||
|
* instruction, and so wfi should not be executed again. However,
|
||||||
|
* the original expected idle time variable must remain unmodified,
|
||||||
|
* so a copy is taken. */
|
||||||
|
xModifiableIdleTime = xExpectedIdleTime;
|
||||||
|
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||||
|
if( xModifiableIdleTime > 0 )
|
||||||
|
{
|
||||||
|
__asm volatile( "dsb" ::: "memory" );
|
||||||
|
__asm volatile( "wfi" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
}
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||||
|
* out of sleep mode to execute immediately. See comments above
|
||||||
|
* the cpsid instruction above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable interrupts again because the clock is about to be stopped
|
||||||
|
* and interrupts that execute while the clock is stopped will
|
||||||
|
* increase any slippage between the time maintained by the RTOS and
|
||||||
|
* calendar time. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable the SysTick clock without reading the
|
||||||
|
* portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||||
|
* portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set.
|
||||||
|
* Again, the time the SysTick is stopped for is accounted for as
|
||||||
|
* best it can be, but using the tickless mode will inevitably
|
||||||
|
* result in some tiny drift of the time maintained by the kernel
|
||||||
|
* with respect to calendar time*/
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
|
||||||
|
|
||||||
|
/* Determine if the SysTick clock has already counted to zero and
|
||||||
|
* been set back to the current reload value (the reload back being
|
||||||
|
* correct for the entire expected idle time) or if the SysTick is
|
||||||
|
* yet to count to zero (in which case an interrupt other than the
|
||||||
|
* SysTick must have brought the system out of sleep mode). */
|
||||||
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt is already pending, and the SysTick count
|
||||||
|
* reloaded with ulReloadValue. Reset the
|
||||||
|
* portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
|
* period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
* underflowed because the post sleep hook did something
|
||||||
|
* that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* As the pending tick will be processed as soon as this
|
||||||
|
* function exits, the tick value maintained by the tick is
|
||||||
|
* stepped forward by one less than the time spent waiting. */
|
||||||
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep.
|
||||||
|
* Work out how long the sleep lasted rounded to complete tick
|
||||||
|
* periods (not the ulReload value which accounted for part
|
||||||
|
* ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* How many complete tick periods passed while the processor
|
||||||
|
* was waiting? */
|
||||||
|
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||||
|
|
||||||
|
/* The reload value is set to whatever fraction of a single tick
|
||||||
|
* period remains. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||||
|
* again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||||
|
* value. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Exit with interrupts enabled. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
/* Stop and reset the SysTick. */
|
/* Stop and reset the SysTick. */
|
||||||
*( portNVIC_SYSTICK_CTRL ) = 0UL;
|
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||||
*( portNVIC_SYSTICK_CURRENT_VALUE ) = 0UL;
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
/* Configure SysTick to interrupt at the requested rate. */
|
/* Configure SysTick to interrupt at the requested rate. */
|
||||||
*( portNVIC_SYSTICK_LOAD ) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||||
*( portNVIC_SYSTICK_CTRL ) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -446,11 +662,11 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
( portMPU_RLAR_REGION_ENABLE );
|
( portMPU_RLAR_REGION_ENABLE );
|
||||||
|
|
||||||
/* Enable mem fault. */
|
/* Enable mem fault. */
|
||||||
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE;
|
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
|
||||||
|
|
||||||
/* Enable MPU with privileged background access i.e. unmapped
|
/* Enable MPU with privileged background access i.e. unmapped
|
||||||
* regions have privileged access. */
|
* regions have privileged access. */
|
||||||
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE | portMPU_ENABLE );
|
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* configENABLE_MPU */
|
#endif /* configENABLE_MPU */
|
||||||
|
@ -484,7 +700,7 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Set a PendSV to request a context switch. */
|
/* Set a PendSV to request a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
|
||||||
/* Barriers are normally not required but do ensure the code is
|
/* Barriers are normally not required but do ensure the code is
|
||||||
* completely within the specified behaviour for the architecture. */
|
* completely within the specified behaviour for the architecture. */
|
||||||
|
@ -527,7 +743,7 @@ uint32_t ulPreviousMask;
|
||||||
if( xTaskIncrementTick() != pdFALSE )
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
{
|
{
|
||||||
/* Pend a context switch. */
|
/* Pend a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||||
|
@ -772,8 +988,8 @@ uint8_t ucSVCNumber;
|
||||||
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
#if( configENABLE_MPU == 1 )
|
#if( configENABLE_MPU == 1 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -227,6 +227,15 @@ typedef struct MPU_SETTINGS
|
||||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tickless idle/low power functionality.
|
||||||
|
*/
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -227,6 +227,15 @@ typedef struct MPU_SETTINGS
|
||||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tickless idle/low power functionality.
|
||||||
|
*/
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -227,6 +227,15 @@ typedef struct MPU_SETTINGS
|
||||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tickless idle/low power functionality.
|
||||||
|
*/
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -227,6 +227,15 @@ typedef struct MPU_SETTINGS
|
||||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tickless idle/low power functionality.
|
||||||
|
*/
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -216,6 +216,15 @@ typedef struct MPU_SETTINGS
|
||||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tickless idle/low power functionality.
|
||||||
|
*/
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Critical section management.
|
* @brief Critical section management.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -227,6 +227,15 @@ typedef struct MPU_SETTINGS
|
||||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tickless idle/low power functionality.
|
||||||
|
*/
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -227,6 +227,15 @@ typedef struct MPU_SETTINGS
|
||||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tickless idle/low power functionality.
|
||||||
|
*/
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -227,6 +227,15 @@ typedef struct MPU_SETTINGS
|
||||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tickless idle/low power functionality.
|
||||||
|
*/
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -73,6 +73,7 @@ typedef unsigned long UBaseType_t;
|
||||||
#define portSTACK_GROWTH ( -1 )
|
#define portSTACK_GROWTH ( -1 )
|
||||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
#define portBYTE_ALIGNMENT 8
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
#define portDONT_DISCARD __attribute__(( used ))
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -71,25 +71,32 @@
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to manipulate the NVIC.
|
* @brief Constants required to manipulate the NVIC.
|
||||||
*/
|
*/
|
||||||
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
|
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||||
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 )
|
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||||
#define portNVIC_SYSTICK_CURRENT_VALUE ( ( volatile uint32_t * ) 0xe000e018 )
|
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||||
#define portNVIC_INT_CTRL ( ( volatile uint32_t * ) 0xe000ed04 )
|
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
#define portNVIC_SYSPRI2 ( ( volatile uint32_t * ) 0xe000ed20 )
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
#define portNVIC_SYSTICK_CLK ( 0x00000004 )
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
#define portNVIC_SYSTICK_INT ( 0x00000002 )
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001 )
|
|
||||||
#define portNVIC_PENDSVSET ( 0x10000000 )
|
|
||||||
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||||
#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 )
|
||||||
|
#ifndef configSYSTICK_CLOCK_HZ
|
||||||
|
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||||
|
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
|
#else
|
||||||
|
/* The way the SysTick is clocked is not modified in case it is not the
|
||||||
|
* same a the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||||
|
#endif
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 )
|
||||||
#define portSCB_MEM_FAULT_ENABLE ( 1UL << 16UL )
|
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -169,15 +176,30 @@
|
||||||
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
||||||
|
|
||||||
/* Enable privileged access to unmapped region. */
|
/* Enable privileged access to unmapped region. */
|
||||||
#define portMPU_PRIV_BACKGROUND_ENABLE ( 1UL << 2UL )
|
#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL )
|
||||||
|
|
||||||
/* Enable MPU. */
|
/* Enable MPU. */
|
||||||
#define portMPU_ENABLE ( 1UL << 0UL )
|
#define portMPU_ENABLE_BIT ( 1UL << 0UL )
|
||||||
|
|
||||||
/* Expected value of the portMPU_TYPE register. */
|
/* Expected value of the portMPU_TYPE register. */
|
||||||
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum 24-bit number.
|
||||||
|
*
|
||||||
|
* It is needed because the systick is a 24-bit counter.
|
||||||
|
*/
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A fiddle factor to estimate the number of SysTick counts that would
|
||||||
|
* have occurred while the SysTick counter is stopped during tickless idle
|
||||||
|
* calculations.
|
||||||
|
*/
|
||||||
|
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to set up the initial stack.
|
* @brief Constants required to set up the initial stack.
|
||||||
*/
|
*/
|
||||||
|
@ -332,17 +354,211 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
|
||||||
*/
|
*/
|
||||||
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
||||||
#endif /* configENABLE_TRUSTZONE */
|
#endif /* configENABLE_TRUSTZONE */
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
/**
|
||||||
|
* @brief The number of SysTick increments that make up one tick period.
|
||||||
|
*/
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum number of tick periods that can be suppressed is
|
||||||
|
* limited by the 24 bit resolution of the SysTick timer.
|
||||||
|
*/
|
||||||
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compensate for the CPU cycles that pass while the SysTick is
|
||||||
|
* stopped (low power functionality only).
|
||||||
|
*/
|
||||||
|
static uint32_t ulStoppedTimerCompensation = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
__attribute__(( weak )) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||||
|
{
|
||||||
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
|
||||||
|
TickType_t xModifiableIdleTime;
|
||||||
|
|
||||||
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||||
|
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||||
|
{
|
||||||
|
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the SysTick momentarily. The time the SysTick is stopped for is
|
||||||
|
* accounted for as best it can be, but using the tickless mode will
|
||||||
|
* inevitably result in some tiny drift of the time maintained by the
|
||||||
|
* kernel with respect to calendar time. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||||
|
* tick periods. -1 is used because this code will execute part way
|
||||||
|
* through one of the tick periods. */
|
||||||
|
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||||
|
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||||
|
{
|
||||||
|
ulReloadValue -= ulStoppedTimerCompensation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||||
|
* method as that will mask interrupts that should exit sleep mode. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* If a context switch is pending or a task is waiting for the scheduler
|
||||||
|
* to be un-suspended then abandon the low power entry. */
|
||||||
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
* this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
* periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||||
|
* above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the new reload value. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||||
|
|
||||||
|
/* Clear the SysTick count flag and set the count value back to
|
||||||
|
* zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||||
|
* set its parameter to 0 to indicate that its implementation
|
||||||
|
* contains its own wait for interrupt or wait for event
|
||||||
|
* instruction, and so wfi should not be executed again. However,
|
||||||
|
* the original expected idle time variable must remain unmodified,
|
||||||
|
* so a copy is taken. */
|
||||||
|
xModifiableIdleTime = xExpectedIdleTime;
|
||||||
|
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||||
|
if( xModifiableIdleTime > 0 )
|
||||||
|
{
|
||||||
|
__asm volatile( "dsb" ::: "memory" );
|
||||||
|
__asm volatile( "wfi" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
}
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||||
|
* out of sleep mode to execute immediately. See comments above
|
||||||
|
* the cpsid instruction above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable interrupts again because the clock is about to be stopped
|
||||||
|
* and interrupts that execute while the clock is stopped will
|
||||||
|
* increase any slippage between the time maintained by the RTOS and
|
||||||
|
* calendar time. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable the SysTick clock without reading the
|
||||||
|
* portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||||
|
* portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set.
|
||||||
|
* Again, the time the SysTick is stopped for is accounted for as
|
||||||
|
* best it can be, but using the tickless mode will inevitably
|
||||||
|
* result in some tiny drift of the time maintained by the kernel
|
||||||
|
* with respect to calendar time*/
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
|
||||||
|
|
||||||
|
/* Determine if the SysTick clock has already counted to zero and
|
||||||
|
* been set back to the current reload value (the reload back being
|
||||||
|
* correct for the entire expected idle time) or if the SysTick is
|
||||||
|
* yet to count to zero (in which case an interrupt other than the
|
||||||
|
* SysTick must have brought the system out of sleep mode). */
|
||||||
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt is already pending, and the SysTick count
|
||||||
|
* reloaded with ulReloadValue. Reset the
|
||||||
|
* portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
|
* period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
* underflowed because the post sleep hook did something
|
||||||
|
* that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* As the pending tick will be processed as soon as this
|
||||||
|
* function exits, the tick value maintained by the tick is
|
||||||
|
* stepped forward by one less than the time spent waiting. */
|
||||||
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep.
|
||||||
|
* Work out how long the sleep lasted rounded to complete tick
|
||||||
|
* periods (not the ulReload value which accounted for part
|
||||||
|
* ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* How many complete tick periods passed while the processor
|
||||||
|
* was waiting? */
|
||||||
|
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||||
|
|
||||||
|
/* The reload value is set to whatever fraction of a single tick
|
||||||
|
* period remains. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||||
|
* again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||||
|
* value. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Exit with interrupts enabled. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
/* Stop and reset the SysTick. */
|
/* Stop and reset the SysTick. */
|
||||||
*( portNVIC_SYSTICK_CTRL ) = 0UL;
|
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||||
*( portNVIC_SYSTICK_CURRENT_VALUE ) = 0UL;
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
/* Configure SysTick to interrupt at the requested rate. */
|
/* Configure SysTick to interrupt at the requested rate. */
|
||||||
*( portNVIC_SYSTICK_LOAD ) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||||
*( portNVIC_SYSTICK_CTRL ) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -446,11 +662,11 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
( portMPU_RLAR_REGION_ENABLE );
|
( portMPU_RLAR_REGION_ENABLE );
|
||||||
|
|
||||||
/* Enable mem fault. */
|
/* Enable mem fault. */
|
||||||
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE;
|
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
|
||||||
|
|
||||||
/* Enable MPU with privileged background access i.e. unmapped
|
/* Enable MPU with privileged background access i.e. unmapped
|
||||||
* regions have privileged access. */
|
* regions have privileged access. */
|
||||||
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE | portMPU_ENABLE );
|
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* configENABLE_MPU */
|
#endif /* configENABLE_MPU */
|
||||||
|
@ -484,7 +700,7 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Set a PendSV to request a context switch. */
|
/* Set a PendSV to request a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
|
||||||
/* Barriers are normally not required but do ensure the code is
|
/* Barriers are normally not required but do ensure the code is
|
||||||
* completely within the specified behaviour for the architecture. */
|
* completely within the specified behaviour for the architecture. */
|
||||||
|
@ -527,7 +743,7 @@ uint32_t ulPreviousMask;
|
||||||
if( xTaskIncrementTick() != pdFALSE )
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
{
|
{
|
||||||
/* Pend a context switch. */
|
/* Pend a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||||
|
@ -772,8 +988,8 @@ uint8_t ucSVCNumber;
|
||||||
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
#if( configENABLE_MPU == 1 )
|
#if( configENABLE_MPU == 1 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -227,6 +227,15 @@ typedef struct MPU_SETTINGS
|
||||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tickless idle/low power functionality.
|
||||||
|
*/
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -71,25 +71,32 @@
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to manipulate the NVIC.
|
* @brief Constants required to manipulate the NVIC.
|
||||||
*/
|
*/
|
||||||
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
|
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||||
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 )
|
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||||
#define portNVIC_SYSTICK_CURRENT_VALUE ( ( volatile uint32_t * ) 0xe000e018 )
|
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||||
#define portNVIC_INT_CTRL ( ( volatile uint32_t * ) 0xe000ed04 )
|
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
#define portNVIC_SYSPRI2 ( ( volatile uint32_t * ) 0xe000ed20 )
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
#define portNVIC_SYSTICK_CLK ( 0x00000004 )
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
#define portNVIC_SYSTICK_INT ( 0x00000002 )
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001 )
|
|
||||||
#define portNVIC_PENDSVSET ( 0x10000000 )
|
|
||||||
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||||
#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 )
|
||||||
|
#ifndef configSYSTICK_CLOCK_HZ
|
||||||
|
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||||
|
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
|
#else
|
||||||
|
/* The way the SysTick is clocked is not modified in case it is not the
|
||||||
|
* same a the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||||
|
#endif
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 )
|
||||||
#define portSCB_MEM_FAULT_ENABLE ( 1UL << 16UL )
|
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -169,15 +176,30 @@
|
||||||
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
||||||
|
|
||||||
/* Enable privileged access to unmapped region. */
|
/* Enable privileged access to unmapped region. */
|
||||||
#define portMPU_PRIV_BACKGROUND_ENABLE ( 1UL << 2UL )
|
#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL )
|
||||||
|
|
||||||
/* Enable MPU. */
|
/* Enable MPU. */
|
||||||
#define portMPU_ENABLE ( 1UL << 0UL )
|
#define portMPU_ENABLE_BIT ( 1UL << 0UL )
|
||||||
|
|
||||||
/* Expected value of the portMPU_TYPE register. */
|
/* Expected value of the portMPU_TYPE register. */
|
||||||
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum 24-bit number.
|
||||||
|
*
|
||||||
|
* It is needed because the systick is a 24-bit counter.
|
||||||
|
*/
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A fiddle factor to estimate the number of SysTick counts that would
|
||||||
|
* have occurred while the SysTick counter is stopped during tickless idle
|
||||||
|
* calculations.
|
||||||
|
*/
|
||||||
|
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to set up the initial stack.
|
* @brief Constants required to set up the initial stack.
|
||||||
*/
|
*/
|
||||||
|
@ -332,17 +354,211 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
|
||||||
*/
|
*/
|
||||||
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
||||||
#endif /* configENABLE_TRUSTZONE */
|
#endif /* configENABLE_TRUSTZONE */
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
/**
|
||||||
|
* @brief The number of SysTick increments that make up one tick period.
|
||||||
|
*/
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum number of tick periods that can be suppressed is
|
||||||
|
* limited by the 24 bit resolution of the SysTick timer.
|
||||||
|
*/
|
||||||
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compensate for the CPU cycles that pass while the SysTick is
|
||||||
|
* stopped (low power functionality only).
|
||||||
|
*/
|
||||||
|
static uint32_t ulStoppedTimerCompensation = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
__attribute__(( weak )) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||||
|
{
|
||||||
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
|
||||||
|
TickType_t xModifiableIdleTime;
|
||||||
|
|
||||||
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||||
|
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||||
|
{
|
||||||
|
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the SysTick momentarily. The time the SysTick is stopped for is
|
||||||
|
* accounted for as best it can be, but using the tickless mode will
|
||||||
|
* inevitably result in some tiny drift of the time maintained by the
|
||||||
|
* kernel with respect to calendar time. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||||
|
* tick periods. -1 is used because this code will execute part way
|
||||||
|
* through one of the tick periods. */
|
||||||
|
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||||
|
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||||
|
{
|
||||||
|
ulReloadValue -= ulStoppedTimerCompensation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||||
|
* method as that will mask interrupts that should exit sleep mode. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* If a context switch is pending or a task is waiting for the scheduler
|
||||||
|
* to be un-suspended then abandon the low power entry. */
|
||||||
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
* this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
* periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||||
|
* above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the new reload value. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||||
|
|
||||||
|
/* Clear the SysTick count flag and set the count value back to
|
||||||
|
* zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||||
|
* set its parameter to 0 to indicate that its implementation
|
||||||
|
* contains its own wait for interrupt or wait for event
|
||||||
|
* instruction, and so wfi should not be executed again. However,
|
||||||
|
* the original expected idle time variable must remain unmodified,
|
||||||
|
* so a copy is taken. */
|
||||||
|
xModifiableIdleTime = xExpectedIdleTime;
|
||||||
|
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||||
|
if( xModifiableIdleTime > 0 )
|
||||||
|
{
|
||||||
|
__asm volatile( "dsb" ::: "memory" );
|
||||||
|
__asm volatile( "wfi" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
}
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||||
|
* out of sleep mode to execute immediately. See comments above
|
||||||
|
* the cpsid instruction above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable interrupts again because the clock is about to be stopped
|
||||||
|
* and interrupts that execute while the clock is stopped will
|
||||||
|
* increase any slippage between the time maintained by the RTOS and
|
||||||
|
* calendar time. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable the SysTick clock without reading the
|
||||||
|
* portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||||
|
* portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set.
|
||||||
|
* Again, the time the SysTick is stopped for is accounted for as
|
||||||
|
* best it can be, but using the tickless mode will inevitably
|
||||||
|
* result in some tiny drift of the time maintained by the kernel
|
||||||
|
* with respect to calendar time*/
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
|
||||||
|
|
||||||
|
/* Determine if the SysTick clock has already counted to zero and
|
||||||
|
* been set back to the current reload value (the reload back being
|
||||||
|
* correct for the entire expected idle time) or if the SysTick is
|
||||||
|
* yet to count to zero (in which case an interrupt other than the
|
||||||
|
* SysTick must have brought the system out of sleep mode). */
|
||||||
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt is already pending, and the SysTick count
|
||||||
|
* reloaded with ulReloadValue. Reset the
|
||||||
|
* portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
|
* period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
* underflowed because the post sleep hook did something
|
||||||
|
* that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* As the pending tick will be processed as soon as this
|
||||||
|
* function exits, the tick value maintained by the tick is
|
||||||
|
* stepped forward by one less than the time spent waiting. */
|
||||||
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep.
|
||||||
|
* Work out how long the sleep lasted rounded to complete tick
|
||||||
|
* periods (not the ulReload value which accounted for part
|
||||||
|
* ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* How many complete tick periods passed while the processor
|
||||||
|
* was waiting? */
|
||||||
|
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||||
|
|
||||||
|
/* The reload value is set to whatever fraction of a single tick
|
||||||
|
* period remains. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||||
|
* again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||||
|
* value. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Exit with interrupts enabled. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
/* Stop and reset the SysTick. */
|
/* Stop and reset the SysTick. */
|
||||||
*( portNVIC_SYSTICK_CTRL ) = 0UL;
|
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||||
*( portNVIC_SYSTICK_CURRENT_VALUE ) = 0UL;
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
/* Configure SysTick to interrupt at the requested rate. */
|
/* Configure SysTick to interrupt at the requested rate. */
|
||||||
*( portNVIC_SYSTICK_LOAD ) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||||
*( portNVIC_SYSTICK_CTRL ) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -446,11 +662,11 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
( portMPU_RLAR_REGION_ENABLE );
|
( portMPU_RLAR_REGION_ENABLE );
|
||||||
|
|
||||||
/* Enable mem fault. */
|
/* Enable mem fault. */
|
||||||
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE;
|
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
|
||||||
|
|
||||||
/* Enable MPU with privileged background access i.e. unmapped
|
/* Enable MPU with privileged background access i.e. unmapped
|
||||||
* regions have privileged access. */
|
* regions have privileged access. */
|
||||||
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE | portMPU_ENABLE );
|
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* configENABLE_MPU */
|
#endif /* configENABLE_MPU */
|
||||||
|
@ -484,7 +700,7 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Set a PendSV to request a context switch. */
|
/* Set a PendSV to request a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
|
||||||
/* Barriers are normally not required but do ensure the code is
|
/* Barriers are normally not required but do ensure the code is
|
||||||
* completely within the specified behaviour for the architecture. */
|
* completely within the specified behaviour for the architecture. */
|
||||||
|
@ -527,7 +743,7 @@ uint32_t ulPreviousMask;
|
||||||
if( xTaskIncrementTick() != pdFALSE )
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
{
|
{
|
||||||
/* Pend a context switch. */
|
/* Pend a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||||
|
@ -772,8 +988,8 @@ uint8_t ucSVCNumber;
|
||||||
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
#if( configENABLE_MPU == 1 )
|
#if( configENABLE_MPU == 1 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -227,6 +227,15 @@ typedef struct MPU_SETTINGS
|
||||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tickless idle/low power functionality.
|
||||||
|
*/
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -73,6 +73,7 @@ typedef unsigned long UBaseType_t;
|
||||||
#define portSTACK_GROWTH ( -1 )
|
#define portSTACK_GROWTH ( -1 )
|
||||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
#define portBYTE_ALIGNMENT 8
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
#define portDONT_DISCARD __attribute__(( used ))
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Scheduler utilities. */
|
/* Scheduler utilities. */
|
||||||
|
|
|
@ -71,25 +71,32 @@
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to manipulate the NVIC.
|
* @brief Constants required to manipulate the NVIC.
|
||||||
*/
|
*/
|
||||||
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
|
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||||
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 )
|
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||||
#define portNVIC_SYSTICK_CURRENT_VALUE ( ( volatile uint32_t * ) 0xe000e018 )
|
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||||
#define portNVIC_INT_CTRL ( ( volatile uint32_t * ) 0xe000ed04 )
|
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
#define portNVIC_SYSPRI2 ( ( volatile uint32_t * ) 0xe000ed20 )
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
#define portNVIC_SYSTICK_CLK ( 0x00000004 )
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
#define portNVIC_SYSTICK_INT ( 0x00000002 )
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001 )
|
|
||||||
#define portNVIC_PENDSVSET ( 0x10000000 )
|
|
||||||
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||||
#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 )
|
||||||
|
#ifndef configSYSTICK_CLOCK_HZ
|
||||||
|
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||||
|
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
|
#else
|
||||||
|
/* The way the SysTick is clocked is not modified in case it is not the
|
||||||
|
* same a the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||||
|
#endif
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 )
|
||||||
#define portSCB_MEM_FAULT_ENABLE ( 1UL << 16UL )
|
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -169,15 +176,30 @@
|
||||||
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
||||||
|
|
||||||
/* Enable privileged access to unmapped region. */
|
/* Enable privileged access to unmapped region. */
|
||||||
#define portMPU_PRIV_BACKGROUND_ENABLE ( 1UL << 2UL )
|
#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL )
|
||||||
|
|
||||||
/* Enable MPU. */
|
/* Enable MPU. */
|
||||||
#define portMPU_ENABLE ( 1UL << 0UL )
|
#define portMPU_ENABLE_BIT ( 1UL << 0UL )
|
||||||
|
|
||||||
/* Expected value of the portMPU_TYPE register. */
|
/* Expected value of the portMPU_TYPE register. */
|
||||||
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum 24-bit number.
|
||||||
|
*
|
||||||
|
* It is needed because the systick is a 24-bit counter.
|
||||||
|
*/
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A fiddle factor to estimate the number of SysTick counts that would
|
||||||
|
* have occurred while the SysTick counter is stopped during tickless idle
|
||||||
|
* calculations.
|
||||||
|
*/
|
||||||
|
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to set up the initial stack.
|
* @brief Constants required to set up the initial stack.
|
||||||
*/
|
*/
|
||||||
|
@ -332,17 +354,211 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
|
||||||
*/
|
*/
|
||||||
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
||||||
#endif /* configENABLE_TRUSTZONE */
|
#endif /* configENABLE_TRUSTZONE */
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
/**
|
||||||
|
* @brief The number of SysTick increments that make up one tick period.
|
||||||
|
*/
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum number of tick periods that can be suppressed is
|
||||||
|
* limited by the 24 bit resolution of the SysTick timer.
|
||||||
|
*/
|
||||||
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compensate for the CPU cycles that pass while the SysTick is
|
||||||
|
* stopped (low power functionality only).
|
||||||
|
*/
|
||||||
|
static uint32_t ulStoppedTimerCompensation = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
__attribute__(( weak )) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||||
|
{
|
||||||
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
|
||||||
|
TickType_t xModifiableIdleTime;
|
||||||
|
|
||||||
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||||
|
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||||
|
{
|
||||||
|
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the SysTick momentarily. The time the SysTick is stopped for is
|
||||||
|
* accounted for as best it can be, but using the tickless mode will
|
||||||
|
* inevitably result in some tiny drift of the time maintained by the
|
||||||
|
* kernel with respect to calendar time. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||||
|
* tick periods. -1 is used because this code will execute part way
|
||||||
|
* through one of the tick periods. */
|
||||||
|
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||||
|
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||||
|
{
|
||||||
|
ulReloadValue -= ulStoppedTimerCompensation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||||
|
* method as that will mask interrupts that should exit sleep mode. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* If a context switch is pending or a task is waiting for the scheduler
|
||||||
|
* to be un-suspended then abandon the low power entry. */
|
||||||
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
* this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
* periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||||
|
* above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the new reload value. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||||
|
|
||||||
|
/* Clear the SysTick count flag and set the count value back to
|
||||||
|
* zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||||
|
* set its parameter to 0 to indicate that its implementation
|
||||||
|
* contains its own wait for interrupt or wait for event
|
||||||
|
* instruction, and so wfi should not be executed again. However,
|
||||||
|
* the original expected idle time variable must remain unmodified,
|
||||||
|
* so a copy is taken. */
|
||||||
|
xModifiableIdleTime = xExpectedIdleTime;
|
||||||
|
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||||
|
if( xModifiableIdleTime > 0 )
|
||||||
|
{
|
||||||
|
__asm volatile( "dsb" ::: "memory" );
|
||||||
|
__asm volatile( "wfi" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
}
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||||
|
* out of sleep mode to execute immediately. See comments above
|
||||||
|
* the cpsid instruction above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable interrupts again because the clock is about to be stopped
|
||||||
|
* and interrupts that execute while the clock is stopped will
|
||||||
|
* increase any slippage between the time maintained by the RTOS and
|
||||||
|
* calendar time. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable the SysTick clock without reading the
|
||||||
|
* portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||||
|
* portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set.
|
||||||
|
* Again, the time the SysTick is stopped for is accounted for as
|
||||||
|
* best it can be, but using the tickless mode will inevitably
|
||||||
|
* result in some tiny drift of the time maintained by the kernel
|
||||||
|
* with respect to calendar time*/
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
|
||||||
|
|
||||||
|
/* Determine if the SysTick clock has already counted to zero and
|
||||||
|
* been set back to the current reload value (the reload back being
|
||||||
|
* correct for the entire expected idle time) or if the SysTick is
|
||||||
|
* yet to count to zero (in which case an interrupt other than the
|
||||||
|
* SysTick must have brought the system out of sleep mode). */
|
||||||
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt is already pending, and the SysTick count
|
||||||
|
* reloaded with ulReloadValue. Reset the
|
||||||
|
* portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
|
* period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
* underflowed because the post sleep hook did something
|
||||||
|
* that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* As the pending tick will be processed as soon as this
|
||||||
|
* function exits, the tick value maintained by the tick is
|
||||||
|
* stepped forward by one less than the time spent waiting. */
|
||||||
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep.
|
||||||
|
* Work out how long the sleep lasted rounded to complete tick
|
||||||
|
* periods (not the ulReload value which accounted for part
|
||||||
|
* ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* How many complete tick periods passed while the processor
|
||||||
|
* was waiting? */
|
||||||
|
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||||
|
|
||||||
|
/* The reload value is set to whatever fraction of a single tick
|
||||||
|
* period remains. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||||
|
* again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||||
|
* value. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Exit with interrupts enabled. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
/* Stop and reset the SysTick. */
|
/* Stop and reset the SysTick. */
|
||||||
*( portNVIC_SYSTICK_CTRL ) = 0UL;
|
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||||
*( portNVIC_SYSTICK_CURRENT_VALUE ) = 0UL;
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
/* Configure SysTick to interrupt at the requested rate. */
|
/* Configure SysTick to interrupt at the requested rate. */
|
||||||
*( portNVIC_SYSTICK_LOAD ) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||||
*( portNVIC_SYSTICK_CTRL ) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -446,11 +662,11 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
( portMPU_RLAR_REGION_ENABLE );
|
( portMPU_RLAR_REGION_ENABLE );
|
||||||
|
|
||||||
/* Enable mem fault. */
|
/* Enable mem fault. */
|
||||||
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE;
|
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
|
||||||
|
|
||||||
/* Enable MPU with privileged background access i.e. unmapped
|
/* Enable MPU with privileged background access i.e. unmapped
|
||||||
* regions have privileged access. */
|
* regions have privileged access. */
|
||||||
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE | portMPU_ENABLE );
|
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* configENABLE_MPU */
|
#endif /* configENABLE_MPU */
|
||||||
|
@ -484,7 +700,7 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Set a PendSV to request a context switch. */
|
/* Set a PendSV to request a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
|
||||||
/* Barriers are normally not required but do ensure the code is
|
/* Barriers are normally not required but do ensure the code is
|
||||||
* completely within the specified behaviour for the architecture. */
|
* completely within the specified behaviour for the architecture. */
|
||||||
|
@ -527,7 +743,7 @@ uint32_t ulPreviousMask;
|
||||||
if( xTaskIncrementTick() != pdFALSE )
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
{
|
{
|
||||||
/* Pend a context switch. */
|
/* Pend a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||||
|
@ -772,8 +988,8 @@ uint8_t ucSVCNumber;
|
||||||
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
#if( configENABLE_MPU == 1 )
|
#if( configENABLE_MPU == 1 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -227,6 +227,15 @@ typedef struct MPU_SETTINGS
|
||||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tickless idle/low power functionality.
|
||||||
|
*/
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -71,25 +71,32 @@
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to manipulate the NVIC.
|
* @brief Constants required to manipulate the NVIC.
|
||||||
*/
|
*/
|
||||||
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
|
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||||
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 )
|
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||||
#define portNVIC_SYSTICK_CURRENT_VALUE ( ( volatile uint32_t * ) 0xe000e018 )
|
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||||
#define portNVIC_INT_CTRL ( ( volatile uint32_t * ) 0xe000ed04 )
|
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
#define portNVIC_SYSPRI2 ( ( volatile uint32_t * ) 0xe000ed20 )
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
#define portNVIC_SYSTICK_CLK ( 0x00000004 )
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
#define portNVIC_SYSTICK_INT ( 0x00000002 )
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001 )
|
|
||||||
#define portNVIC_PENDSVSET ( 0x10000000 )
|
|
||||||
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||||
#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 )
|
||||||
|
#ifndef configSYSTICK_CLOCK_HZ
|
||||||
|
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||||
|
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
|
#else
|
||||||
|
/* The way the SysTick is clocked is not modified in case it is not the
|
||||||
|
* same a the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||||
|
#endif
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 )
|
||||||
#define portSCB_MEM_FAULT_ENABLE ( 1UL << 16UL )
|
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -169,15 +176,30 @@
|
||||||
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
||||||
|
|
||||||
/* Enable privileged access to unmapped region. */
|
/* Enable privileged access to unmapped region. */
|
||||||
#define portMPU_PRIV_BACKGROUND_ENABLE ( 1UL << 2UL )
|
#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL )
|
||||||
|
|
||||||
/* Enable MPU. */
|
/* Enable MPU. */
|
||||||
#define portMPU_ENABLE ( 1UL << 0UL )
|
#define portMPU_ENABLE_BIT ( 1UL << 0UL )
|
||||||
|
|
||||||
/* Expected value of the portMPU_TYPE register. */
|
/* Expected value of the portMPU_TYPE register. */
|
||||||
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum 24-bit number.
|
||||||
|
*
|
||||||
|
* It is needed because the systick is a 24-bit counter.
|
||||||
|
*/
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A fiddle factor to estimate the number of SysTick counts that would
|
||||||
|
* have occurred while the SysTick counter is stopped during tickless idle
|
||||||
|
* calculations.
|
||||||
|
*/
|
||||||
|
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to set up the initial stack.
|
* @brief Constants required to set up the initial stack.
|
||||||
*/
|
*/
|
||||||
|
@ -332,17 +354,211 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
|
||||||
*/
|
*/
|
||||||
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
||||||
#endif /* configENABLE_TRUSTZONE */
|
#endif /* configENABLE_TRUSTZONE */
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
/**
|
||||||
|
* @brief The number of SysTick increments that make up one tick period.
|
||||||
|
*/
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum number of tick periods that can be suppressed is
|
||||||
|
* limited by the 24 bit resolution of the SysTick timer.
|
||||||
|
*/
|
||||||
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compensate for the CPU cycles that pass while the SysTick is
|
||||||
|
* stopped (low power functionality only).
|
||||||
|
*/
|
||||||
|
static uint32_t ulStoppedTimerCompensation = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
__attribute__(( weak )) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||||
|
{
|
||||||
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
|
||||||
|
TickType_t xModifiableIdleTime;
|
||||||
|
|
||||||
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||||
|
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||||
|
{
|
||||||
|
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the SysTick momentarily. The time the SysTick is stopped for is
|
||||||
|
* accounted for as best it can be, but using the tickless mode will
|
||||||
|
* inevitably result in some tiny drift of the time maintained by the
|
||||||
|
* kernel with respect to calendar time. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||||
|
* tick periods. -1 is used because this code will execute part way
|
||||||
|
* through one of the tick periods. */
|
||||||
|
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||||
|
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||||
|
{
|
||||||
|
ulReloadValue -= ulStoppedTimerCompensation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||||
|
* method as that will mask interrupts that should exit sleep mode. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* If a context switch is pending or a task is waiting for the scheduler
|
||||||
|
* to be un-suspended then abandon the low power entry. */
|
||||||
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
* this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
* periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||||
|
* above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the new reload value. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||||
|
|
||||||
|
/* Clear the SysTick count flag and set the count value back to
|
||||||
|
* zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||||
|
* set its parameter to 0 to indicate that its implementation
|
||||||
|
* contains its own wait for interrupt or wait for event
|
||||||
|
* instruction, and so wfi should not be executed again. However,
|
||||||
|
* the original expected idle time variable must remain unmodified,
|
||||||
|
* so a copy is taken. */
|
||||||
|
xModifiableIdleTime = xExpectedIdleTime;
|
||||||
|
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||||
|
if( xModifiableIdleTime > 0 )
|
||||||
|
{
|
||||||
|
__asm volatile( "dsb" ::: "memory" );
|
||||||
|
__asm volatile( "wfi" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
}
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||||
|
* out of sleep mode to execute immediately. See comments above
|
||||||
|
* the cpsid instruction above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable interrupts again because the clock is about to be stopped
|
||||||
|
* and interrupts that execute while the clock is stopped will
|
||||||
|
* increase any slippage between the time maintained by the RTOS and
|
||||||
|
* calendar time. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable the SysTick clock without reading the
|
||||||
|
* portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||||
|
* portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set.
|
||||||
|
* Again, the time the SysTick is stopped for is accounted for as
|
||||||
|
* best it can be, but using the tickless mode will inevitably
|
||||||
|
* result in some tiny drift of the time maintained by the kernel
|
||||||
|
* with respect to calendar time*/
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
|
||||||
|
|
||||||
|
/* Determine if the SysTick clock has already counted to zero and
|
||||||
|
* been set back to the current reload value (the reload back being
|
||||||
|
* correct for the entire expected idle time) or if the SysTick is
|
||||||
|
* yet to count to zero (in which case an interrupt other than the
|
||||||
|
* SysTick must have brought the system out of sleep mode). */
|
||||||
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt is already pending, and the SysTick count
|
||||||
|
* reloaded with ulReloadValue. Reset the
|
||||||
|
* portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
|
* period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
* underflowed because the post sleep hook did something
|
||||||
|
* that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* As the pending tick will be processed as soon as this
|
||||||
|
* function exits, the tick value maintained by the tick is
|
||||||
|
* stepped forward by one less than the time spent waiting. */
|
||||||
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep.
|
||||||
|
* Work out how long the sleep lasted rounded to complete tick
|
||||||
|
* periods (not the ulReload value which accounted for part
|
||||||
|
* ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* How many complete tick periods passed while the processor
|
||||||
|
* was waiting? */
|
||||||
|
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||||
|
|
||||||
|
/* The reload value is set to whatever fraction of a single tick
|
||||||
|
* period remains. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||||
|
* again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||||
|
* value. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Exit with interrupts enabled. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
/* Stop and reset the SysTick. */
|
/* Stop and reset the SysTick. */
|
||||||
*( portNVIC_SYSTICK_CTRL ) = 0UL;
|
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||||
*( portNVIC_SYSTICK_CURRENT_VALUE ) = 0UL;
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
/* Configure SysTick to interrupt at the requested rate. */
|
/* Configure SysTick to interrupt at the requested rate. */
|
||||||
*( portNVIC_SYSTICK_LOAD ) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||||
*( portNVIC_SYSTICK_CTRL ) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -446,11 +662,11 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
( portMPU_RLAR_REGION_ENABLE );
|
( portMPU_RLAR_REGION_ENABLE );
|
||||||
|
|
||||||
/* Enable mem fault. */
|
/* Enable mem fault. */
|
||||||
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE;
|
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
|
||||||
|
|
||||||
/* Enable MPU with privileged background access i.e. unmapped
|
/* Enable MPU with privileged background access i.e. unmapped
|
||||||
* regions have privileged access. */
|
* regions have privileged access. */
|
||||||
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE | portMPU_ENABLE );
|
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* configENABLE_MPU */
|
#endif /* configENABLE_MPU */
|
||||||
|
@ -484,7 +700,7 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Set a PendSV to request a context switch. */
|
/* Set a PendSV to request a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
|
||||||
/* Barriers are normally not required but do ensure the code is
|
/* Barriers are normally not required but do ensure the code is
|
||||||
* completely within the specified behaviour for the architecture. */
|
* completely within the specified behaviour for the architecture. */
|
||||||
|
@ -527,7 +743,7 @@ uint32_t ulPreviousMask;
|
||||||
if( xTaskIncrementTick() != pdFALSE )
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
{
|
{
|
||||||
/* Pend a context switch. */
|
/* Pend a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||||
|
@ -772,8 +988,8 @@ uint8_t ucSVCNumber;
|
||||||
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
#if( configENABLE_MPU == 1 )
|
#if( configENABLE_MPU == 1 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -227,6 +227,15 @@ typedef struct MPU_SETTINGS
|
||||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tickless idle/low power functionality.
|
||||||
|
*/
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -584,6 +584,7 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
|
||||||
|
|
||||||
static void prvSetupMPU( void )
|
static void prvSetupMPU( void )
|
||||||
{
|
{
|
||||||
|
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__[];
|
||||||
|
@ -593,7 +594,7 @@ extern uint32_t __privileged_data_end__[];
|
||||||
/* 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 )
|
||||||
{
|
{
|
||||||
/* First setup the entire flash for unprivileged read only access. */
|
/* First setup the unprivileged flash for unprivileged read only access. */
|
||||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
( portUNPRIVILEGED_FLASH_REGION );
|
( portUNPRIVILEGED_FLASH_REGION );
|
||||||
|
@ -603,16 +604,15 @@ extern uint32_t __privileged_data_end__[];
|
||||||
( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
||||||
( portMPU_REGION_ENABLE );
|
( portMPU_REGION_ENABLE );
|
||||||
|
|
||||||
/* Setup the first 16K for privileged only access (even though less
|
/* Setup the privileged flash for privileged only access. This is where
|
||||||
* than 10K is actually being used). This is where the kernel code is
|
* the kernel code is * placed. */
|
||||||
* placed. */
|
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_functions_start__ ) | /* Base address. */
|
||||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
( portPRIVILEGED_FLASH_REGION );
|
( portPRIVILEGED_FLASH_REGION );
|
||||||
|
|
||||||
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) |
|
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) |
|
||||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||||
( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__ ) ) |
|
||||||
( portMPU_REGION_ENABLE );
|
( portMPU_REGION_ENABLE );
|
||||||
|
|
||||||
/* Setup the privileged data RAM region. This is where the kernel data
|
/* Setup the privileged data RAM region. This is where the kernel data
|
||||||
|
|
|
@ -109,6 +109,7 @@ typedef struct MPU_SETTINGS
|
||||||
#define portSTACK_GROWTH ( -1 )
|
#define portSTACK_GROWTH ( -1 )
|
||||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
#define portBYTE_ALIGNMENT 8
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
#define portDONT_DISCARD __attribute__(( used ))
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* SVC numbers for various services. */
|
/* SVC numbers for various services. */
|
||||||
|
|
|
@ -73,6 +73,7 @@ typedef unsigned long UBaseType_t;
|
||||||
#define portSTACK_GROWTH ( -1 )
|
#define portSTACK_GROWTH ( -1 )
|
||||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
#define portBYTE_ALIGNMENT 8
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
#define portDONT_DISCARD __attribute__(( used ))
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Scheduler utilities. */
|
/* Scheduler utilities. */
|
||||||
|
|
|
@ -640,6 +640,7 @@ static void prvSetupMPU( void )
|
||||||
#if defined( __ARMCC_VERSION )
|
#if defined( __ARMCC_VERSION )
|
||||||
/* Declaration when these variable are defined in code instead of being
|
/* Declaration when these variable are defined in code instead of being
|
||||||
* exported from linker scripts. */
|
* exported from linker scripts. */
|
||||||
|
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__;
|
||||||
|
@ -647,6 +648,7 @@ static void prvSetupMPU( void )
|
||||||
extern uint32_t * __privileged_data_end__;
|
extern uint32_t * __privileged_data_end__;
|
||||||
#else
|
#else
|
||||||
/* Declaration when these variable are exported from linker scripts. */
|
/* Declaration when these variable are exported from linker scripts. */
|
||||||
|
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__[];
|
||||||
|
@ -656,7 +658,7 @@ static void prvSetupMPU( void )
|
||||||
/* 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 )
|
||||||
{
|
{
|
||||||
/* First setup the entire flash for unprivileged read only access. */
|
/* First setup the unprivileged flash for unprivileged read only access. */
|
||||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
( portUNPRIVILEGED_FLASH_REGION );
|
( portUNPRIVILEGED_FLASH_REGION );
|
||||||
|
@ -666,16 +668,15 @@ static void prvSetupMPU( void )
|
||||||
( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
||||||
( portMPU_REGION_ENABLE );
|
( portMPU_REGION_ENABLE );
|
||||||
|
|
||||||
/* Setup the first nK for privileged only access (even though less
|
/* Setup the privileged flash for privileged only access. This is where
|
||||||
than 10K is actually being used). This is where the kernel code is
|
the kernel code is placed. */
|
||||||
placed. */
|
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_functions_start__ ) | /* Base address. */
|
||||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
( portPRIVILEGED_FLASH_REGION );
|
( portPRIVILEGED_FLASH_REGION );
|
||||||
|
|
||||||
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) |
|
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) |
|
||||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||||
( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__ ) ) |
|
||||||
( portMPU_REGION_ENABLE );
|
( portMPU_REGION_ENABLE );
|
||||||
|
|
||||||
/* Setup the privileged data RAM region. This is where the kernel data
|
/* Setup the privileged data RAM region. This is where the kernel data
|
||||||
|
|
|
@ -109,6 +109,7 @@ typedef struct MPU_SETTINGS
|
||||||
#define portSTACK_GROWTH ( -1 )
|
#define portSTACK_GROWTH ( -1 )
|
||||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
#define portBYTE_ALIGNMENT 8
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
#define portDONT_DISCARD __attribute__(( used ))
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* SVC numbers for various services. */
|
/* SVC numbers for various services. */
|
||||||
|
|
|
@ -73,6 +73,7 @@ typedef unsigned long UBaseType_t;
|
||||||
#define portSTACK_GROWTH ( -1 )
|
#define portSTACK_GROWTH ( -1 )
|
||||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
#define portBYTE_ALIGNMENT 8
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
#define portDONT_DISCARD __attribute__(( used ))
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Scheduler utilities. */
|
/* Scheduler utilities. */
|
||||||
|
|
|
@ -71,25 +71,32 @@
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to manipulate the NVIC.
|
* @brief Constants required to manipulate the NVIC.
|
||||||
*/
|
*/
|
||||||
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
|
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||||
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 )
|
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||||
#define portNVIC_SYSTICK_CURRENT_VALUE ( ( volatile uint32_t * ) 0xe000e018 )
|
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||||
#define portNVIC_INT_CTRL ( ( volatile uint32_t * ) 0xe000ed04 )
|
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
#define portNVIC_SYSPRI2 ( ( volatile uint32_t * ) 0xe000ed20 )
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
#define portNVIC_SYSTICK_CLK ( 0x00000004 )
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
#define portNVIC_SYSTICK_INT ( 0x00000002 )
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001 )
|
|
||||||
#define portNVIC_PENDSVSET ( 0x10000000 )
|
|
||||||
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||||
#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 )
|
||||||
|
#ifndef configSYSTICK_CLOCK_HZ
|
||||||
|
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||||
|
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
|
#else
|
||||||
|
/* The way the SysTick is clocked is not modified in case it is not the
|
||||||
|
* same a the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||||
|
#endif
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 )
|
||||||
#define portSCB_MEM_FAULT_ENABLE ( 1UL << 16UL )
|
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -169,15 +176,30 @@
|
||||||
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
||||||
|
|
||||||
/* Enable privileged access to unmapped region. */
|
/* Enable privileged access to unmapped region. */
|
||||||
#define portMPU_PRIV_BACKGROUND_ENABLE ( 1UL << 2UL )
|
#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL )
|
||||||
|
|
||||||
/* Enable MPU. */
|
/* Enable MPU. */
|
||||||
#define portMPU_ENABLE ( 1UL << 0UL )
|
#define portMPU_ENABLE_BIT ( 1UL << 0UL )
|
||||||
|
|
||||||
/* Expected value of the portMPU_TYPE register. */
|
/* Expected value of the portMPU_TYPE register. */
|
||||||
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum 24-bit number.
|
||||||
|
*
|
||||||
|
* It is needed because the systick is a 24-bit counter.
|
||||||
|
*/
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A fiddle factor to estimate the number of SysTick counts that would
|
||||||
|
* have occurred while the SysTick counter is stopped during tickless idle
|
||||||
|
* calculations.
|
||||||
|
*/
|
||||||
|
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to set up the initial stack.
|
* @brief Constants required to set up the initial stack.
|
||||||
*/
|
*/
|
||||||
|
@ -332,17 +354,211 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
|
||||||
*/
|
*/
|
||||||
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
||||||
#endif /* configENABLE_TRUSTZONE */
|
#endif /* configENABLE_TRUSTZONE */
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
/**
|
||||||
|
* @brief The number of SysTick increments that make up one tick period.
|
||||||
|
*/
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum number of tick periods that can be suppressed is
|
||||||
|
* limited by the 24 bit resolution of the SysTick timer.
|
||||||
|
*/
|
||||||
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compensate for the CPU cycles that pass while the SysTick is
|
||||||
|
* stopped (low power functionality only).
|
||||||
|
*/
|
||||||
|
static uint32_t ulStoppedTimerCompensation = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
__attribute__(( weak )) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||||
|
{
|
||||||
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
|
||||||
|
TickType_t xModifiableIdleTime;
|
||||||
|
|
||||||
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||||
|
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||||
|
{
|
||||||
|
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the SysTick momentarily. The time the SysTick is stopped for is
|
||||||
|
* accounted for as best it can be, but using the tickless mode will
|
||||||
|
* inevitably result in some tiny drift of the time maintained by the
|
||||||
|
* kernel with respect to calendar time. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||||
|
* tick periods. -1 is used because this code will execute part way
|
||||||
|
* through one of the tick periods. */
|
||||||
|
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||||
|
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||||
|
{
|
||||||
|
ulReloadValue -= ulStoppedTimerCompensation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||||
|
* method as that will mask interrupts that should exit sleep mode. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* If a context switch is pending or a task is waiting for the scheduler
|
||||||
|
* to be un-suspended then abandon the low power entry. */
|
||||||
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
* this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
* periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||||
|
* above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the new reload value. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||||
|
|
||||||
|
/* Clear the SysTick count flag and set the count value back to
|
||||||
|
* zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||||
|
* set its parameter to 0 to indicate that its implementation
|
||||||
|
* contains its own wait for interrupt or wait for event
|
||||||
|
* instruction, and so wfi should not be executed again. However,
|
||||||
|
* the original expected idle time variable must remain unmodified,
|
||||||
|
* so a copy is taken. */
|
||||||
|
xModifiableIdleTime = xExpectedIdleTime;
|
||||||
|
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||||
|
if( xModifiableIdleTime > 0 )
|
||||||
|
{
|
||||||
|
__asm volatile( "dsb" ::: "memory" );
|
||||||
|
__asm volatile( "wfi" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
}
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||||
|
* out of sleep mode to execute immediately. See comments above
|
||||||
|
* the cpsid instruction above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable interrupts again because the clock is about to be stopped
|
||||||
|
* and interrupts that execute while the clock is stopped will
|
||||||
|
* increase any slippage between the time maintained by the RTOS and
|
||||||
|
* calendar time. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable the SysTick clock without reading the
|
||||||
|
* portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||||
|
* portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set.
|
||||||
|
* Again, the time the SysTick is stopped for is accounted for as
|
||||||
|
* best it can be, but using the tickless mode will inevitably
|
||||||
|
* result in some tiny drift of the time maintained by the kernel
|
||||||
|
* with respect to calendar time*/
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
|
||||||
|
|
||||||
|
/* Determine if the SysTick clock has already counted to zero and
|
||||||
|
* been set back to the current reload value (the reload back being
|
||||||
|
* correct for the entire expected idle time) or if the SysTick is
|
||||||
|
* yet to count to zero (in which case an interrupt other than the
|
||||||
|
* SysTick must have brought the system out of sleep mode). */
|
||||||
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt is already pending, and the SysTick count
|
||||||
|
* reloaded with ulReloadValue. Reset the
|
||||||
|
* portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
|
* period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
* underflowed because the post sleep hook did something
|
||||||
|
* that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* As the pending tick will be processed as soon as this
|
||||||
|
* function exits, the tick value maintained by the tick is
|
||||||
|
* stepped forward by one less than the time spent waiting. */
|
||||||
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep.
|
||||||
|
* Work out how long the sleep lasted rounded to complete tick
|
||||||
|
* periods (not the ulReload value which accounted for part
|
||||||
|
* ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* How many complete tick periods passed while the processor
|
||||||
|
* was waiting? */
|
||||||
|
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||||
|
|
||||||
|
/* The reload value is set to whatever fraction of a single tick
|
||||||
|
* period remains. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||||
|
* again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||||
|
* value. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Exit with interrupts enabled. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
/* Stop and reset the SysTick. */
|
/* Stop and reset the SysTick. */
|
||||||
*( portNVIC_SYSTICK_CTRL ) = 0UL;
|
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||||
*( portNVIC_SYSTICK_CURRENT_VALUE ) = 0UL;
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
/* Configure SysTick to interrupt at the requested rate. */
|
/* Configure SysTick to interrupt at the requested rate. */
|
||||||
*( portNVIC_SYSTICK_LOAD ) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||||
*( portNVIC_SYSTICK_CTRL ) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -446,11 +662,11 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
( portMPU_RLAR_REGION_ENABLE );
|
( portMPU_RLAR_REGION_ENABLE );
|
||||||
|
|
||||||
/* Enable mem fault. */
|
/* Enable mem fault. */
|
||||||
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE;
|
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
|
||||||
|
|
||||||
/* Enable MPU with privileged background access i.e. unmapped
|
/* Enable MPU with privileged background access i.e. unmapped
|
||||||
* regions have privileged access. */
|
* regions have privileged access. */
|
||||||
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE | portMPU_ENABLE );
|
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* configENABLE_MPU */
|
#endif /* configENABLE_MPU */
|
||||||
|
@ -484,7 +700,7 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Set a PendSV to request a context switch. */
|
/* Set a PendSV to request a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
|
||||||
/* Barriers are normally not required but do ensure the code is
|
/* Barriers are normally not required but do ensure the code is
|
||||||
* completely within the specified behaviour for the architecture. */
|
* completely within the specified behaviour for the architecture. */
|
||||||
|
@ -527,7 +743,7 @@ uint32_t ulPreviousMask;
|
||||||
if( xTaskIncrementTick() != pdFALSE )
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
{
|
{
|
||||||
/* Pend a context switch. */
|
/* Pend a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||||
|
@ -772,8 +988,8 @@ uint8_t ucSVCNumber;
|
||||||
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
#if( configENABLE_MPU == 1 )
|
#if( configENABLE_MPU == 1 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -216,6 +216,15 @@ typedef struct MPU_SETTINGS
|
||||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tickless idle/low power functionality.
|
||||||
|
*/
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Critical section management.
|
* @brief Critical section management.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -71,25 +71,32 @@
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to manipulate the NVIC.
|
* @brief Constants required to manipulate the NVIC.
|
||||||
*/
|
*/
|
||||||
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
|
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||||
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 )
|
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||||
#define portNVIC_SYSTICK_CURRENT_VALUE ( ( volatile uint32_t * ) 0xe000e018 )
|
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||||
#define portNVIC_INT_CTRL ( ( volatile uint32_t * ) 0xe000ed04 )
|
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
#define portNVIC_SYSPRI2 ( ( volatile uint32_t * ) 0xe000ed20 )
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
#define portNVIC_SYSTICK_CLK ( 0x00000004 )
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
#define portNVIC_SYSTICK_INT ( 0x00000002 )
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001 )
|
|
||||||
#define portNVIC_PENDSVSET ( 0x10000000 )
|
|
||||||
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||||
#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 )
|
||||||
|
#ifndef configSYSTICK_CLOCK_HZ
|
||||||
|
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||||
|
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
|
#else
|
||||||
|
/* The way the SysTick is clocked is not modified in case it is not the
|
||||||
|
* same a the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||||
|
#endif
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 )
|
||||||
#define portSCB_MEM_FAULT_ENABLE ( 1UL << 16UL )
|
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -169,15 +176,30 @@
|
||||||
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
||||||
|
|
||||||
/* Enable privileged access to unmapped region. */
|
/* Enable privileged access to unmapped region. */
|
||||||
#define portMPU_PRIV_BACKGROUND_ENABLE ( 1UL << 2UL )
|
#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL )
|
||||||
|
|
||||||
/* Enable MPU. */
|
/* Enable MPU. */
|
||||||
#define portMPU_ENABLE ( 1UL << 0UL )
|
#define portMPU_ENABLE_BIT ( 1UL << 0UL )
|
||||||
|
|
||||||
/* Expected value of the portMPU_TYPE register. */
|
/* Expected value of the portMPU_TYPE register. */
|
||||||
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum 24-bit number.
|
||||||
|
*
|
||||||
|
* It is needed because the systick is a 24-bit counter.
|
||||||
|
*/
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A fiddle factor to estimate the number of SysTick counts that would
|
||||||
|
* have occurred while the SysTick counter is stopped during tickless idle
|
||||||
|
* calculations.
|
||||||
|
*/
|
||||||
|
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to set up the initial stack.
|
* @brief Constants required to set up the initial stack.
|
||||||
*/
|
*/
|
||||||
|
@ -332,17 +354,211 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
|
||||||
*/
|
*/
|
||||||
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
||||||
#endif /* configENABLE_TRUSTZONE */
|
#endif /* configENABLE_TRUSTZONE */
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
/**
|
||||||
|
* @brief The number of SysTick increments that make up one tick period.
|
||||||
|
*/
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum number of tick periods that can be suppressed is
|
||||||
|
* limited by the 24 bit resolution of the SysTick timer.
|
||||||
|
*/
|
||||||
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compensate for the CPU cycles that pass while the SysTick is
|
||||||
|
* stopped (low power functionality only).
|
||||||
|
*/
|
||||||
|
static uint32_t ulStoppedTimerCompensation = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
__attribute__(( weak )) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||||
|
{
|
||||||
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
|
||||||
|
TickType_t xModifiableIdleTime;
|
||||||
|
|
||||||
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||||
|
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||||
|
{
|
||||||
|
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the SysTick momentarily. The time the SysTick is stopped for is
|
||||||
|
* accounted for as best it can be, but using the tickless mode will
|
||||||
|
* inevitably result in some tiny drift of the time maintained by the
|
||||||
|
* kernel with respect to calendar time. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||||
|
* tick periods. -1 is used because this code will execute part way
|
||||||
|
* through one of the tick periods. */
|
||||||
|
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||||
|
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||||
|
{
|
||||||
|
ulReloadValue -= ulStoppedTimerCompensation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||||
|
* method as that will mask interrupts that should exit sleep mode. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* If a context switch is pending or a task is waiting for the scheduler
|
||||||
|
* to be un-suspended then abandon the low power entry. */
|
||||||
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
* this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
* periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||||
|
* above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the new reload value. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||||
|
|
||||||
|
/* Clear the SysTick count flag and set the count value back to
|
||||||
|
* zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||||
|
* set its parameter to 0 to indicate that its implementation
|
||||||
|
* contains its own wait for interrupt or wait for event
|
||||||
|
* instruction, and so wfi should not be executed again. However,
|
||||||
|
* the original expected idle time variable must remain unmodified,
|
||||||
|
* so a copy is taken. */
|
||||||
|
xModifiableIdleTime = xExpectedIdleTime;
|
||||||
|
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||||
|
if( xModifiableIdleTime > 0 )
|
||||||
|
{
|
||||||
|
__asm volatile( "dsb" ::: "memory" );
|
||||||
|
__asm volatile( "wfi" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
}
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||||
|
* out of sleep mode to execute immediately. See comments above
|
||||||
|
* the cpsid instruction above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable interrupts again because the clock is about to be stopped
|
||||||
|
* and interrupts that execute while the clock is stopped will
|
||||||
|
* increase any slippage between the time maintained by the RTOS and
|
||||||
|
* calendar time. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable the SysTick clock without reading the
|
||||||
|
* portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||||
|
* portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set.
|
||||||
|
* Again, the time the SysTick is stopped for is accounted for as
|
||||||
|
* best it can be, but using the tickless mode will inevitably
|
||||||
|
* result in some tiny drift of the time maintained by the kernel
|
||||||
|
* with respect to calendar time*/
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
|
||||||
|
|
||||||
|
/* Determine if the SysTick clock has already counted to zero and
|
||||||
|
* been set back to the current reload value (the reload back being
|
||||||
|
* correct for the entire expected idle time) or if the SysTick is
|
||||||
|
* yet to count to zero (in which case an interrupt other than the
|
||||||
|
* SysTick must have brought the system out of sleep mode). */
|
||||||
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt is already pending, and the SysTick count
|
||||||
|
* reloaded with ulReloadValue. Reset the
|
||||||
|
* portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
|
* period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
* underflowed because the post sleep hook did something
|
||||||
|
* that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* As the pending tick will be processed as soon as this
|
||||||
|
* function exits, the tick value maintained by the tick is
|
||||||
|
* stepped forward by one less than the time spent waiting. */
|
||||||
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep.
|
||||||
|
* Work out how long the sleep lasted rounded to complete tick
|
||||||
|
* periods (not the ulReload value which accounted for part
|
||||||
|
* ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* How many complete tick periods passed while the processor
|
||||||
|
* was waiting? */
|
||||||
|
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||||
|
|
||||||
|
/* The reload value is set to whatever fraction of a single tick
|
||||||
|
* period remains. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||||
|
* again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||||
|
* value. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Exit with interrupts enabled. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
/* Stop and reset the SysTick. */
|
/* Stop and reset the SysTick. */
|
||||||
*( portNVIC_SYSTICK_CTRL ) = 0UL;
|
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||||
*( portNVIC_SYSTICK_CURRENT_VALUE ) = 0UL;
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
/* Configure SysTick to interrupt at the requested rate. */
|
/* Configure SysTick to interrupt at the requested rate. */
|
||||||
*( portNVIC_SYSTICK_LOAD ) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||||
*( portNVIC_SYSTICK_CTRL ) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -446,11 +662,11 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
( portMPU_RLAR_REGION_ENABLE );
|
( portMPU_RLAR_REGION_ENABLE );
|
||||||
|
|
||||||
/* Enable mem fault. */
|
/* Enable mem fault. */
|
||||||
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE;
|
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
|
||||||
|
|
||||||
/* Enable MPU with privileged background access i.e. unmapped
|
/* Enable MPU with privileged background access i.e. unmapped
|
||||||
* regions have privileged access. */
|
* regions have privileged access. */
|
||||||
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE | portMPU_ENABLE );
|
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* configENABLE_MPU */
|
#endif /* configENABLE_MPU */
|
||||||
|
@ -484,7 +700,7 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Set a PendSV to request a context switch. */
|
/* Set a PendSV to request a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
|
||||||
/* Barriers are normally not required but do ensure the code is
|
/* Barriers are normally not required but do ensure the code is
|
||||||
* completely within the specified behaviour for the architecture. */
|
* completely within the specified behaviour for the architecture. */
|
||||||
|
@ -527,7 +743,7 @@ uint32_t ulPreviousMask;
|
||||||
if( xTaskIncrementTick() != pdFALSE )
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
{
|
{
|
||||||
/* Pend a context switch. */
|
/* Pend a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||||
|
@ -772,8 +988,8 @@ uint8_t ucSVCNumber;
|
||||||
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
#if( configENABLE_MPU == 1 )
|
#if( configENABLE_MPU == 1 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -227,6 +227,15 @@ typedef struct MPU_SETTINGS
|
||||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tickless idle/low power functionality.
|
||||||
|
*/
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -71,25 +71,32 @@
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to manipulate the NVIC.
|
* @brief Constants required to manipulate the NVIC.
|
||||||
*/
|
*/
|
||||||
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
|
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||||
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 )
|
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||||
#define portNVIC_SYSTICK_CURRENT_VALUE ( ( volatile uint32_t * ) 0xe000e018 )
|
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||||
#define portNVIC_INT_CTRL ( ( volatile uint32_t * ) 0xe000ed04 )
|
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
#define portNVIC_SYSPRI2 ( ( volatile uint32_t * ) 0xe000ed20 )
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
#define portNVIC_SYSTICK_CLK ( 0x00000004 )
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
#define portNVIC_SYSTICK_INT ( 0x00000002 )
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001 )
|
|
||||||
#define portNVIC_PENDSVSET ( 0x10000000 )
|
|
||||||
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||||
#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 )
|
||||||
|
#ifndef configSYSTICK_CLOCK_HZ
|
||||||
|
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||||
|
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
|
#else
|
||||||
|
/* The way the SysTick is clocked is not modified in case it is not the
|
||||||
|
* same a the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||||
|
#endif
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 )
|
||||||
#define portSCB_MEM_FAULT_ENABLE ( 1UL << 16UL )
|
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -169,15 +176,30 @@
|
||||||
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
||||||
|
|
||||||
/* Enable privileged access to unmapped region. */
|
/* Enable privileged access to unmapped region. */
|
||||||
#define portMPU_PRIV_BACKGROUND_ENABLE ( 1UL << 2UL )
|
#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL )
|
||||||
|
|
||||||
/* Enable MPU. */
|
/* Enable MPU. */
|
||||||
#define portMPU_ENABLE ( 1UL << 0UL )
|
#define portMPU_ENABLE_BIT ( 1UL << 0UL )
|
||||||
|
|
||||||
/* Expected value of the portMPU_TYPE register. */
|
/* Expected value of the portMPU_TYPE register. */
|
||||||
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum 24-bit number.
|
||||||
|
*
|
||||||
|
* It is needed because the systick is a 24-bit counter.
|
||||||
|
*/
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A fiddle factor to estimate the number of SysTick counts that would
|
||||||
|
* have occurred while the SysTick counter is stopped during tickless idle
|
||||||
|
* calculations.
|
||||||
|
*/
|
||||||
|
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to set up the initial stack.
|
* @brief Constants required to set up the initial stack.
|
||||||
*/
|
*/
|
||||||
|
@ -332,17 +354,211 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
|
||||||
*/
|
*/
|
||||||
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
||||||
#endif /* configENABLE_TRUSTZONE */
|
#endif /* configENABLE_TRUSTZONE */
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
/**
|
||||||
|
* @brief The number of SysTick increments that make up one tick period.
|
||||||
|
*/
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum number of tick periods that can be suppressed is
|
||||||
|
* limited by the 24 bit resolution of the SysTick timer.
|
||||||
|
*/
|
||||||
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compensate for the CPU cycles that pass while the SysTick is
|
||||||
|
* stopped (low power functionality only).
|
||||||
|
*/
|
||||||
|
static uint32_t ulStoppedTimerCompensation = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
__attribute__(( weak )) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||||
|
{
|
||||||
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
|
||||||
|
TickType_t xModifiableIdleTime;
|
||||||
|
|
||||||
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||||
|
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||||
|
{
|
||||||
|
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the SysTick momentarily. The time the SysTick is stopped for is
|
||||||
|
* accounted for as best it can be, but using the tickless mode will
|
||||||
|
* inevitably result in some tiny drift of the time maintained by the
|
||||||
|
* kernel with respect to calendar time. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||||
|
* tick periods. -1 is used because this code will execute part way
|
||||||
|
* through one of the tick periods. */
|
||||||
|
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||||
|
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||||
|
{
|
||||||
|
ulReloadValue -= ulStoppedTimerCompensation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||||
|
* method as that will mask interrupts that should exit sleep mode. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* If a context switch is pending or a task is waiting for the scheduler
|
||||||
|
* to be un-suspended then abandon the low power entry. */
|
||||||
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
* this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
* periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||||
|
* above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the new reload value. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||||
|
|
||||||
|
/* Clear the SysTick count flag and set the count value back to
|
||||||
|
* zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||||
|
* set its parameter to 0 to indicate that its implementation
|
||||||
|
* contains its own wait for interrupt or wait for event
|
||||||
|
* instruction, and so wfi should not be executed again. However,
|
||||||
|
* the original expected idle time variable must remain unmodified,
|
||||||
|
* so a copy is taken. */
|
||||||
|
xModifiableIdleTime = xExpectedIdleTime;
|
||||||
|
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||||
|
if( xModifiableIdleTime > 0 )
|
||||||
|
{
|
||||||
|
__asm volatile( "dsb" ::: "memory" );
|
||||||
|
__asm volatile( "wfi" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
}
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||||
|
* out of sleep mode to execute immediately. See comments above
|
||||||
|
* the cpsid instruction above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable interrupts again because the clock is about to be stopped
|
||||||
|
* and interrupts that execute while the clock is stopped will
|
||||||
|
* increase any slippage between the time maintained by the RTOS and
|
||||||
|
* calendar time. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable the SysTick clock without reading the
|
||||||
|
* portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||||
|
* portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set.
|
||||||
|
* Again, the time the SysTick is stopped for is accounted for as
|
||||||
|
* best it can be, but using the tickless mode will inevitably
|
||||||
|
* result in some tiny drift of the time maintained by the kernel
|
||||||
|
* with respect to calendar time*/
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
|
||||||
|
|
||||||
|
/* Determine if the SysTick clock has already counted to zero and
|
||||||
|
* been set back to the current reload value (the reload back being
|
||||||
|
* correct for the entire expected idle time) or if the SysTick is
|
||||||
|
* yet to count to zero (in which case an interrupt other than the
|
||||||
|
* SysTick must have brought the system out of sleep mode). */
|
||||||
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt is already pending, and the SysTick count
|
||||||
|
* reloaded with ulReloadValue. Reset the
|
||||||
|
* portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
|
* period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
* underflowed because the post sleep hook did something
|
||||||
|
* that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* As the pending tick will be processed as soon as this
|
||||||
|
* function exits, the tick value maintained by the tick is
|
||||||
|
* stepped forward by one less than the time spent waiting. */
|
||||||
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep.
|
||||||
|
* Work out how long the sleep lasted rounded to complete tick
|
||||||
|
* periods (not the ulReload value which accounted for part
|
||||||
|
* ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* How many complete tick periods passed while the processor
|
||||||
|
* was waiting? */
|
||||||
|
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||||
|
|
||||||
|
/* The reload value is set to whatever fraction of a single tick
|
||||||
|
* period remains. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||||
|
* again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||||
|
* value. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Exit with interrupts enabled. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
/* Stop and reset the SysTick. */
|
/* Stop and reset the SysTick. */
|
||||||
*( portNVIC_SYSTICK_CTRL ) = 0UL;
|
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||||
*( portNVIC_SYSTICK_CURRENT_VALUE ) = 0UL;
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
/* Configure SysTick to interrupt at the requested rate. */
|
/* Configure SysTick to interrupt at the requested rate. */
|
||||||
*( portNVIC_SYSTICK_LOAD ) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||||
*( portNVIC_SYSTICK_CTRL ) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -446,11 +662,11 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
( portMPU_RLAR_REGION_ENABLE );
|
( portMPU_RLAR_REGION_ENABLE );
|
||||||
|
|
||||||
/* Enable mem fault. */
|
/* Enable mem fault. */
|
||||||
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE;
|
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
|
||||||
|
|
||||||
/* Enable MPU with privileged background access i.e. unmapped
|
/* Enable MPU with privileged background access i.e. unmapped
|
||||||
* regions have privileged access. */
|
* regions have privileged access. */
|
||||||
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE | portMPU_ENABLE );
|
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* configENABLE_MPU */
|
#endif /* configENABLE_MPU */
|
||||||
|
@ -484,7 +700,7 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Set a PendSV to request a context switch. */
|
/* Set a PendSV to request a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
|
||||||
/* Barriers are normally not required but do ensure the code is
|
/* Barriers are normally not required but do ensure the code is
|
||||||
* completely within the specified behaviour for the architecture. */
|
* completely within the specified behaviour for the architecture. */
|
||||||
|
@ -527,7 +743,7 @@ uint32_t ulPreviousMask;
|
||||||
if( xTaskIncrementTick() != pdFALSE )
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
{
|
{
|
||||||
/* Pend a context switch. */
|
/* Pend a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||||
|
@ -772,8 +988,8 @@ uint8_t ucSVCNumber;
|
||||||
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
#if( configENABLE_MPU == 1 )
|
#if( configENABLE_MPU == 1 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
*
|
*
|
||||||
* 1 tab == 4 spaces!
|
* 1 tab == 4 spaces!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||||
contains code not understood by the assembler - for example the 'extern' keyword.
|
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||||
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||||
|
|
|
@ -227,6 +227,15 @@ typedef struct MPU_SETTINGS
|
||||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tickless idle/low power functionality.
|
||||||
|
*/
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -71,25 +71,32 @@
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to manipulate the NVIC.
|
* @brief Constants required to manipulate the NVIC.
|
||||||
*/
|
*/
|
||||||
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
|
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||||
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 )
|
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||||
#define portNVIC_SYSTICK_CURRENT_VALUE ( ( volatile uint32_t * ) 0xe000e018 )
|
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||||
#define portNVIC_INT_CTRL ( ( volatile uint32_t * ) 0xe000ed04 )
|
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
#define portNVIC_SYSPRI2 ( ( volatile uint32_t * ) 0xe000ed20 )
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
#define portNVIC_SYSTICK_CLK ( 0x00000004 )
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
#define portNVIC_SYSTICK_INT ( 0x00000002 )
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001 )
|
|
||||||
#define portNVIC_PENDSVSET ( 0x10000000 )
|
|
||||||
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||||
#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 )
|
||||||
|
#ifndef configSYSTICK_CLOCK_HZ
|
||||||
|
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||||
|
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
|
#else
|
||||||
|
/* The way the SysTick is clocked is not modified in case it is not the
|
||||||
|
* same a the core. */
|
||||||
|
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||||
|
#endif
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 )
|
||||||
#define portSCB_MEM_FAULT_ENABLE ( 1UL << 16UL )
|
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -169,15 +176,30 @@
|
||||||
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
||||||
|
|
||||||
/* Enable privileged access to unmapped region. */
|
/* Enable privileged access to unmapped region. */
|
||||||
#define portMPU_PRIV_BACKGROUND_ENABLE ( 1UL << 2UL )
|
#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL )
|
||||||
|
|
||||||
/* Enable MPU. */
|
/* Enable MPU. */
|
||||||
#define portMPU_ENABLE ( 1UL << 0UL )
|
#define portMPU_ENABLE_BIT ( 1UL << 0UL )
|
||||||
|
|
||||||
/* Expected value of the portMPU_TYPE register. */
|
/* Expected value of the portMPU_TYPE register. */
|
||||||
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum 24-bit number.
|
||||||
|
*
|
||||||
|
* It is needed because the systick is a 24-bit counter.
|
||||||
|
*/
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A fiddle factor to estimate the number of SysTick counts that would
|
||||||
|
* have occurred while the SysTick counter is stopped during tickless idle
|
||||||
|
* calculations.
|
||||||
|
*/
|
||||||
|
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constants required to set up the initial stack.
|
* @brief Constants required to set up the initial stack.
|
||||||
*/
|
*/
|
||||||
|
@ -332,17 +354,211 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
|
||||||
*/
|
*/
|
||||||
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
||||||
#endif /* configENABLE_TRUSTZONE */
|
#endif /* configENABLE_TRUSTZONE */
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
/**
|
||||||
|
* @brief The number of SysTick increments that make up one tick period.
|
||||||
|
*/
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum number of tick periods that can be suppressed is
|
||||||
|
* limited by the 24 bit resolution of the SysTick timer.
|
||||||
|
*/
|
||||||
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compensate for the CPU cycles that pass while the SysTick is
|
||||||
|
* stopped (low power functionality only).
|
||||||
|
*/
|
||||||
|
static uint32_t ulStoppedTimerCompensation = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
__attribute__(( weak )) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||||
|
{
|
||||||
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
|
||||||
|
TickType_t xModifiableIdleTime;
|
||||||
|
|
||||||
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||||
|
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||||
|
{
|
||||||
|
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the SysTick momentarily. The time the SysTick is stopped for is
|
||||||
|
* accounted for as best it can be, but using the tickless mode will
|
||||||
|
* inevitably result in some tiny drift of the time maintained by the
|
||||||
|
* kernel with respect to calendar time. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||||
|
* tick periods. -1 is used because this code will execute part way
|
||||||
|
* through one of the tick periods. */
|
||||||
|
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||||
|
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||||
|
{
|
||||||
|
ulReloadValue -= ulStoppedTimerCompensation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||||
|
* method as that will mask interrupts that should exit sleep mode. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* If a context switch is pending or a task is waiting for the scheduler
|
||||||
|
* to be un-suspended then abandon the low power entry. */
|
||||||
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
* this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
* periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||||
|
* above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the new reload value. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||||
|
|
||||||
|
/* Clear the SysTick count flag and set the count value back to
|
||||||
|
* zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||||
|
* set its parameter to 0 to indicate that its implementation
|
||||||
|
* contains its own wait for interrupt or wait for event
|
||||||
|
* instruction, and so wfi should not be executed again. However,
|
||||||
|
* the original expected idle time variable must remain unmodified,
|
||||||
|
* so a copy is taken. */
|
||||||
|
xModifiableIdleTime = xExpectedIdleTime;
|
||||||
|
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||||
|
if( xModifiableIdleTime > 0 )
|
||||||
|
{
|
||||||
|
__asm volatile( "dsb" ::: "memory" );
|
||||||
|
__asm volatile( "wfi" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
}
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||||
|
* out of sleep mode to execute immediately. See comments above
|
||||||
|
* the cpsid instruction above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable interrupts again because the clock is about to be stopped
|
||||||
|
* and interrupts that execute while the clock is stopped will
|
||||||
|
* increase any slippage between the time maintained by the RTOS and
|
||||||
|
* calendar time. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable the SysTick clock without reading the
|
||||||
|
* portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||||
|
* portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set.
|
||||||
|
* Again, the time the SysTick is stopped for is accounted for as
|
||||||
|
* best it can be, but using the tickless mode will inevitably
|
||||||
|
* result in some tiny drift of the time maintained by the kernel
|
||||||
|
* with respect to calendar time*/
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
|
||||||
|
|
||||||
|
/* Determine if the SysTick clock has already counted to zero and
|
||||||
|
* been set back to the current reload value (the reload back being
|
||||||
|
* correct for the entire expected idle time) or if the SysTick is
|
||||||
|
* yet to count to zero (in which case an interrupt other than the
|
||||||
|
* SysTick must have brought the system out of sleep mode). */
|
||||||
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt is already pending, and the SysTick count
|
||||||
|
* reloaded with ulReloadValue. Reset the
|
||||||
|
* portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
|
* period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
* underflowed because the post sleep hook did something
|
||||||
|
* that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* As the pending tick will be processed as soon as this
|
||||||
|
* function exits, the tick value maintained by the tick is
|
||||||
|
* stepped forward by one less than the time spent waiting. */
|
||||||
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep.
|
||||||
|
* Work out how long the sleep lasted rounded to complete tick
|
||||||
|
* periods (not the ulReload value which accounted for part
|
||||||
|
* ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* How many complete tick periods passed while the processor
|
||||||
|
* was waiting? */
|
||||||
|
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||||
|
|
||||||
|
/* The reload value is set to whatever fraction of a single tick
|
||||||
|
* period remains. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||||
|
* again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||||
|
* value. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Exit with interrupts enabled. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
/* Stop and reset the SysTick. */
|
/* Stop and reset the SysTick. */
|
||||||
*( portNVIC_SYSTICK_CTRL ) = 0UL;
|
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||||
*( portNVIC_SYSTICK_CURRENT_VALUE ) = 0UL;
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
/* Configure SysTick to interrupt at the requested rate. */
|
/* Configure SysTick to interrupt at the requested rate. */
|
||||||
*( portNVIC_SYSTICK_LOAD ) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||||
*( portNVIC_SYSTICK_CTRL ) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -446,11 +662,11 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
( portMPU_RLAR_REGION_ENABLE );
|
( portMPU_RLAR_REGION_ENABLE );
|
||||||
|
|
||||||
/* Enable mem fault. */
|
/* Enable mem fault. */
|
||||||
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE;
|
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
|
||||||
|
|
||||||
/* Enable MPU with privileged background access i.e. unmapped
|
/* Enable MPU with privileged background access i.e. unmapped
|
||||||
* regions have privileged access. */
|
* regions have privileged access. */
|
||||||
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE | portMPU_ENABLE );
|
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* configENABLE_MPU */
|
#endif /* configENABLE_MPU */
|
||||||
|
@ -484,7 +700,7 @@ volatile uint32_t ulDummy = 0UL;
|
||||||
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Set a PendSV to request a context switch. */
|
/* Set a PendSV to request a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
|
|
||||||
/* Barriers are normally not required but do ensure the code is
|
/* Barriers are normally not required but do ensure the code is
|
||||||
* completely within the specified behaviour for the architecture. */
|
* completely within the specified behaviour for the architecture. */
|
||||||
|
@ -527,7 +743,7 @@ uint32_t ulPreviousMask;
|
||||||
if( xTaskIncrementTick() != pdFALSE )
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
{
|
{
|
||||||
/* Pend a context switch. */
|
/* Pend a context switch. */
|
||||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||||
|
@ -772,8 +988,8 @@ uint8_t ucSVCNumber;
|
||||||
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||||
{
|
{
|
||||||
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
*( portNVIC_SYSPRI2 ) |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
#if( configENABLE_MPU == 1 )
|
#if( configENABLE_MPU == 1 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
*
|
*
|
||||||
* 1 tab == 4 spaces!
|
* 1 tab == 4 spaces!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||||
contains code not understood by the assembler - for example the 'extern' keyword.
|
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||||
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||||
|
|
|
@ -227,6 +227,15 @@ typedef struct MPU_SETTINGS
|
||||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tickless idle/low power functionality.
|
||||||
|
*/
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -506,6 +506,7 @@ __weak void vPortSetupTimerInterrupt( void )
|
||||||
|
|
||||||
static void prvSetupMPU( void )
|
static void prvSetupMPU( void )
|
||||||
{
|
{
|
||||||
|
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__[];
|
||||||
|
@ -515,7 +516,7 @@ extern uint32_t __privileged_data_end__[];
|
||||||
/* 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 )
|
||||||
{
|
{
|
||||||
/* First setup the entire flash for unprivileged read only access. */
|
/* First setup the unprivileged flash for unprivileged read only access. */
|
||||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
( portUNPRIVILEGED_FLASH_REGION );
|
( portUNPRIVILEGED_FLASH_REGION );
|
||||||
|
@ -525,16 +526,15 @@ extern uint32_t __privileged_data_end__[];
|
||||||
( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
||||||
( portMPU_REGION_ENABLE );
|
( portMPU_REGION_ENABLE );
|
||||||
|
|
||||||
/* Setup the first 16K for privileged only access (even though less
|
/* Setup the privileged flash for privileged only access. This is where
|
||||||
* than 10K is actually being used). This is where the kernel code is
|
* the kernel code is placed. */
|
||||||
* placed. */
|
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_functions_start__ ) | /* Base address. */
|
||||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
( portPRIVILEGED_FLASH_REGION );
|
( portPRIVILEGED_FLASH_REGION );
|
||||||
|
|
||||||
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) |
|
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) |
|
||||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||||
( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__ ) ) |
|
||||||
( portMPU_REGION_ENABLE );
|
( portMPU_REGION_ENABLE );
|
||||||
|
|
||||||
/* Setup the privileged data RAM region. This is where the kernel data
|
/* Setup the privileged data RAM region. This is where the kernel data
|
||||||
|
|
|
@ -638,6 +638,7 @@ __asm void vPortEnableVFP( void )
|
||||||
|
|
||||||
static void prvSetupMPU( void )
|
static void prvSetupMPU( void )
|
||||||
{
|
{
|
||||||
|
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__;
|
||||||
|
@ -647,7 +648,7 @@ extern uint32_t __privileged_data_end__;
|
||||||
/* 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 )
|
||||||
{
|
{
|
||||||
/* First setup the entire flash for unprivileged read only access. */
|
/* First setup the unprivileged flash for unprivileged read only access. */
|
||||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
( portUNPRIVILEGED_FLASH_REGION );
|
( portUNPRIVILEGED_FLASH_REGION );
|
||||||
|
@ -657,16 +658,15 @@ extern uint32_t __privileged_data_end__;
|
||||||
( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
||||||
( portMPU_REGION_ENABLE );
|
( portMPU_REGION_ENABLE );
|
||||||
|
|
||||||
/* Setup the first 16K for privileged only access (even though less
|
/* Setup the privileged flash for privileged only access. This is where
|
||||||
* than 10K is actually being used). This is where the kernel code is
|
* the kernel code is placed. */
|
||||||
* placed. */
|
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_functions_start__ ) | /* Base address. */
|
||||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
( portPRIVILEGED_FLASH_REGION );
|
( portPRIVILEGED_FLASH_REGION );
|
||||||
|
|
||||||
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) |
|
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) |
|
||||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||||
( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__ ) ) |
|
||||||
( portMPU_REGION_ENABLE );
|
( portMPU_REGION_ENABLE );
|
||||||
|
|
||||||
/* Setup the privileged data RAM region. This is where the kernel data
|
/* Setup the privileged data RAM region. This is where the kernel data
|
||||||
|
|
52
portable/ThirdParty/GCC/ARC_EM_HS/arc_freertos_exceptions.c
vendored
Normal file
52
portable/ThirdParty/GCC/ARC_EM_HS/arc_freertos_exceptions.c
vendored
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.2.1
|
||||||
|
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* http://www.FreeRTOS.org
|
||||||
|
* http://aws.amazon.com/freertos
|
||||||
|
*
|
||||||
|
* 1 tab == 4 spaces!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* \brief exception processing for freertos
|
||||||
|
*/
|
||||||
|
|
||||||
|
// #include "embARC.h"
|
||||||
|
|
||||||
|
#include "arc_freertos_exceptions.h"
|
||||||
|
|
||||||
|
#ifdef __GNU__
|
||||||
|
extern void gnu_printf_setup(void);
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* \brief freertos related cpu exception initialization, all the interrupts handled by freertos must be not
|
||||||
|
* fast irqs. If fiq is needed, please install the default firq_exc_entry or your own fast irq entry into
|
||||||
|
* the specific interrupt exception.
|
||||||
|
*/
|
||||||
|
void freertos_exc_init(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef __GNU__
|
||||||
|
gnu_printf_setup();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
45
portable/ThirdParty/GCC/ARC_EM_HS/arc_freertos_exceptions.h
vendored
Normal file
45
portable/ThirdParty/GCC/ARC_EM_HS/arc_freertos_exceptions.h
vendored
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.2.1
|
||||||
|
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* http://www.FreeRTOS.org
|
||||||
|
* http://aws.amazon.com/freertos
|
||||||
|
*
|
||||||
|
* 1 tab == 4 spaces!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ARC_FREERTOS_EXCEPTIONS_H
|
||||||
|
#define ARC_FREERTOS_EXCEPTIONS_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* here, all arc cpu exceptions share the same entry, also for all interrupt
|
||||||
|
* exceptions
|
||||||
|
*/
|
||||||
|
extern void exc_entry_cpu(void); /* cpu exception entry for freertos */
|
||||||
|
extern void exc_entry_int(void); /* int exception entry for freertos */
|
||||||
|
|
||||||
|
/* task dispatch functions in .s */
|
||||||
|
extern void start_r(void);
|
||||||
|
extern void start_dispatch();
|
||||||
|
extern void dispatch();
|
||||||
|
|
||||||
|
extern void freertos_exc_init(void);
|
||||||
|
|
||||||
|
#endif /* ARC_FREERTOS_EXCEPTIONS_H */
|
521
portable/ThirdParty/GCC/ARC_EM_HS/arc_support.s
vendored
Normal file
521
portable/ThirdParty/GCC/ARC_EM_HS/arc_support.s
vendored
Normal file
|
@ -0,0 +1,521 @@
|
||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.2.1
|
||||||
|
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* http://www.FreeRTOS.org
|
||||||
|
* http://aws.amazon.com/freertos
|
||||||
|
*
|
||||||
|
* 1 tab == 4 spaces!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file
|
||||||
|
* \ingroup OS_FREERTOS
|
||||||
|
* \brief freertos support for arc processor
|
||||||
|
* like task dispatcher, interrupt handler
|
||||||
|
*/
|
||||||
|
/** @cond OS_FREERTOS_ASM_ARC_SUPPORT */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* core-dependent part in assemble language (for arc)
|
||||||
|
*/
|
||||||
|
#define __ASSEMBLY__
|
||||||
|
#include "arc/arc.h"
|
||||||
|
#include "arc/arc_asm_common.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* task dispatcher
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
.text
|
||||||
|
.align 4
|
||||||
|
.global dispatch
|
||||||
|
dispatch:
|
||||||
|
/*
|
||||||
|
* the pre-conditions of this routine are task context, CPU is
|
||||||
|
* locked, dispatch is enabled.
|
||||||
|
*/
|
||||||
|
SAVE_NONSCRATCH_REGS /* save callee save registers */
|
||||||
|
mov r1, dispatch_r
|
||||||
|
PUSH r1 /* save return address */
|
||||||
|
ld r0, [pxCurrentTCB]
|
||||||
|
bl dispatcher
|
||||||
|
|
||||||
|
/* return routine when task dispatch happened in task context */
|
||||||
|
dispatch_r:
|
||||||
|
RESTORE_NONSCRATCH_REGS /* recover registers */
|
||||||
|
j [blink]
|
||||||
|
|
||||||
|
/*
|
||||||
|
* start dispatch
|
||||||
|
*/
|
||||||
|
.global start_dispatch
|
||||||
|
.align 4
|
||||||
|
start_dispatch:
|
||||||
|
/*
|
||||||
|
* this routine is called in the non-task context during the startup of the kernel
|
||||||
|
* , and all the interrupts are locked.
|
||||||
|
*
|
||||||
|
* when the dispatcher is called, the cpu is locked, no nest exception (CPU exception/interrupt).
|
||||||
|
* In target_initialize, all interrupt priority mask should be cleared, cpu should be
|
||||||
|
* locked, the interrupts outside the kernel such as fiq can be
|
||||||
|
* enabled.
|
||||||
|
*/
|
||||||
|
clri
|
||||||
|
mov r0, 0
|
||||||
|
st r0, [exc_nest_count]
|
||||||
|
b dispatcher_0
|
||||||
|
/*
|
||||||
|
* dispatcher
|
||||||
|
*/
|
||||||
|
dispatcher:
|
||||||
|
ld r1, [ulCriticalNesting]
|
||||||
|
PUSH r1 /* save critical nesting */
|
||||||
|
st sp, [r0] /* save stack pointer of current task, r0->pxCurrentTCB */
|
||||||
|
jl vTaskSwitchContext /* change the value of pxCurrentTCB */
|
||||||
|
/*
|
||||||
|
* before dispatcher is called, task context | cpu locked | dispatch enabled
|
||||||
|
* should be satisfied. In this routine, the processor will jump
|
||||||
|
* into the entry of next to run task
|
||||||
|
*
|
||||||
|
* i.e. kernel mode, IRQ disabled, dispatch enabled
|
||||||
|
*/
|
||||||
|
dispatcher_0:
|
||||||
|
ld r1, [pxCurrentTCB]
|
||||||
|
ld sp, [r1] /* recover task stack */
|
||||||
|
#if ARC_FEATURE_STACK_CHECK
|
||||||
|
#if ARC_FEATURE_SEC_PRESENT
|
||||||
|
lr r0, [AUX_SEC_STAT]
|
||||||
|
bclr r0, r0, AUX_SEC_STAT_BIT_SSC
|
||||||
|
sflag r0
|
||||||
|
#else
|
||||||
|
lr r0, [AUX_STATUS32]
|
||||||
|
bclr r0, r0, AUX_STATUS_BIT_SC
|
||||||
|
kflag r0
|
||||||
|
#endif
|
||||||
|
jl vPortSetStackCheck
|
||||||
|
#if ARC_FEATURE_SEC_PRESENT
|
||||||
|
lr r0, [AUX_SEC_STAT]
|
||||||
|
bset r0, r0, AUX_SEC_STAT_BIT_SSC
|
||||||
|
sflag r0
|
||||||
|
#else
|
||||||
|
lr r0, [AUX_STATUS32]
|
||||||
|
bset r0, r0, AUX_STATUS_BIT_SC
|
||||||
|
kflag r0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
POP r0 /* get critical nesting */
|
||||||
|
st r0, [ulCriticalNesting]
|
||||||
|
POP r0 /* get return address */
|
||||||
|
j [r0]
|
||||||
|
|
||||||
|
/*
|
||||||
|
* task startup routine
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
.text
|
||||||
|
.global start_r
|
||||||
|
.align 4
|
||||||
|
start_r:
|
||||||
|
seti /* unlock cpu */
|
||||||
|
mov blink, vPortEndTask /* set return address */
|
||||||
|
POP r1 /* get task function body */
|
||||||
|
POP r0 /* get task parameters */
|
||||||
|
j [r1]
|
||||||
|
|
||||||
|
/****** exceptions and interrupts handing ******/
|
||||||
|
/****** entry for exception handling ******/
|
||||||
|
.global exc_entry_cpu
|
||||||
|
.align 4
|
||||||
|
exc_entry_cpu:
|
||||||
|
|
||||||
|
EXCEPTION_PROLOGUE
|
||||||
|
|
||||||
|
mov blink, sp
|
||||||
|
mov r3, sp /* as exception handler's para(p_excinfo) */
|
||||||
|
|
||||||
|
ld r0, [exc_nest_count]
|
||||||
|
add r1, r0, 1
|
||||||
|
st r1, [exc_nest_count]
|
||||||
|
brne r0, 0, exc_handler_1
|
||||||
|
/* change to exception stack if interrupt happened in task context */
|
||||||
|
mov sp, _e_stack
|
||||||
|
exc_handler_1:
|
||||||
|
PUSH blink
|
||||||
|
|
||||||
|
lr r0, [AUX_ECR]
|
||||||
|
lsr r0, r0, 16
|
||||||
|
mov r1, exc_int_handler_table
|
||||||
|
ld.as r2, [r1, r0]
|
||||||
|
|
||||||
|
mov r0, r3
|
||||||
|
jl [r2] /* !!!!jump to exception handler where interrupts are not allowed! */
|
||||||
|
|
||||||
|
/* interrupts are not allowed */
|
||||||
|
ret_exc:
|
||||||
|
POP sp
|
||||||
|
mov r1, exc_nest_count
|
||||||
|
ld r0, [r1]
|
||||||
|
sub r0, r0, 1
|
||||||
|
st r0, [r1]
|
||||||
|
brne r0, 0, ret_exc_1 /* nest exception case */
|
||||||
|
lr r1, [AUX_IRQ_ACT] /* nest interrupt case */
|
||||||
|
brne r1, 0, ret_exc_1
|
||||||
|
|
||||||
|
ld r0, [context_switch_reqflg]
|
||||||
|
brne r0, 0, ret_exc_2
|
||||||
|
ret_exc_1: /* return from non-task context, interrupts or exceptions are nested */
|
||||||
|
|
||||||
|
EXCEPTION_EPILOGUE
|
||||||
|
rtie
|
||||||
|
|
||||||
|
/* there is a dispatch request */
|
||||||
|
ret_exc_2:
|
||||||
|
/* clear dispatch request */
|
||||||
|
mov r0, 0
|
||||||
|
st r0, [context_switch_reqflg]
|
||||||
|
|
||||||
|
ld r0, [pxCurrentTCB]
|
||||||
|
breq r0, 0, ret_exc_1
|
||||||
|
|
||||||
|
SAVE_CALLEE_REGS /* save callee save registers */
|
||||||
|
|
||||||
|
lr r0, [AUX_STATUS32]
|
||||||
|
bclr r0, r0, AUX_STATUS_BIT_AE /* clear exception bit */
|
||||||
|
kflag r0
|
||||||
|
|
||||||
|
mov r1, ret_exc_r /* save return address */
|
||||||
|
PUSH r1
|
||||||
|
|
||||||
|
bl dispatcher /* r0->pxCurrentTCB */
|
||||||
|
|
||||||
|
ret_exc_r:
|
||||||
|
/* recover exception status */
|
||||||
|
lr r0, [AUX_STATUS32]
|
||||||
|
bset r0, r0, AUX_STATUS_BIT_AE
|
||||||
|
kflag r0
|
||||||
|
|
||||||
|
RESTORE_CALLEE_REGS /* recover registers */
|
||||||
|
EXCEPTION_EPILOGUE
|
||||||
|
rtie
|
||||||
|
|
||||||
|
/****** entry for normal interrupt exception handling ******/
|
||||||
|
.global exc_entry_int /* entry for interrupt handling */
|
||||||
|
.align 4
|
||||||
|
exc_entry_int:
|
||||||
|
#if ARC_FEATURE_FIRQ == 1
|
||||||
|
#if ARC_FEATURE_RGF_NUM_BANKS > 1
|
||||||
|
lr r0, [AUX_IRQ_ACT] /* check whether it is P0 interrupt */
|
||||||
|
btst r0, 0
|
||||||
|
jnz exc_entry_firq
|
||||||
|
#else
|
||||||
|
PUSH r10
|
||||||
|
lr r10, [AUX_IRQ_ACT]
|
||||||
|
btst r10, 0
|
||||||
|
POP r10
|
||||||
|
jnz exc_entry_firq
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
INTERRUPT_PROLOGUE
|
||||||
|
|
||||||
|
mov blink, sp
|
||||||
|
|
||||||
|
clri /* disable interrupt */
|
||||||
|
ld r3, [exc_nest_count]
|
||||||
|
add r2, r3, 1
|
||||||
|
st r2, [exc_nest_count]
|
||||||
|
seti /* enable higher priority interrupt */
|
||||||
|
|
||||||
|
brne r3, 0, irq_handler_1
|
||||||
|
/* change to exception stack if interrupt happened in task context */
|
||||||
|
mov sp, _e_stack
|
||||||
|
#if ARC_FEATURE_STACK_CHECK
|
||||||
|
#if ARC_FEATURE_SEC_PRESENT
|
||||||
|
lr r0, [AUX_SEC_STAT]
|
||||||
|
bclr r0, r0, AUX_SEC_STAT_BIT_SSC
|
||||||
|
sflag r0
|
||||||
|
#else
|
||||||
|
lr r0, [AUX_STATUS32]
|
||||||
|
bclr r0, r0, AUX_STATUS_BIT_SC
|
||||||
|
kflag r0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
irq_handler_1:
|
||||||
|
PUSH blink
|
||||||
|
|
||||||
|
lr r0, [AUX_IRQ_CAUSE]
|
||||||
|
mov r1, exc_int_handler_table
|
||||||
|
ld.as r2, [r1, r0] /* r2 = exc_int_handler_table + irqno *4 */
|
||||||
|
/* handle software triggered interrupt */
|
||||||
|
lr r3, [AUX_IRQ_HINT]
|
||||||
|
cmp r3, r0
|
||||||
|
bne.d irq_hint_handled
|
||||||
|
xor r3, r3, r3
|
||||||
|
sr r3, [AUX_IRQ_HINT]
|
||||||
|
irq_hint_handled:
|
||||||
|
|
||||||
|
jl [r2] /* jump to interrupt handler */
|
||||||
|
/* no interrupts are allowed from here */
|
||||||
|
ret_int:
|
||||||
|
clri /* disable interrupt */
|
||||||
|
|
||||||
|
POP sp
|
||||||
|
mov r1, exc_nest_count
|
||||||
|
ld r0, [r1]
|
||||||
|
sub r0, r0, 1
|
||||||
|
st r0, [r1]
|
||||||
|
/* if there are multi-bits set in IRQ_ACT, it's still in nest interrupt */
|
||||||
|
lr r0, [AUX_IRQ_CAUSE]
|
||||||
|
sr r0, [AUX_IRQ_SELECT]
|
||||||
|
lr r3, [AUX_IRQ_PRIORITY]
|
||||||
|
lr r1, [AUX_IRQ_ACT]
|
||||||
|
bclr r2, r1, r3
|
||||||
|
brne r2, 0, ret_int_1
|
||||||
|
|
||||||
|
ld r0, [context_switch_reqflg]
|
||||||
|
brne r0, 0, ret_int_2
|
||||||
|
ret_int_1: /* return from non-task context */
|
||||||
|
INTERRUPT_EPILOGUE
|
||||||
|
rtie
|
||||||
|
/* there is a dispatch request */
|
||||||
|
ret_int_2:
|
||||||
|
/* clear dispatch request */
|
||||||
|
mov r0, 0
|
||||||
|
st r0, [context_switch_reqflg]
|
||||||
|
|
||||||
|
ld r0, [pxCurrentTCB]
|
||||||
|
breq r0, 0, ret_int_1
|
||||||
|
|
||||||
|
/* r1 has old AUX_IRQ_ACT */
|
||||||
|
PUSH r1
|
||||||
|
/* clear related bits in IRQ_ACT manually to simulate a irq return */
|
||||||
|
sr r2, [AUX_IRQ_ACT]
|
||||||
|
|
||||||
|
SAVE_CALLEE_REGS /* save callee save registers */
|
||||||
|
mov r1, ret_int_r /* save return address */
|
||||||
|
PUSH r1
|
||||||
|
|
||||||
|
bl dispatcher /* r0->pxCurrentTCB */
|
||||||
|
|
||||||
|
ret_int_r:
|
||||||
|
RESTORE_CALLEE_REGS /* recover registers */
|
||||||
|
POPAX AUX_IRQ_ACT
|
||||||
|
INTERRUPT_EPILOGUE
|
||||||
|
rtie
|
||||||
|
|
||||||
|
#if ARC_FEATURE_FIRQ == 1
|
||||||
|
.global exc_entry_firq
|
||||||
|
.align 4
|
||||||
|
exc_entry_firq:
|
||||||
|
#if ARC_FEATURE_STACK_CHECK && ARC_FEATURE_RGF_NUM_BANKS > 1
|
||||||
|
#if ARC_FEATURE_SEC_PRESENT
|
||||||
|
lr r0, [AUX_SEC_STAT]
|
||||||
|
bclr r0, r0, AUX_SEC_STAT_BIT_SSC
|
||||||
|
sflag r0
|
||||||
|
#else
|
||||||
|
lr r0, [AUX_STATUS32]
|
||||||
|
bclr r0, r0, AUX_STATUS_BIT_SC
|
||||||
|
kflag r0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
SAVE_FIQ_EXC_REGS
|
||||||
|
|
||||||
|
mov blink, sp
|
||||||
|
|
||||||
|
ld r3, [exc_nest_count]
|
||||||
|
add r2, r3, 1
|
||||||
|
st r2, [exc_nest_count]
|
||||||
|
|
||||||
|
brne r3, 0, firq_handler_1
|
||||||
|
#if ARC_FEATURE_STACK_CHECK && ARC_FEATURE_RGF_NUM_BANKS == 1
|
||||||
|
#if ARC_FEATURE_SEC_PRESENT
|
||||||
|
lr r0, [AUX_SEC_STAT]
|
||||||
|
bclr r0, r0, AUX_SEC_STAT_BIT_SSC
|
||||||
|
sflag r0
|
||||||
|
#else
|
||||||
|
lr r0, [AUX_STATUS32]
|
||||||
|
bclr r0, r0, AUX_STATUS_BIT_SC
|
||||||
|
kflag r0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
/* change to exception stack if interrupt happened in task context */
|
||||||
|
mov sp, _e_stack
|
||||||
|
firq_handler_1:
|
||||||
|
PUSH blink
|
||||||
|
|
||||||
|
lr r0, [AUX_IRQ_CAUSE]
|
||||||
|
mov r1, exc_int_handler_table
|
||||||
|
ld.as r2, [r1, r0] /* r2 = exc_int_handler_table + irqno *4 */
|
||||||
|
/* handle software triggered interrupt */
|
||||||
|
lr r3, [AUX_IRQ_HINT]
|
||||||
|
brne r3, r0, firq_hint_handled
|
||||||
|
xor r3, r3, r3
|
||||||
|
sr r3, [AUX_IRQ_HINT]
|
||||||
|
firq_hint_handled:
|
||||||
|
|
||||||
|
jl [r2] /* jump to interrupt handler */
|
||||||
|
/* no interrupts are allowed from here */
|
||||||
|
ret_firq:
|
||||||
|
clri
|
||||||
|
POP sp
|
||||||
|
|
||||||
|
mov r1, exc_nest_count
|
||||||
|
ld r0, [r1]
|
||||||
|
sub r0, r0, 1
|
||||||
|
st r0, [r1]
|
||||||
|
/* if there are multi-bits set in IRQ_ACT, it's still in nest interrupt */
|
||||||
|
lr r1, [AUX_IRQ_ACT]
|
||||||
|
bclr r1, r1, 0
|
||||||
|
brne r1, 0, ret_firq_1
|
||||||
|
|
||||||
|
ld r0, [context_switch_reqflg]
|
||||||
|
brne r0, 0, ret_firq_2
|
||||||
|
ret_firq_1: /* return from non-task context */
|
||||||
|
RESTORE_FIQ_EXC_REGS
|
||||||
|
rtie
|
||||||
|
/* there is a dispatch request */
|
||||||
|
ret_firq_2:
|
||||||
|
/* clear dispatch request */
|
||||||
|
mov r0, 0
|
||||||
|
st r0, [context_switch_reqflg]
|
||||||
|
|
||||||
|
ld r0, [pxCurrentTCB]
|
||||||
|
breq r0, 0, ret_firq_1
|
||||||
|
|
||||||
|
/* reconstruct the interruptted context
|
||||||
|
* When ARC_FEATURE_RGF_BANKED_REGS >= 16 (16, 32), sp is banked
|
||||||
|
* so need to restore the fast irq stack.
|
||||||
|
*/
|
||||||
|
#if ARC_FEATURE_RGF_BANKED_REGS >= 16
|
||||||
|
RESTORE_LP_REGS
|
||||||
|
#if ARC_FEATURE_CODE_DENSITY
|
||||||
|
RESTORE_CODE_DENSITY
|
||||||
|
#endif
|
||||||
|
RESTORE_R58_R59
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* when BANKED_REGS == 16, r4-r9 wiil be also saved in fast irq stack
|
||||||
|
* so pop them out
|
||||||
|
*/
|
||||||
|
#if ARC_FEATURE_RGF_BANKED_REGS == 16 && !defined(ARC_FEATURE_RF16)
|
||||||
|
POP r9
|
||||||
|
POP r8
|
||||||
|
POP r7
|
||||||
|
POP r6
|
||||||
|
POP r5
|
||||||
|
POP r4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* for other cases, unbanked regs are already in interrupted context's stack,
|
||||||
|
* so just need to save and pop the banked regs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* save the interruptted context */
|
||||||
|
#if ARC_FEATURE_RGF_BANKED_REGS > 0
|
||||||
|
/* switch back to bank0 */
|
||||||
|
lr r0, [AUX_STATUS32]
|
||||||
|
bic r0, r0, 0x70000
|
||||||
|
kflag r0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ARC_FEATURE_RGF_BANKED_REGS == 4
|
||||||
|
/* r4 - r12, gp, fp, r30, blink already saved */
|
||||||
|
PUSH r0
|
||||||
|
PUSH r1
|
||||||
|
PUSH r2
|
||||||
|
PUSH r3
|
||||||
|
#elif ARC_FEATURE_RGF_BANKED_REGS == 8
|
||||||
|
/* r4 - r9, r0, r11 gp, fp, r30, blink already saved */
|
||||||
|
PUSH r0
|
||||||
|
PUSH r1
|
||||||
|
PUSH r2
|
||||||
|
PUSH r3
|
||||||
|
PUSH r12
|
||||||
|
#elif ARC_FEATURE_RGF_BANKED_REGS >= 16
|
||||||
|
/* nothing is saved, */
|
||||||
|
SAVE_R0_TO_R12
|
||||||
|
|
||||||
|
SAVE_R58_R59
|
||||||
|
PUSH gp
|
||||||
|
PUSH fp
|
||||||
|
PUSH r30 /* general purpose */
|
||||||
|
PUSH blink
|
||||||
|
|
||||||
|
#if ARC_FEATURE_CODE_DENSITY
|
||||||
|
SAVE_CODE_DENSITY
|
||||||
|
#endif
|
||||||
|
SAVE_LP_REGS
|
||||||
|
#endif
|
||||||
|
PUSH ilink
|
||||||
|
lr r0, [AUX_STATUS32_P0]
|
||||||
|
PUSH r0
|
||||||
|
lr r0, [AUX_IRQ_ACT]
|
||||||
|
PUSH r0
|
||||||
|
bclr r0, r0, 0
|
||||||
|
sr r0, [AUX_IRQ_ACT]
|
||||||
|
|
||||||
|
SAVE_CALLEE_REGS /* save callee save registers */
|
||||||
|
|
||||||
|
mov r1, ret_firq_r /* save return address */
|
||||||
|
PUSH r1
|
||||||
|
ld r0, [pxCurrentTCB]
|
||||||
|
bl dispatcher /* r0->pxCurrentTCB */
|
||||||
|
|
||||||
|
ret_firq_r:
|
||||||
|
RESTORE_CALLEE_REGS /* recover registers */
|
||||||
|
POPAX AUX_IRQ_ACT
|
||||||
|
POPAX AUX_STATUS32_P0
|
||||||
|
POP ilink
|
||||||
|
|
||||||
|
#if ARC_FEATURE_RGF_NUM_BANKS > 1
|
||||||
|
#if ARC_FEATURE_RGF_BANKED_REGS == 4
|
||||||
|
/* r4 - r12, gp, fp, r30, blink already saved */
|
||||||
|
POP r3
|
||||||
|
POP r2
|
||||||
|
POP r1
|
||||||
|
POP r0
|
||||||
|
RESTORE_FIQ_EXC_REGS
|
||||||
|
#elif ARC_FEATURE_RGF_BANKED_REGS == 8
|
||||||
|
/* r4 - r9, gp, fp, r30, blink already saved */
|
||||||
|
POP r12
|
||||||
|
POP r3
|
||||||
|
POP r2
|
||||||
|
POP r1
|
||||||
|
POP r0
|
||||||
|
RESTORE_FIQ_EXC_REGS
|
||||||
|
#elif ARC_FEATURE_RGF_BANKED_REGS >= 16
|
||||||
|
RESTORE_LP_REGS
|
||||||
|
#if ARC_FEATURE_CODE_DENSITY
|
||||||
|
RESTORE_CODE_DENSITY
|
||||||
|
#endif
|
||||||
|
POP blink
|
||||||
|
POP r30
|
||||||
|
POP fp
|
||||||
|
POP gp
|
||||||
|
|
||||||
|
RESTORE_R58_R59
|
||||||
|
RESTORE_R0_TO_R12
|
||||||
|
#endif /* ARC_FEATURE_RGF_BANKED_REGS */
|
||||||
|
#else
|
||||||
|
RESTORE_FIQ_EXC_REGS
|
||||||
|
#endif /* ARC_FEATURE_RGF_NUM_BANKS */
|
||||||
|
rtie
|
||||||
|
#endif
|
||||||
|
/** @endcond */
|
205
portable/ThirdParty/GCC/ARC_EM_HS/freertos_tls.c
vendored
Normal file
205
portable/ThirdParty/GCC/ARC_EM_HS/freertos_tls.c
vendored
Normal file
|
@ -0,0 +1,205 @@
|
||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.2.1
|
||||||
|
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* http://www.FreeRTOS.org
|
||||||
|
* http://aws.amazon.com/freertos
|
||||||
|
*
|
||||||
|
* 1 tab == 4 spaces!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(__MW__)
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
|
||||||
|
#include "queue.h"
|
||||||
|
#include "semphr.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
#include "arc/arc_exception.h"
|
||||||
|
#include "embARC_toolchain.h"
|
||||||
|
#include "embARC_debug.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_FREERTOS_TLS_DEBUG
|
||||||
|
#define TLS_DEBUG(fmt, ...) EMBARC_PRINTF(fmt, ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define TLS_DEBUG(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Runtime routines to execute constructors and
|
||||||
|
* destructors for task local storage.
|
||||||
|
*/
|
||||||
|
extern void __mw_run_tls_dtor();
|
||||||
|
extern void __mw_run_tls_ctor();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Linker generated symbols to mark .tls section addresses
|
||||||
|
* first byte .. last byte
|
||||||
|
*/
|
||||||
|
extern char _ftls[], _etls[];
|
||||||
|
#pragma weak _ftls
|
||||||
|
#pragma weak _etls
|
||||||
|
|
||||||
|
void executable_requires_tls_section(void)
|
||||||
|
{
|
||||||
|
#if _ARC
|
||||||
|
for (;;) {
|
||||||
|
_flag(1);
|
||||||
|
_nop();
|
||||||
|
_nop();
|
||||||
|
_nop();
|
||||||
|
_nop();
|
||||||
|
_nop();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#pragma off_inline(executable_requires_tls_section);
|
||||||
|
#pragma alias(executable_requires_tls_section, "executable_requires_.tls_section");
|
||||||
|
|
||||||
|
static void* init_task_tls(void)
|
||||||
|
{
|
||||||
|
uint32_t len = (uint32_t)(_etls - _ftls);
|
||||||
|
void *tls = NULL;
|
||||||
|
|
||||||
|
#if FREERTOS_HEAP_SEL == 3
|
||||||
|
#warning "FreeRTOS TLS support is not compatible with heap 3 solution(FREERTOS_HEAP_SEL=3)!"
|
||||||
|
#warning "You can change FREERTOS_HEAP_SEL in freertos.mk to select other heap solution."
|
||||||
|
#else
|
||||||
|
tls = pvPortMalloc(len);
|
||||||
|
#endif
|
||||||
|
if (tls) {
|
||||||
|
TLS_DEBUG("Malloc task tls:%dbytes\r\n", len);
|
||||||
|
memcpy(tls, _ftls, len);
|
||||||
|
__mw_run_tls_ctor(); // Run constructors
|
||||||
|
}
|
||||||
|
return tls;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_task_tls(void *pxTCB)
|
||||||
|
{
|
||||||
|
TaskHandle_t task2free = (TaskHandle_t)pxTCB;
|
||||||
|
|
||||||
|
if (task2free != NULL) {
|
||||||
|
void *tls = pvTaskGetThreadLocalStoragePointer(task2free, 0);
|
||||||
|
if (tls) {
|
||||||
|
TLS_DEBUG("Free task tls\r\n");
|
||||||
|
__mw_run_tls_dtor();
|
||||||
|
vPortFree(tls);
|
||||||
|
vTaskSetThreadLocalStoragePointer(task2free, 0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void task_end_hook(void *pxTCB)
|
||||||
|
{
|
||||||
|
free_task_tls(pxTCB);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* get_isr_tls(void)
|
||||||
|
{
|
||||||
|
// In an ISR
|
||||||
|
static int first = 1;
|
||||||
|
if (_Rarely(first)) {
|
||||||
|
first = 0;
|
||||||
|
__mw_run_tls_ctor(); // Run constructors
|
||||||
|
}
|
||||||
|
return (void *)_ftls;
|
||||||
|
}
|
||||||
|
#pragma off_inline(get_isr_tls)
|
||||||
|
|
||||||
|
static void* get_task_tls(void)
|
||||||
|
{
|
||||||
|
TaskHandle_t cur_task;
|
||||||
|
|
||||||
|
cur_task = xTaskGetCurrentTaskHandle();
|
||||||
|
if (cur_task == NULL) return get_isr_tls();
|
||||||
|
void *tls = pvTaskGetThreadLocalStoragePointer(cur_task, 0);
|
||||||
|
if (tls == NULL) {
|
||||||
|
tls = init_task_tls();
|
||||||
|
if (tls) {
|
||||||
|
vTaskSetThreadLocalStoragePointer(cur_task, 0, tls);
|
||||||
|
} else {
|
||||||
|
tls = get_isr_tls();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tls;
|
||||||
|
}
|
||||||
|
#pragma off_inline(get_task_tls)
|
||||||
|
|
||||||
|
#if _ARC /* for ARC XCALLs need to preserve flags */
|
||||||
|
extern void * _Preserve_flags _mwget_tls(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Back end gens calls to find local data for this task
|
||||||
|
*/
|
||||||
|
void* _mwget_tls(void)
|
||||||
|
{
|
||||||
|
if (_ftls == (char *)0) {
|
||||||
|
executable_requires_tls_section();
|
||||||
|
}
|
||||||
|
if (exc_sense()) { /* In ISR */
|
||||||
|
return get_isr_tls();
|
||||||
|
} else { /* In Task */
|
||||||
|
return get_task_tls();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// simple interface of thread safe
|
||||||
|
typedef xSemaphoreHandle _lock_t;
|
||||||
|
#if configUSE_RECURSIVE_MUTEXES != 1
|
||||||
|
#error "configUSE_RECURSIVE_MUTEXES in FreeRTOSConfig.h need to 1"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void _mwmutex_create(_lock_t *mutex_ptr)
|
||||||
|
{
|
||||||
|
*mutex_ptr = xSemaphoreCreateRecursiveMutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _mwmutex_delete(_lock_t *mutex_ptr)
|
||||||
|
{
|
||||||
|
if ((*mutex_ptr) != NULL) {
|
||||||
|
vSemaphoreDelete(*mutex_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _mwmutex_lock(_lock_t mutex)
|
||||||
|
{
|
||||||
|
if ((mutex) != NULL) {
|
||||||
|
while (xSemaphoreTakeRecursive(mutex, portMAX_DELAY) != pdTRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _mwmutex_unlock(_lock_t mutex)
|
||||||
|
{
|
||||||
|
if ((mutex) != NULL) {
|
||||||
|
xSemaphoreGiveRecursive(mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#endif /* __MW__ */
|
283
portable/ThirdParty/GCC/ARC_EM_HS/port.c
vendored
Normal file
283
portable/ThirdParty/GCC/ARC_EM_HS/port.c
vendored
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.2.1
|
||||||
|
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* http://www.FreeRTOS.org
|
||||||
|
* http://aws.amazon.com/freertos
|
||||||
|
*
|
||||||
|
* 1 tab == 4 spaces!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implementation of functions defined in portable.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "FreeRTOSConfig.h"
|
||||||
|
|
||||||
|
#include "arc/arc_exception.h"
|
||||||
|
#include "arc/arc_timer.h"
|
||||||
|
#include "board.h"
|
||||||
|
|
||||||
|
#include "arc_freertos_exceptions.h"
|
||||||
|
|
||||||
|
volatile unsigned int ulCriticalNesting = 999UL;
|
||||||
|
volatile unsigned int context_switch_reqflg; /* task context switch request flag in exceptions and interrupts handling */
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @brief kernel tick interrupt handler of freertos
|
||||||
|
*/
|
||||||
|
/* ----------------------------------------------------------------------------*/
|
||||||
|
static void vKernelTick( void *ptr )
|
||||||
|
{
|
||||||
|
/* clear timer interrupt */
|
||||||
|
timer_int_clear(BOARD_OS_TIMER_ID);
|
||||||
|
board_timer_update(configTICK_RATE_HZ);
|
||||||
|
|
||||||
|
if (xTaskIncrementTick()) {
|
||||||
|
portYIELD_FROM_ISR(); /* need to make task switch */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @brief setup freertos kernel tick
|
||||||
|
*/
|
||||||
|
/* ----------------------------------------------------------------------------*/
|
||||||
|
static void prvSetupTimerInterrupt(void)
|
||||||
|
{
|
||||||
|
unsigned int cyc = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
|
||||||
|
|
||||||
|
int_disable(BOARD_OS_TIMER_INTNO); /* disable os timer interrupt */
|
||||||
|
timer_stop(BOARD_OS_TIMER_ID);
|
||||||
|
timer_start(BOARD_OS_TIMER_ID, TIMER_CTRL_IE | TIMER_CTRL_NH, cyc);
|
||||||
|
|
||||||
|
int_handler_install(BOARD_OS_TIMER_INTNO, (INT_HANDLER_T)vKernelTick);
|
||||||
|
int_pri_set(BOARD_OS_TIMER_INTNO, INT_PRI_MIN);
|
||||||
|
int_enable(BOARD_OS_TIMER_INTNO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the stack of a new task so it is ready to be placed under the
|
||||||
|
* scheduler control. The registers have to be placed on the stack in
|
||||||
|
* the order that the port expects to find them.
|
||||||
|
*
|
||||||
|
* For ARC, task context switch is implemented with the help of SWI exception
|
||||||
|
* It's not efficient but simple.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||||
|
{
|
||||||
|
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||||
|
is not really required. */
|
||||||
|
pxTopOfStack--;
|
||||||
|
|
||||||
|
/* Setup the initial stack of the task. The stack is set exactly as
|
||||||
|
expected by the portRESTORE_CONTEXT() macro. */
|
||||||
|
|
||||||
|
/* When the task starts is will expect to find the function parameter in
|
||||||
|
R0. */
|
||||||
|
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||||
|
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) pxCode; /* function body */
|
||||||
|
|
||||||
|
/* PC */
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = ( StackType_t ) start_r; /* dispatch return address */
|
||||||
|
|
||||||
|
pxTopOfStack--;
|
||||||
|
*pxTopOfStack = (StackType_t) portNO_CRITICAL_NESTING;
|
||||||
|
return pxTopOfStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @brief start the freertos scheduler, go to the first task
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
/* ----------------------------------------------------------------------------*/
|
||||||
|
BaseType_t xPortStartScheduler( void )
|
||||||
|
{
|
||||||
|
/* Start the timer that generates the tick ISR. */
|
||||||
|
prvSetupTimerInterrupt();
|
||||||
|
start_dispatch();
|
||||||
|
|
||||||
|
/* Should not get here! */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
/* ----------------------------------------------------------------------------*/
|
||||||
|
void vPortEndScheduler( void )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @brief generate a task switch request in ISR
|
||||||
|
*/
|
||||||
|
/* ----------------------------------------------------------------------------*/
|
||||||
|
void vPortYieldFromIsr(void)
|
||||||
|
{
|
||||||
|
unsigned int status32;
|
||||||
|
|
||||||
|
status32 = cpu_lock_save();
|
||||||
|
context_switch_reqflg = true;
|
||||||
|
cpu_unlock_restore(status32);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
/* ----------------------------------------------------------------------------*/
|
||||||
|
void vPortYield(void)
|
||||||
|
{
|
||||||
|
unsigned int status32;
|
||||||
|
|
||||||
|
status32 = cpu_lock_save();
|
||||||
|
dispatch();
|
||||||
|
cpu_unlock_restore(status32);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
/* ----------------------------------------------------------------------------*/
|
||||||
|
void vPortEndTask(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if ( INCLUDE_vTaskDelete == 1 )
|
||||||
|
vTaskDelete(NULL); /* Delete task itself */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while(1) { /* Yield to other task */
|
||||||
|
vPortYield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ARC_FEATURE_STACK_CHECK
|
||||||
|
|
||||||
|
/*
|
||||||
|
* !!! Note !!!
|
||||||
|
* This a trick!!!
|
||||||
|
* It's a copy from task.c. We need to konw the definition of TCB for the purpose of hardware
|
||||||
|
* stack check. Pls don't forget to update it when FreeRTOS is updated.
|
||||||
|
*/
|
||||||
|
typedef struct tskTaskControlBlock /* The old naming convention is used to prevent breaking kernel aware debuggers. */
|
||||||
|
{
|
||||||
|
volatile StackType_t *pxTopOfStack; /*< Points to the location of the last item placed on the tasks stack. THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */
|
||||||
|
|
||||||
|
#if ( portUSING_MPU_WRAPPERS == 1 )
|
||||||
|
xMPU_SETTINGS xMPUSettings; /*< The MPU settings are defined as part of the port layer. THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ListItem_t xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
|
||||||
|
ListItem_t xEventListItem; /*< Used to reference a task from an event list. */
|
||||||
|
UBaseType_t uxPriority; /*< The priority of the task. 0 is the lowest priority. */
|
||||||
|
StackType_t *pxStack; /*< Points to the start of the stack. */
|
||||||
|
char pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created. Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
|
||||||
|
|
||||||
|
#if ( ( portSTACK_GROWTH > 0 ) || ( configRECORD_STACK_HIGH_ADDRESS == 1 ) )
|
||||||
|
StackType_t *pxEndOfStack; /*< Points to the highest valid address for the stack. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
|
||||||
|
UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
||||||
|
UBaseType_t uxTCBNumber; /*< Stores a number that increments each time a TCB is created. It allows debuggers to determine when a task has been deleted and then recreated. */
|
||||||
|
UBaseType_t uxTaskNumber; /*< Stores a number specifically for use by third party trace code. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ( configUSE_MUTEXES == 1 )
|
||||||
|
UBaseType_t uxBasePriority; /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
|
||||||
|
UBaseType_t uxMutexesHeld;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
|
||||||
|
TaskHookFunction_t pxTaskTag;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
|
||||||
|
void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if( configGENERATE_RUN_TIME_STATS == 1 )
|
||||||
|
uint32_t ulRunTimeCounter; /*< Stores the amount of time the task has spent in the Running state. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ( configUSE_NEWLIB_REENTRANT == 1 )
|
||||||
|
/* Allocate a Newlib reent structure that is specific to this task.
|
||||||
|
Note Newlib support has been included by popular demand, but is not
|
||||||
|
used by the FreeRTOS maintainers themselves. FreeRTOS is not
|
||||||
|
responsible for resulting newlib operation. User must be familiar with
|
||||||
|
newlib and must provide system-wide implementations of the necessary
|
||||||
|
stubs. Be warned that (at the time of writing) the current newlib design
|
||||||
|
implements a system-wide malloc() that must be provided with locks. */
|
||||||
|
struct _reent xNewLib_reent;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if( configUSE_TASK_NOTIFICATIONS == 1 )
|
||||||
|
volatile uint32_t ulNotifiedValue;
|
||||||
|
volatile uint8_t ucNotifyState;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* See the comments above the definition of
|
||||||
|
tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
|
||||||
|
#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
|
||||||
|
uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if( INCLUDE_xTaskAbortDelay == 1 )
|
||||||
|
uint8_t ucDelayAborted;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if( configUSE_POSIX_ERRNO == 1 )
|
||||||
|
int iTaskErrno;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} tskTCB;
|
||||||
|
|
||||||
|
|
||||||
|
void vPortSetStackCheck(TaskHandle_t old, TaskHandle_t new)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (new != NULL) {
|
||||||
|
#if ARC_FEATURE_SEC_PRESENT
|
||||||
|
arc_aux_write(AUX_S_KSTACK_BASE, (uint32_t)(new->pxEndOfStack));
|
||||||
|
arc_aux_write(AUX_S_KSTACK_TOP, (uint32_t)(new->pxStack));
|
||||||
|
#else
|
||||||
|
arc_aux_write(AUX_KSTACK_BASE, (uint32_t)(new->pxEndOfStack));
|
||||||
|
arc_aux_write(AUX_KSTACK_TOP, (uint32_t)(new->pxStack));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
158
portable/ThirdParty/GCC/ARC_EM_HS/portmacro.h
vendored
Normal file
158
portable/ThirdParty/GCC/ARC_EM_HS/portmacro.h
vendored
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.2.1
|
||||||
|
* Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* http://www.FreeRTOS.org
|
||||||
|
* http://aws.amazon.com/freertos
|
||||||
|
*
|
||||||
|
* 1 tab == 4 spaces!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* record stack high address for stack check */
|
||||||
|
#ifndef configRECORD_STACK_HIGH_ADDRESS
|
||||||
|
#define configRECORD_STACK_HIGH_ADDRESS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the
|
||||||
|
* given hardware and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*-----------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Type definitions. */
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT float
|
||||||
|
#define portDOUBLE double
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT short
|
||||||
|
#define portSTACK_TYPE unsigned int
|
||||||
|
#define portBASE_TYPE portLONG
|
||||||
|
|
||||||
|
#ifndef Inline
|
||||||
|
#define Inline static __inline__
|
||||||
|
#endif
|
||||||
|
#ifndef Asm
|
||||||
|
#define Asm __asm__ volatile
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* normal constants
|
||||||
|
*/
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL 0 /* invalid pointer */
|
||||||
|
#endif /* NULL */
|
||||||
|
|
||||||
|
#ifndef true
|
||||||
|
#define true 1 /* true */
|
||||||
|
#endif /* true */
|
||||||
|
|
||||||
|
#ifndef false
|
||||||
|
#define false 0 /* false */
|
||||||
|
#endif /* false */
|
||||||
|
|
||||||
|
typedef portSTACK_TYPE StackType_t;
|
||||||
|
typedef long BaseType_t;
|
||||||
|
typedef unsigned long UBaseType_t;
|
||||||
|
|
||||||
|
#if( configUSE_16_BIT_TICKS == 1 )
|
||||||
|
typedef uint16_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||||
|
#else
|
||||||
|
typedef unsigned int TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define portNO_CRITICAL_NESTING 0x0
|
||||||
|
#define portSTACK_GROWTH ( -1 )
|
||||||
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
#define portNOP() Asm( "nop_s" );
|
||||||
|
#define IPM_ENABLE_ALL 1
|
||||||
|
|
||||||
|
#define portYIELD_FROM_ISR() vPortYieldFromIsr()
|
||||||
|
#define portYIELD() vPortYield()
|
||||||
|
|
||||||
|
/* Critical section management. */
|
||||||
|
#define portDISABLE_INTERRUPTS() \
|
||||||
|
{ \
|
||||||
|
Asm("clri"); \
|
||||||
|
Asm("":::"memory"); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define portENABLE_INTERRUPTS() \
|
||||||
|
{ \
|
||||||
|
Asm("":::"memory"); \
|
||||||
|
Asm("seti"); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
extern volatile unsigned int ulCriticalNesting;
|
||||||
|
|
||||||
|
#define portENTER_CRITICAL() \
|
||||||
|
{ \
|
||||||
|
portDISABLE_INTERRUPTS() \
|
||||||
|
ulCriticalNesting++; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define portEXIT_CRITICAL() \
|
||||||
|
{ \
|
||||||
|
if (ulCriticalNesting > portNO_CRITICAL_NESTING) \
|
||||||
|
{ \
|
||||||
|
ulCriticalNesting--; \
|
||||||
|
if (ulCriticalNesting == portNO_CRITICAL_NESTING) \
|
||||||
|
{ \
|
||||||
|
portENABLE_INTERRUPTS() \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
|
||||||
|
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() do {} while (0) /* we use the timer */
|
||||||
|
#define portALT_GET_RUN_TIME_COUNTER_VALUE(dest) (dest = xTickCount)
|
||||||
|
|
||||||
|
#if defined(__MW__)
|
||||||
|
extern void task_end_hook(void *pxTCB);
|
||||||
|
#define portCLEAN_UP_TCB( pxTCB ) task_end_hook((void *)pxTCB)
|
||||||
|
#else
|
||||||
|
#define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void vPortYield(void);
|
||||||
|
void vPortYieldFromIsr(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
601
portable/ThirdParty/GCC/Posix/port.c
vendored
Normal file
601
portable/ThirdParty/GCC/Posix/port.c
vendored
Normal file
|
@ -0,0 +1,601 @@
|
||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.3.0
|
||||||
|
* Copyright (C) 2020 Cambridge Consultants Ltd.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* http://www.FreeRTOS.org
|
||||||
|
* http://aws.amazon.com/freertos
|
||||||
|
*
|
||||||
|
* 1 tab == 4 spaces!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Implementation of functions defined in portable.h for the Posix port.
|
||||||
|
*
|
||||||
|
* Each task has a pthread which eases use of standard debuggers
|
||||||
|
* (allowing backtraces of tasks etc). Threads for tasks that are not
|
||||||
|
* running are blocked in sigwait().
|
||||||
|
*
|
||||||
|
* Task switch is done by resuming the thread for the next task by
|
||||||
|
* sending it the resume signal (SIGUSR1) and then suspending the
|
||||||
|
* current thread.
|
||||||
|
*
|
||||||
|
* The timer interrupt uses SIGALRM and care is taken to ensure that
|
||||||
|
* the signal handler runs only on the thread for the current task.
|
||||||
|
*
|
||||||
|
* Use of part of the standard C library requires care as some
|
||||||
|
* functions can take pthread mutexes internally which can result in
|
||||||
|
* deadlocks as the FreeRTOS kernel can switch tasks while they're
|
||||||
|
* holding a pthread mutex.
|
||||||
|
*
|
||||||
|
* Replacement malloc(), free(), calloc(), and realloc() are provided
|
||||||
|
* for glibc (see below for more information).
|
||||||
|
*
|
||||||
|
* stdio (printf() and friends) should be called from a single task
|
||||||
|
* only or serialized with a FreeRTOS primitive such as a binary
|
||||||
|
* semaphore or mutex.
|
||||||
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/times.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
/* Scheduler includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define SIG_RESUME SIGUSR1
|
||||||
|
|
||||||
|
typedef struct THREAD
|
||||||
|
{
|
||||||
|
pthread_t pthread;
|
||||||
|
pdTASK_CODE pxCode;
|
||||||
|
void *pvParams;
|
||||||
|
BaseType_t xDying;
|
||||||
|
} Thread_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The additional per-thread data is stored at the beginning of the
|
||||||
|
* task's stack.
|
||||||
|
*/
|
||||||
|
static inline Thread_t *prvGetThreadFromTask(TaskHandle_t xTask)
|
||||||
|
{
|
||||||
|
StackType_t *pxTopOfStack = *(StackType_t **)xTask;
|
||||||
|
|
||||||
|
return (Thread_t *)(pxTopOfStack + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static pthread_once_t hSigSetupThread = PTHREAD_ONCE_INIT;
|
||||||
|
static sigset_t xResumeSignals;
|
||||||
|
static sigset_t xAllSignals;
|
||||||
|
static sigset_t xSchedulerOriginalSignalMask;
|
||||||
|
static pthread_t hMainThread = ( pthread_t )NULL;
|
||||||
|
static volatile portBASE_TYPE uxCriticalNesting;
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static portBASE_TYPE xSchedulerEnd = pdFALSE;
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvSetupSignalsAndSchedulerPolicy( void );
|
||||||
|
static void prvSetupTimerInterrupt( void );
|
||||||
|
static void *prvWaitForStart( void * pvParams );
|
||||||
|
static void prvSwitchThread( Thread_t *xThreadToResume, Thread_t *xThreadToSuspend );
|
||||||
|
static void prvSuspendSelf( void );
|
||||||
|
static void prvResumeThread( pthread_t xThreadId );
|
||||||
|
static void vPortSystemTickHandler( int sig );
|
||||||
|
static void vPortStartFirstTask( void );
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The standard glibc malloc(), free() etc. take an internal lock so
|
||||||
|
* it is not safe to switch tasks while calling them.
|
||||||
|
*
|
||||||
|
* Requiring the application use the safe xPortMalloc() and
|
||||||
|
* vPortFree() is not sufficient as malloc() is used internally by
|
||||||
|
* glibc (e.g., by strdup() and the pthread library.)
|
||||||
|
*
|
||||||
|
* To further complicate things malloc() and free() may be called
|
||||||
|
* outside of task context during pthread destruction so using
|
||||||
|
* vTaskSuspend() and xTaskResumeAll() cannot be used.
|
||||||
|
* vPortEnterCritical() and vPortExitCritical() cannot be used either
|
||||||
|
* as they use global state for the critical section nesting (this
|
||||||
|
* cannot be fixed by using TLS as pthread destruction needs to free
|
||||||
|
* the TLS).
|
||||||
|
*
|
||||||
|
* Explicitly save/disable and restore the signal mask to block the
|
||||||
|
* timer (SIGALRM) and other signals.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern void *__libc_malloc(size_t);
|
||||||
|
extern void __libc_free(void *);
|
||||||
|
extern void *__libc_calloc(size_t, size_t);
|
||||||
|
extern void *__libc_realloc(void *ptr, size_t);
|
||||||
|
|
||||||
|
void *malloc(size_t size)
|
||||||
|
{
|
||||||
|
sigset_t xSavedSignals;
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
pthread_sigmask( SIG_BLOCK, &xAllSignals, &xSavedSignals );
|
||||||
|
ptr = __libc_malloc( size );
|
||||||
|
pthread_sigmask( SIG_SETMASK, &xSavedSignals, NULL );
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(void *ptr)
|
||||||
|
{
|
||||||
|
sigset_t xSavedSignals;
|
||||||
|
|
||||||
|
pthread_sigmask( SIG_BLOCK, &xAllSignals, &xSavedSignals );
|
||||||
|
__libc_free( ptr );
|
||||||
|
pthread_sigmask( SIG_SETMASK, &xSavedSignals, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
void *calloc(size_t nmemb, size_t size)
|
||||||
|
{
|
||||||
|
sigset_t xSavedSignals;
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
pthread_sigmask( SIG_BLOCK, &xAllSignals, &xSavedSignals );
|
||||||
|
ptr = __libc_calloc( nmemb, size );
|
||||||
|
pthread_sigmask( SIG_SETMASK, &xSavedSignals, NULL );
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *realloc(void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
sigset_t xSavedSignals;
|
||||||
|
|
||||||
|
pthread_sigmask( SIG_BLOCK, &xAllSignals, &xSavedSignals );
|
||||||
|
ptr = __libc_realloc( ptr, size );
|
||||||
|
pthread_sigmask( SIG_SETMASK, &xSavedSignals, NULL );
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void prvFatalError( const char *pcCall, int iErrno )
|
||||||
|
{
|
||||||
|
fprintf( stderr, "%s: %s\n", pcCall, strerror( iErrno ) );
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack,
|
||||||
|
portSTACK_TYPE *pxEndOfStack,
|
||||||
|
pdTASK_CODE pxCode, void *pvParameters )
|
||||||
|
{
|
||||||
|
Thread_t *thread;
|
||||||
|
pthread_attr_t xThreadAttributes;
|
||||||
|
size_t ulStackSize;
|
||||||
|
int iRet;
|
||||||
|
|
||||||
|
(void)pthread_once( &hSigSetupThread, prvSetupSignalsAndSchedulerPolicy );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Store the additional thread data at the start of the stack.
|
||||||
|
*/
|
||||||
|
thread = (Thread_t *)(pxTopOfStack + 1) - 1;
|
||||||
|
pxTopOfStack = (portSTACK_TYPE *)thread - 1;
|
||||||
|
ulStackSize = (pxTopOfStack + 1 - pxEndOfStack) * sizeof(*pxTopOfStack);
|
||||||
|
|
||||||
|
thread->pxCode = pxCode;
|
||||||
|
thread->pvParams = pvParameters;
|
||||||
|
thread->xDying = pdFALSE;
|
||||||
|
|
||||||
|
pthread_attr_init( &xThreadAttributes );
|
||||||
|
pthread_attr_setstack( &xThreadAttributes, pxEndOfStack, ulStackSize );
|
||||||
|
|
||||||
|
vPortEnterCritical();
|
||||||
|
|
||||||
|
iRet = pthread_create( &thread->pthread, &xThreadAttributes,
|
||||||
|
prvWaitForStart, thread );
|
||||||
|
if ( iRet )
|
||||||
|
{
|
||||||
|
prvFatalError( "pthread_create", iRet );
|
||||||
|
}
|
||||||
|
|
||||||
|
vPortExitCritical();
|
||||||
|
|
||||||
|
return pxTopOfStack;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortStartFirstTask( void )
|
||||||
|
{
|
||||||
|
Thread_t *pxFirstThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
|
||||||
|
|
||||||
|
/* Start the first task. */
|
||||||
|
prvResumeThread( pxFirstThread->pthread );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See header file for description.
|
||||||
|
*/
|
||||||
|
portBASE_TYPE xPortStartScheduler( void )
|
||||||
|
{
|
||||||
|
int iSignal;
|
||||||
|
sigset_t xSignals;
|
||||||
|
|
||||||
|
hMainThread = pthread_self();
|
||||||
|
|
||||||
|
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||||
|
here already. */
|
||||||
|
prvSetupTimerInterrupt();
|
||||||
|
|
||||||
|
/* Start the first task. */
|
||||||
|
vPortStartFirstTask();
|
||||||
|
|
||||||
|
/* Wait until signaled by vPortEndScheduler(). */
|
||||||
|
sigemptyset( &xSignals );
|
||||||
|
sigaddset( &xSignals, SIG_RESUME );
|
||||||
|
|
||||||
|
while ( !xSchedulerEnd )
|
||||||
|
{
|
||||||
|
sigwait( &xSignals, &iSignal );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore original signal mask. */
|
||||||
|
(void)pthread_sigmask( SIG_SETMASK, &xSchedulerOriginalSignalMask, NULL );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortEndScheduler( void )
|
||||||
|
{
|
||||||
|
struct itimerval itimer;
|
||||||
|
struct sigaction sigtick;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
(void)setitimer( ITIMER_REAL, &itimer, NULL );
|
||||||
|
|
||||||
|
sigtick.sa_flags = 0;
|
||||||
|
sigtick.sa_handler = SIG_IGN;
|
||||||
|
sigaction( SIGALRM, &sigtick, NULL );
|
||||||
|
|
||||||
|
/* Signal the scheduler to exit its loop. */
|
||||||
|
xSchedulerEnd = pdTRUE;
|
||||||
|
(void)pthread_kill( hMainThread, SIG_RESUME );
|
||||||
|
|
||||||
|
prvSuspendSelf();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortEnterCritical( void )
|
||||||
|
{
|
||||||
|
if ( uxCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
vPortDisableInterrupts();
|
||||||
|
}
|
||||||
|
uxCriticalNesting++;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortExitCritical( void )
|
||||||
|
{
|
||||||
|
uxCriticalNesting--;
|
||||||
|
|
||||||
|
/* If we have reached 0 then re-enable the interrupts. */
|
||||||
|
if( uxCriticalNesting == 0 )
|
||||||
|
{
|
||||||
|
vPortEnableInterrupts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortYieldFromISR( void )
|
||||||
|
{
|
||||||
|
Thread_t *xThreadToSuspend;
|
||||||
|
Thread_t *xThreadToResume;
|
||||||
|
|
||||||
|
xThreadToSuspend = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
|
||||||
|
|
||||||
|
vTaskSwitchContext();
|
||||||
|
|
||||||
|
xThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
|
||||||
|
|
||||||
|
prvSwitchThread( xThreadToResume, xThreadToSuspend );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortYield( void )
|
||||||
|
{
|
||||||
|
vPortEnterCritical();
|
||||||
|
|
||||||
|
vPortYieldFromISR();
|
||||||
|
|
||||||
|
vPortExitCritical();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortDisableInterrupts( void )
|
||||||
|
{
|
||||||
|
pthread_sigmask( SIG_BLOCK, &xAllSignals, NULL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortEnableInterrupts( void )
|
||||||
|
{
|
||||||
|
pthread_sigmask( SIG_UNBLOCK, &xAllSignals, NULL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
portBASE_TYPE xPortSetInterruptMask( void )
|
||||||
|
{
|
||||||
|
/* Interrupts are always disabled inside ISRs (signals
|
||||||
|
handlers). */
|
||||||
|
return pdTRUE;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortClearInterruptMask( portBASE_TYPE xMask )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static uint64_t prvGetTimeNs(void)
|
||||||
|
{
|
||||||
|
struct timespec t;
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &t);
|
||||||
|
|
||||||
|
return t.tv_sec * 1000000000ull + t.tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t prvStartTimeNs;
|
||||||
|
static uint64_t prvTickCount;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the systick timer to generate the tick interrupts at the required
|
||||||
|
* frequency.
|
||||||
|
*/
|
||||||
|
void prvSetupTimerInterrupt( void )
|
||||||
|
{
|
||||||
|
struct itimerval itimer;
|
||||||
|
int iRet;
|
||||||
|
|
||||||
|
/* Initialise the structure with the current timer information. */
|
||||||
|
iRet = getitimer( ITIMER_REAL, &itimer );
|
||||||
|
if ( iRet )
|
||||||
|
{
|
||||||
|
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 )
|
||||||
|
{
|
||||||
|
prvFatalError( "setitimer", errno );
|
||||||
|
}
|
||||||
|
|
||||||
|
prvStartTimeNs = prvGetTimeNs();
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vPortSystemTickHandler( int sig )
|
||||||
|
{
|
||||||
|
Thread_t *pxThreadToSuspend;
|
||||||
|
Thread_t *pxThreadToResume;
|
||||||
|
uint64_t xExpectedTicks;
|
||||||
|
|
||||||
|
uxCriticalNesting++; /* Signals are blocked in this signal handler. */
|
||||||
|
|
||||||
|
pxThreadToSuspend = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
|
||||||
|
|
||||||
|
/* Tick Increment, accounting for any lost signals or drift in
|
||||||
|
* the timer. */
|
||||||
|
xExpectedTicks = (prvGetTimeNs() - prvStartTimeNs)
|
||||||
|
/ (portTICK_RATE_MICROSECONDS * 1000);
|
||||||
|
do {
|
||||||
|
xTaskIncrementTick();
|
||||||
|
prvTickCount++;
|
||||||
|
} while (prvTickCount < xExpectedTicks);
|
||||||
|
|
||||||
|
#if ( configUSE_PREEMPTION == 1 )
|
||||||
|
/* Select Next Task. */
|
||||||
|
vTaskSwitchContext();
|
||||||
|
|
||||||
|
pxThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
|
||||||
|
|
||||||
|
prvSwitchThread(pxThreadToResume, pxThreadToSuspend);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uxCriticalNesting--;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
void vPortThreadDying( void *pxTaskToDelete, volatile BaseType_t *pxPendYield )
|
||||||
|
{
|
||||||
|
Thread_t *pxThread = prvGetThreadFromTask( pxTaskToDelete );
|
||||||
|
|
||||||
|
pxThread->xDying = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vPortCancelThread( void *pxTaskToDelete )
|
||||||
|
{
|
||||||
|
Thread_t *pxThreadToCancel = prvGetThreadFromTask( pxTaskToDelete );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The thread has already been suspended so it can be safely
|
||||||
|
* cancelled.
|
||||||
|
*/
|
||||||
|
pthread_cancel( pxThreadToCancel->pthread );
|
||||||
|
pthread_join( pxThreadToCancel->pthread, NULL );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void *prvWaitForStart( void * pvParams )
|
||||||
|
{
|
||||||
|
Thread_t *pxThread = pvParams;
|
||||||
|
|
||||||
|
prvSuspendSelf();
|
||||||
|
|
||||||
|
/* Resumed for the first time, unblocks all signals. */
|
||||||
|
uxCriticalNesting = 0;
|
||||||
|
vPortEnableInterrupts();
|
||||||
|
|
||||||
|
/* Call the task's entry point. */
|
||||||
|
pxThread->pxCode( pxThread->pvParams );
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvSwitchThread( Thread_t *pxThreadToResume,
|
||||||
|
Thread_t *pxThreadToSuspend )
|
||||||
|
{
|
||||||
|
BaseType_t uxSavedCriticalNesting;
|
||||||
|
|
||||||
|
if ( pxThreadToSuspend != pxThreadToResume )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Switch tasks.
|
||||||
|
*
|
||||||
|
* The critical section nesting is per-task, so save it on the
|
||||||
|
* stack of the current (suspending thread), restoring it when
|
||||||
|
* we switch back to this task.
|
||||||
|
*/
|
||||||
|
uxSavedCriticalNesting = uxCriticalNesting;
|
||||||
|
|
||||||
|
prvResumeThread( pxThreadToResume->pthread );
|
||||||
|
if ( pxThreadToSuspend->xDying )
|
||||||
|
{
|
||||||
|
pthread_exit( NULL );
|
||||||
|
}
|
||||||
|
prvSuspendSelf();
|
||||||
|
|
||||||
|
uxCriticalNesting = uxSavedCriticalNesting;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvSuspendSelf( void )
|
||||||
|
{
|
||||||
|
int iSig;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Suspend this thread by waiting for a SIG_RESUME signal.
|
||||||
|
*
|
||||||
|
* A suspended thread must not handle signals (interrupts) so
|
||||||
|
* all signals must be blocked by calling this from:
|
||||||
|
*
|
||||||
|
* - Inside a critical section (vPortEnterCritical() /
|
||||||
|
* vPortExitCritical()).
|
||||||
|
*
|
||||||
|
* - From a signal handler that has all signals masked.
|
||||||
|
*
|
||||||
|
* - A thread with all signals blocked with pthread_sigmask().
|
||||||
|
*/
|
||||||
|
sigwait( &xResumeSignals, &iSig );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvResumeThread( pthread_t xThreadId )
|
||||||
|
{
|
||||||
|
if ( pthread_self() != xThreadId )
|
||||||
|
{
|
||||||
|
pthread_kill( xThreadId, SIG_RESUME );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvSetupSignalsAndSchedulerPolicy( void )
|
||||||
|
{
|
||||||
|
struct sigaction sigresume, sigtick;
|
||||||
|
int iRet;
|
||||||
|
|
||||||
|
hMainThread = pthread_self();
|
||||||
|
|
||||||
|
/* Initialise common signal masks. */
|
||||||
|
sigemptyset( &xResumeSignals );
|
||||||
|
sigaddset( &xResumeSignals, SIG_RESUME );
|
||||||
|
sigfillset( &xAllSignals );
|
||||||
|
/* Don't block SIGINT so this can be used to break into GDB while
|
||||||
|
* in a critical section. */
|
||||||
|
sigdelset( &xAllSignals, SIGINT );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Block all signals in this thread so all new threads
|
||||||
|
* inherits this mask.
|
||||||
|
*
|
||||||
|
* When a thread is resumed for the first time, all signals
|
||||||
|
* will be unblocked.
|
||||||
|
*/
|
||||||
|
(void)pthread_sigmask( SIG_SETMASK, &xAllSignals,
|
||||||
|
&xSchedulerOriginalSignalMask );
|
||||||
|
|
||||||
|
/* SIG_RESUME is only used with sigwait() so doesn't need a
|
||||||
|
handler. */
|
||||||
|
sigresume.sa_flags = 0;
|
||||||
|
sigresume.sa_handler = SIG_IGN;
|
||||||
|
sigfillset( &sigresume.sa_mask );
|
||||||
|
|
||||||
|
sigtick.sa_flags = 0;
|
||||||
|
sigtick.sa_handler = vPortSystemTickHandler;
|
||||||
|
sigfillset( &sigtick.sa_mask );
|
||||||
|
|
||||||
|
iRet = sigaction( SIG_RESUME, &sigresume, NULL );
|
||||||
|
if ( iRet )
|
||||||
|
{
|
||||||
|
prvFatalError( "sigaction", errno );
|
||||||
|
}
|
||||||
|
|
||||||
|
iRet = sigaction( SIGALRM, &sigtick, NULL );
|
||||||
|
if ( iRet )
|
||||||
|
{
|
||||||
|
prvFatalError( "sigaction", errno );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
unsigned long ulPortGetRunTime( void )
|
||||||
|
{
|
||||||
|
struct tms xTimes;
|
||||||
|
|
||||||
|
times( &xTimes );
|
||||||
|
|
||||||
|
return ( unsigned long ) xTimes.tms_utime;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
134
portable/ThirdParty/GCC/Posix/portmacro.h
vendored
Normal file
134
portable/ThirdParty/GCC/Posix/portmacro.h
vendored
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
* FreeRTOS Kernel V10.3.0
|
||||||
|
* Copyright 2020 Cambridge Consultants Ltd.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* http://www.FreeRTOS.org
|
||||||
|
* http://aws.amazon.com/freertos
|
||||||
|
*
|
||||||
|
* 1 tab == 4 spaces!
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the
|
||||||
|
* given hardware and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*-----------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Type definitions. */
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT float
|
||||||
|
#define portDOUBLE double
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT short
|
||||||
|
#define portSTACK_TYPE unsigned long
|
||||||
|
#define portBASE_TYPE long
|
||||||
|
#define portPOINTER_SIZE_TYPE intptr_t
|
||||||
|
|
||||||
|
typedef portSTACK_TYPE StackType_t;
|
||||||
|
typedef long BaseType_t;
|
||||||
|
typedef unsigned long UBaseType_t;
|
||||||
|
|
||||||
|
typedef unsigned long TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) ULONG_MAX
|
||||||
|
|
||||||
|
#define portTICK_TYPE_IS_ATOMIC 1
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Architecture specifics. */
|
||||||
|
#define portSTACK_GROWTH ( -1 )
|
||||||
|
#define portHAS_STACK_OVERFLOW_CHECKING ( 1 )
|
||||||
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
|
#define portTICK_RATE_MICROSECONDS ( ( portTickType ) 1000000 / configTICK_RATE_HZ )
|
||||||
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Scheduler utilities. */
|
||||||
|
extern void vPortYield( void );
|
||||||
|
|
||||||
|
#define portYIELD() vPortYield()
|
||||||
|
|
||||||
|
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) vPortYield()
|
||||||
|
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Critical section management. */
|
||||||
|
extern void vPortDisableInterrupts( void );
|
||||||
|
extern void vPortEnableInterrupts( void );
|
||||||
|
#define portSET_INTERRUPT_MASK() ( vPortDisableInterrupts() )
|
||||||
|
#define portCLEAR_INTERRUPT_MASK() ( vPortEnableInterrupts() )
|
||||||
|
|
||||||
|
extern portBASE_TYPE xPortSetInterruptMask( void );
|
||||||
|
extern void vPortClearInterruptMask( portBASE_TYPE xMask );
|
||||||
|
|
||||||
|
extern void vPortEnterCritical( void );
|
||||||
|
extern void vPortExitCritical( void );
|
||||||
|
#define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMask()
|
||||||
|
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
|
||||||
|
#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK()
|
||||||
|
#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK()
|
||||||
|
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||||
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
extern void vPortThreadDying( void *pxTaskToDelete, volatile BaseType_t *pxPendYield );
|
||||||
|
extern void vPortCancelThread( void *pxTaskToDelete );
|
||||||
|
#define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxPendYield ) vPortThreadDying( ( pvTaskToDelete ), ( pxPendYield ) )
|
||||||
|
#define portCLEAN_UP_TCB( pxTCB ) vPortCancelThread( pxTCB )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tasks run in their own pthreads and context switches between them
|
||||||
|
* are always a full memory barrier. ISRs are emulated as signals
|
||||||
|
* which also imply a full memory barrier.
|
||||||
|
*
|
||||||
|
* Thus, only a compilier barrier is needed to prevent the compiler
|
||||||
|
* reordering.
|
||||||
|
*/
|
||||||
|
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||||
|
|
||||||
|
extern unsigned long ulPortGetRunTime( void );
|
||||||
|
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() /* no-op */
|
||||||
|
#define portGET_RUN_TIME_COUNTER_VALUE() ulPortGetRunTime()
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
9
tasks.c
9
tasks.c
|
@ -3948,8 +3948,6 @@ static void prvCheckTasksWaitingTermination( void )
|
||||||
|
|
||||||
static void prvResetNextTaskUnblockTime( void )
|
static void prvResetNextTaskUnblockTime( void )
|
||||||
{
|
{
|
||||||
TCB_t *pxTCB;
|
|
||||||
|
|
||||||
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
|
if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )
|
||||||
{
|
{
|
||||||
/* The new current delayed list is empty. Set xNextTaskUnblockTime to
|
/* The new current delayed list is empty. Set xNextTaskUnblockTime to
|
||||||
|
@ -3964,8 +3962,7 @@ TCB_t *pxTCB;
|
||||||
the item at the head of the delayed list. This is the time at
|
the item at the head of the delayed list. This is the time at
|
||||||
which the task at the head of the delayed list should be removed
|
which the task at the head of the delayed list should be removed
|
||||||
from the Blocked state. */
|
from the Blocked state. */
|
||||||
( pxTCB ) = listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
|
xNextTaskUnblockTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxDelayedTaskList );
|
||||||
xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xStateListItem ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
@ -4133,10 +4130,10 @@ TCB_t *pxTCB;
|
||||||
the mutex. If the mutex is held by a task then it cannot be
|
the mutex. If the mutex is held by a task then it cannot be
|
||||||
given from an interrupt, and if a mutex is given by the
|
given from an interrupt, and if a mutex is given by the
|
||||||
holding task then it must be the running state task. Remove
|
holding task then it must be the running state task. Remove
|
||||||
the holding task from the ready/delayed list. */
|
the holding task from the ready list. */
|
||||||
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
||||||
{
|
{
|
||||||
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
|
portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue