mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-09-12 00:57:44 -04:00
Synced portable section.
This commit is contained in:
parent
7ceed10420
commit
0b9e3b2c5f
514 changed files with 172645 additions and 170941 deletions
|
@ -242,10 +242,10 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* configPRECONDITION should be resolve to configASSERT.
|
/* configPRECONDITION should be resolve to configASSERT.
|
||||||
The CBMC proofs need a way to track assumptions and assertions.
|
The CBMC proofs need a way to track assumptions and assertions.
|
||||||
A configPRECONDITION statement should express an implicit invariant or assumption made.
|
A configPRECONDITION statement should express an implicit invariant or
|
||||||
A configASSERT statement should express an invariant that must hold explicit before calling
|
assumption made. A configASSERT statement should express an invariant that must
|
||||||
the code. */
|
hold explicit before calling the code. */
|
||||||
#ifndef configPRECONDITION
|
#ifndef configPRECONDITION
|
||||||
#define configPRECONDITION( X ) configASSERT(X)
|
#define configPRECONDITION( X ) configASSERT(X)
|
||||||
#define configPRECONDITION_DEFINED 0
|
#define configPRECONDITION_DEFINED 0
|
||||||
|
@ -257,6 +257,10 @@ extern "C" {
|
||||||
#define portMEMORY_BARRIER()
|
#define portMEMORY_BARRIER()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef portSOFTWARE_BARRIER
|
||||||
|
#define portSOFTWARE_BARRIER()
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The timers module relies on xTaskGetSchedulerState(). */
|
/* The timers module relies on xTaskGetSchedulerState(). */
|
||||||
#if configUSE_TIMERS == 1
|
#if configUSE_TIMERS == 1
|
||||||
|
|
||||||
|
|
258
include/atomic.h
258
include/atomic.h
|
@ -29,9 +29,9 @@
|
||||||
* @file atomic.h
|
* @file atomic.h
|
||||||
* @brief FreeRTOS atomic operation support.
|
* @brief FreeRTOS atomic operation support.
|
||||||
*
|
*
|
||||||
* This file implements atomic by disabling interrupts globally.
|
* This file implements atomic functions by disabling interrupts globally.
|
||||||
* Implementation with architecture specific atomic instructions
|
* Implementations with architecture specific atomic instructions can be
|
||||||
* are to be provided under each compiler directory.
|
* provided under each compiler directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ATOMIC_H
|
#ifndef ATOMIC_H
|
||||||
|
@ -48,12 +48,14 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Port specific definitions -- entering/exiting critical section.
|
/*
|
||||||
|
* Port specific definitions -- entering/exiting critical section.
|
||||||
* Refer template -- ./lib/FreeRTOS/portable/Compiler/Arch/portmacro.h
|
* Refer template -- ./lib/FreeRTOS/portable/Compiler/Arch/portmacro.h
|
||||||
*
|
*
|
||||||
* Every call to ATOMIC_EXIT_CRITICAL() must be closely paired with
|
* Every call to ATOMIC_EXIT_CRITICAL() must be closely paired with
|
||||||
* ATOMIC_ENTER_CRITICAL().
|
* ATOMIC_ENTER_CRITICAL().
|
||||||
* */
|
*
|
||||||
|
*/
|
||||||
#if defined( portSET_INTERRUPT_MASK_FROM_ISR )
|
#if defined( portSET_INTERRUPT_MASK_FROM_ISR )
|
||||||
|
|
||||||
/* Nested interrupt scheme is supported in this port. */
|
/* Nested interrupt scheme is supported in this port. */
|
||||||
|
@ -71,11 +73,12 @@ extern "C" {
|
||||||
|
|
||||||
#endif /* portSET_INTERRUPT_MASK_FROM_ISR() */
|
#endif /* portSET_INTERRUPT_MASK_FROM_ISR() */
|
||||||
|
|
||||||
/* Port specific definition -- "always inline".
|
/*
|
||||||
* Inline is compiler specific, and may not always get inlined depending on your optimization level.
|
* Port specific definition -- "always inline".
|
||||||
* Also, inline is considerred as performance optimization for atomic.
|
* Inline is compiler specific, and may not always get inlined depending on your
|
||||||
* Thus, if portFORCE_INLINE is not provided by portmacro.h, instead of resulting error,
|
* optimization level. Also, inline is considered as performance optimization
|
||||||
* simply define it.
|
* for atomic. Thus, if portFORCE_INLINE is not provided by portmacro.h,
|
||||||
|
* instead of resulting error, simply define it away.
|
||||||
*/
|
*/
|
||||||
#ifndef portFORCE_INLINE
|
#ifndef portFORCE_INLINE
|
||||||
#define portFORCE_INLINE
|
#define portFORCE_INLINE
|
||||||
|
@ -91,66 +94,67 @@ extern "C" {
|
||||||
*
|
*
|
||||||
* @brief Performs an atomic compare-and-swap operation on the specified values.
|
* @brief Performs an atomic compare-and-swap operation on the specified values.
|
||||||
*
|
*
|
||||||
* @param[in, out] pDestination Pointer to memory location from where value is
|
* @param[in, out] pulDestination Pointer to memory location from where value is
|
||||||
* to be loaded and checked.
|
* to be loaded and checked.
|
||||||
* @param[in] ulExchange If condition meets, write this value to memory.
|
* @param[in] ulExchange If condition meets, write this value to memory.
|
||||||
* @param[in] ulComparand Swap condition.
|
* @param[in] ulComparand Swap condition.
|
||||||
*
|
*
|
||||||
* @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.
|
* @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.
|
||||||
*
|
*
|
||||||
* @note This function only swaps *pDestination with ulExchange, if previous
|
* @note This function only swaps *pulDestination with ulExchange, if previous
|
||||||
* *pDestination value equals ulComparand.
|
* *pulDestination value equals ulComparand.
|
||||||
*/
|
*/
|
||||||
static portFORCE_INLINE uint32_t Atomic_CompareAndSwap_u32(
|
static portFORCE_INLINE uint32_t Atomic_CompareAndSwap_u32( uint32_t volatile * pulDestination,
|
||||||
uint32_t volatile * pDestination,
|
|
||||||
uint32_t ulExchange,
|
uint32_t ulExchange,
|
||||||
uint32_t ulComparand )
|
uint32_t ulComparand )
|
||||||
{
|
{
|
||||||
|
uint32_t ulReturnValue;
|
||||||
uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
|
|
||||||
|
|
||||||
ATOMIC_ENTER_CRITICAL();
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
|
||||||
if ( *pDestination == ulComparand )
|
|
||||||
{
|
{
|
||||||
*pDestination = ulExchange;
|
if( *pulDestination == ulComparand )
|
||||||
|
{
|
||||||
|
*pulDestination = ulExchange;
|
||||||
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;
|
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
ATOMIC_EXIT_CRITICAL();
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
return ulReturnValue;
|
return ulReturnValue;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic swap (pointers)
|
* Atomic swap (pointers)
|
||||||
*
|
*
|
||||||
* @brief Atomically sets the address pointed to by *ppDestination to the value
|
* @brief Atomically sets the address pointed to by *ppvDestination to the value
|
||||||
* of *pExchange.
|
* of *pvExchange.
|
||||||
*
|
*
|
||||||
* @param[in, out] ppDestination Pointer to memory location from where a pointer
|
* @param[in, out] ppvDestination Pointer to memory location from where a pointer
|
||||||
* value is to be loaded and written back to.
|
* value is to be loaded and written back to.
|
||||||
* @param[in] pExchange Pointer value to be written to *ppDestination.
|
* @param[in] pvExchange Pointer value to be written to *ppvDestination.
|
||||||
*
|
*
|
||||||
* @return The initial value of *ppDestination.
|
* @return The initial value of *ppvDestination.
|
||||||
*/
|
*/
|
||||||
static portFORCE_INLINE void * Atomic_SwapPointers_p32(
|
static portFORCE_INLINE void * Atomic_SwapPointers_p32( void * volatile * ppvDestination,
|
||||||
void * volatile * ppDestination,
|
void * pvExchange )
|
||||||
void * pExchange )
|
|
||||||
{
|
{
|
||||||
void * pReturnValue;
|
void * pReturnValue;
|
||||||
|
|
||||||
ATOMIC_ENTER_CRITICAL();
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
pReturnValue = *ppDestination;
|
pReturnValue = *ppvDestination;
|
||||||
|
*ppvDestination = pvExchange;
|
||||||
*ppDestination = pExchange;
|
}
|
||||||
|
|
||||||
ATOMIC_EXIT_CRITICAL();
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
return pReturnValue;
|
return pReturnValue;
|
||||||
}
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic compare-and-swap (pointers)
|
* Atomic compare-and-swap (pointers)
|
||||||
|
@ -158,30 +162,30 @@ static portFORCE_INLINE void * Atomic_SwapPointers_p32(
|
||||||
* @brief Performs an atomic compare-and-swap operation on the specified pointer
|
* @brief Performs an atomic compare-and-swap operation on the specified pointer
|
||||||
* values.
|
* values.
|
||||||
*
|
*
|
||||||
* @param[in, out] ppDestination Pointer to memory location from where a pointer
|
* @param[in, out] ppvDestination Pointer to memory location from where a pointer
|
||||||
* value is to be loaded and checked.
|
* value is to be loaded and checked.
|
||||||
* @param[in] pExchange If condition meets, write this value to memory.
|
* @param[in] pvExchange If condition meets, write this value to memory.
|
||||||
* @param[in] pComparand Swap condition.
|
* @param[in] pvComparand Swap condition.
|
||||||
*
|
*
|
||||||
* @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.
|
* @return Unsigned integer of value 1 or 0. 1 for swapped, 0 for not swapped.
|
||||||
*
|
*
|
||||||
* @note This function only swaps *ppDestination with pExchange, if previous
|
* @note This function only swaps *ppvDestination with pvExchange, if previous
|
||||||
* *ppDestination value equals pComparand.
|
* *ppvDestination value equals pvComparand.
|
||||||
*/
|
*/
|
||||||
static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32(
|
static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32( void * volatile * ppvDestination,
|
||||||
void * volatile * ppDestination,
|
void * pvExchange,
|
||||||
void * pExchange, void * pComparand )
|
void * pvComparand )
|
||||||
{
|
{
|
||||||
uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
|
uint32_t ulReturnValue = ATOMIC_COMPARE_AND_SWAP_FAILURE;
|
||||||
|
|
||||||
ATOMIC_ENTER_CRITICAL();
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
|
||||||
if ( *ppDestination == pComparand )
|
|
||||||
{
|
{
|
||||||
*ppDestination = pExchange;
|
if( *ppvDestination == pvComparand )
|
||||||
|
{
|
||||||
|
*ppvDestination = pvExchange;
|
||||||
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;
|
ulReturnValue = ATOMIC_COMPARE_AND_SWAP_SUCCESS;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ATOMIC_EXIT_CRITICAL();
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
return ulReturnValue;
|
return ulReturnValue;
|
||||||
|
@ -195,28 +199,27 @@ static portFORCE_INLINE uint32_t Atomic_CompareAndSwapPointers_p32(
|
||||||
*
|
*
|
||||||
* @brief Atomically adds count to the value of the specified pointer points to.
|
* @brief Atomically adds count to the value of the specified pointer points to.
|
||||||
*
|
*
|
||||||
* @param[in,out] pAddend Pointer to memory location from where value is to be
|
* @param[in,out] pulAddend Pointer to memory location from where value is to be
|
||||||
* loaded and written back to.
|
* loaded and written back to.
|
||||||
* @param[in] ulCount Value to be added to *pAddend.
|
* @param[in] ulCount Value to be added to *pulAddend.
|
||||||
*
|
*
|
||||||
* @return previous *pAddend value.
|
* @return previous *pulAddend value.
|
||||||
*/
|
*/
|
||||||
static portFORCE_INLINE uint32_t Atomic_Add_u32(
|
static portFORCE_INLINE uint32_t Atomic_Add_u32( uint32_t volatile * pulAddend,
|
||||||
uint32_t volatile * pAddend,
|
|
||||||
uint32_t ulCount )
|
uint32_t ulCount )
|
||||||
{
|
{
|
||||||
uint32_t ulCurrent;
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
ATOMIC_ENTER_CRITICAL();
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
ulCurrent = *pAddend;
|
ulCurrent = *pulAddend;
|
||||||
|
*pulAddend += ulCount;
|
||||||
*pAddend += ulCount;
|
}
|
||||||
|
|
||||||
ATOMIC_EXIT_CRITICAL();
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
return ulCurrent;
|
return ulCurrent;
|
||||||
}
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic subtract
|
* Atomic subtract
|
||||||
|
@ -224,74 +227,72 @@ static portFORCE_INLINE uint32_t Atomic_Add_u32(
|
||||||
* @brief Atomically subtracts count from the value of the specified pointer
|
* @brief Atomically subtracts count from the value of the specified pointer
|
||||||
* pointers to.
|
* pointers to.
|
||||||
*
|
*
|
||||||
* @param[in,out] pAddend Pointer to memory location from where value is to be
|
* @param[in,out] pulAddend Pointer to memory location from where value is to be
|
||||||
* loaded and written back to.
|
* loaded and written back to.
|
||||||
* @param[in] ulCount Value to be subtract from *pAddend.
|
* @param[in] ulCount Value to be subtract from *pulAddend.
|
||||||
*
|
*
|
||||||
* @return previous *pAddend value.
|
* @return previous *pulAddend value.
|
||||||
*/
|
*/
|
||||||
static portFORCE_INLINE uint32_t Atomic_Subtract_u32(
|
static portFORCE_INLINE uint32_t Atomic_Subtract_u32( uint32_t volatile * pulAddend,
|
||||||
uint32_t volatile * pAddend,
|
|
||||||
uint32_t ulCount )
|
uint32_t ulCount )
|
||||||
{
|
{
|
||||||
uint32_t ulCurrent;
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
ATOMIC_ENTER_CRITICAL();
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
ulCurrent = *pAddend;
|
ulCurrent = *pulAddend;
|
||||||
|
*pulAddend -= ulCount;
|
||||||
*pAddend -= ulCount;
|
}
|
||||||
|
|
||||||
ATOMIC_EXIT_CRITICAL();
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
return ulCurrent;
|
return ulCurrent;
|
||||||
}
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic increment
|
* Atomic increment
|
||||||
*
|
*
|
||||||
* @brief Atomically increments the value of the specified pointer points to.
|
* @brief Atomically increments the value of the specified pointer points to.
|
||||||
*
|
*
|
||||||
* @param[in,out] pAddend Pointer to memory location from where value is to be
|
* @param[in,out] pulAddend Pointer to memory location from where value is to be
|
||||||
* loaded and written back to.
|
* loaded and written back to.
|
||||||
*
|
*
|
||||||
* @return *pAddend value before increment.
|
* @return *pulAddend value before increment.
|
||||||
*/
|
*/
|
||||||
static portFORCE_INLINE uint32_t Atomic_Increment_u32( uint32_t volatile * pAddend )
|
static portFORCE_INLINE uint32_t Atomic_Increment_u32( uint32_t volatile * pulAddend )
|
||||||
{
|
{
|
||||||
uint32_t ulCurrent;
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
ATOMIC_ENTER_CRITICAL();
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
ulCurrent = *pAddend;
|
ulCurrent = *pulAddend;
|
||||||
|
*pulAddend += 1;
|
||||||
*pAddend += 1;
|
}
|
||||||
|
|
||||||
ATOMIC_EXIT_CRITICAL();
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
return ulCurrent;
|
return ulCurrent;
|
||||||
}
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic decrement
|
* Atomic decrement
|
||||||
*
|
*
|
||||||
* @brief Atomically decrements the value of the specified pointer points to
|
* @brief Atomically decrements the value of the specified pointer points to
|
||||||
*
|
*
|
||||||
* @param[in,out] pAddend Pointer to memory location from where value is to be
|
* @param[in,out] pulAddend Pointer to memory location from where value is to be
|
||||||
* loaded and written back to.
|
* loaded and written back to.
|
||||||
*
|
*
|
||||||
* @return *pAddend value before decrement.
|
* @return *pulAddend value before decrement.
|
||||||
*/
|
*/
|
||||||
static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pAddend )
|
static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pulAddend )
|
||||||
{
|
{
|
||||||
uint32_t ulCurrent;
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
ATOMIC_ENTER_CRITICAL();
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
ulCurrent = *pAddend;
|
ulCurrent = *pulAddend;
|
||||||
|
*pulAddend -= 1;
|
||||||
*pAddend -= 1;
|
}
|
||||||
|
|
||||||
ATOMIC_EXIT_CRITICAL();
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
return ulCurrent;
|
return ulCurrent;
|
||||||
|
@ -304,108 +305,103 @@ static portFORCE_INLINE uint32_t Atomic_Decrement_u32( uint32_t volatile * pAdde
|
||||||
*
|
*
|
||||||
* @brief Performs an atomic OR operation on the specified values.
|
* @brief Performs an atomic OR operation on the specified values.
|
||||||
*
|
*
|
||||||
* @param [in, out] pDestination Pointer to memory location from where value is
|
* @param [in, out] pulDestination Pointer to memory location from where value is
|
||||||
* to be loaded and written back to.
|
* to be loaded and written back to.
|
||||||
* @param [in] ulValue Value to be ORed with *pDestination.
|
* @param [in] ulValue Value to be ORed with *pulDestination.
|
||||||
*
|
*
|
||||||
* @return The original value of *pDestination.
|
* @return The original value of *pulDestination.
|
||||||
*/
|
*/
|
||||||
static portFORCE_INLINE uint32_t Atomic_OR_u32(
|
static portFORCE_INLINE uint32_t Atomic_OR_u32( uint32_t volatile * pulDestination,
|
||||||
uint32_t volatile * pDestination,
|
|
||||||
uint32_t ulValue )
|
uint32_t ulValue )
|
||||||
{
|
{
|
||||||
uint32_t ulCurrent;
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
ATOMIC_ENTER_CRITICAL();
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
ulCurrent = *pDestination;
|
ulCurrent = *pulDestination;
|
||||||
|
*pulDestination |= ulValue;
|
||||||
*pDestination |= ulValue;
|
}
|
||||||
|
|
||||||
ATOMIC_EXIT_CRITICAL();
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
return ulCurrent;
|
return ulCurrent;
|
||||||
}
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic AND
|
* Atomic AND
|
||||||
*
|
*
|
||||||
* @brief Performs an atomic AND operation on the specified values.
|
* @brief Performs an atomic AND operation on the specified values.
|
||||||
*
|
*
|
||||||
* @param [in, out] pDestination Pointer to memory location from where value is
|
* @param [in, out] pulDestination Pointer to memory location from where value is
|
||||||
* to be loaded and written back to.
|
* to be loaded and written back to.
|
||||||
* @param [in] ulValue Value to be ANDed with *pDestination.
|
* @param [in] ulValue Value to be ANDed with *pulDestination.
|
||||||
*
|
*
|
||||||
* @return The original value of *pDestination.
|
* @return The original value of *pulDestination.
|
||||||
*/
|
*/
|
||||||
static portFORCE_INLINE uint32_t Atomic_AND_u32(
|
static portFORCE_INLINE uint32_t Atomic_AND_u32( uint32_t volatile * pulDestination,
|
||||||
uint32_t volatile * pDestination,
|
|
||||||
uint32_t ulValue )
|
uint32_t ulValue )
|
||||||
{
|
{
|
||||||
uint32_t ulCurrent;
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
ATOMIC_ENTER_CRITICAL();
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
ulCurrent = *pDestination;
|
ulCurrent = *pulDestination;
|
||||||
|
*pulDestination &= ulValue;
|
||||||
*pDestination &= ulValue;
|
}
|
||||||
|
|
||||||
ATOMIC_EXIT_CRITICAL();
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
return ulCurrent;
|
return ulCurrent;
|
||||||
}
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic NAND
|
* Atomic NAND
|
||||||
*
|
*
|
||||||
* @brief Performs an atomic NAND operation on the specified values.
|
* @brief Performs an atomic NAND operation on the specified values.
|
||||||
*
|
*
|
||||||
* @param [in, out] pDestination Pointer to memory location from where value is
|
* @param [in, out] pulDestination Pointer to memory location from where value is
|
||||||
* to be loaded and written back to.
|
* to be loaded and written back to.
|
||||||
* @param [in] ulValue Value to be NANDed with *pDestination.
|
* @param [in] ulValue Value to be NANDed with *pulDestination.
|
||||||
*
|
*
|
||||||
* @return The original value of *pDestination.
|
* @return The original value of *pulDestination.
|
||||||
*/
|
*/
|
||||||
static portFORCE_INLINE uint32_t Atomic_NAND_u32(
|
static portFORCE_INLINE uint32_t Atomic_NAND_u32( uint32_t volatile * pulDestination,
|
||||||
uint32_t volatile * pDestination,
|
|
||||||
uint32_t ulValue )
|
uint32_t ulValue )
|
||||||
{
|
{
|
||||||
uint32_t ulCurrent;
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
ATOMIC_ENTER_CRITICAL();
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
ulCurrent = *pDestination;
|
ulCurrent = *pulDestination;
|
||||||
|
*pulDestination = ~( ulCurrent & ulValue );
|
||||||
*pDestination = ~(ulCurrent & ulValue);
|
}
|
||||||
|
|
||||||
ATOMIC_EXIT_CRITICAL();
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
return ulCurrent;
|
return ulCurrent;
|
||||||
}
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atomic XOR
|
* Atomic XOR
|
||||||
*
|
*
|
||||||
* @brief Performs an atomic XOR operation on the specified values.
|
* @brief Performs an atomic XOR operation on the specified values.
|
||||||
*
|
*
|
||||||
* @param [in, out] pDestination Pointer to memory location from where value is
|
* @param [in, out] pulDestination Pointer to memory location from where value is
|
||||||
* to be loaded and written back to.
|
* to be loaded and written back to.
|
||||||
* @param [in] ulValue Value to be XORed with *pDestination.
|
* @param [in] ulValue Value to be XORed with *pulDestination.
|
||||||
*
|
*
|
||||||
* @return The original value of *pDestination.
|
* @return The original value of *pulDestination.
|
||||||
*/
|
*/
|
||||||
static portFORCE_INLINE uint32_t Atomic_XOR_u32(
|
static portFORCE_INLINE uint32_t Atomic_XOR_u32( uint32_t volatile * pulDestination,
|
||||||
uint32_t volatile * pDestination,
|
|
||||||
uint32_t ulValue )
|
uint32_t ulValue )
|
||||||
{
|
{
|
||||||
uint32_t ulCurrent;
|
uint32_t ulCurrent;
|
||||||
|
|
||||||
ATOMIC_ENTER_CRITICAL();
|
ATOMIC_ENTER_CRITICAL();
|
||||||
|
{
|
||||||
ulCurrent = *pDestination;
|
ulCurrent = *pulDestination;
|
||||||
|
*pulDestination ^= ulValue;
|
||||||
*pDestination ^= ulValue;
|
}
|
||||||
|
|
||||||
ATOMIC_EXIT_CRITICAL();
|
ATOMIC_EXIT_CRITICAL();
|
||||||
|
|
||||||
return ulCurrent;
|
return ulCurrent;
|
||||||
|
|
|
@ -157,7 +157,7 @@ BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPri
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alternatively, if you do not require any other part of the idle task to
|
// Alternatively, if you do not require any other part of the idle task to
|
||||||
// execute, the idle task hook can call vCoRoutineScheduler() within an
|
// execute, the idle task hook can call vCoRoutineSchedule() within an
|
||||||
// infinite loop.
|
// infinite loop.
|
||||||
void vApplicationIdleHook( void )
|
void vApplicationIdleHook( void )
|
||||||
{
|
{
|
||||||
|
|
|
@ -76,6 +76,7 @@ BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue,
|
||||||
BaseType_t MPU_xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
BaseType_t MPU_xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
uint32_t MPU_ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
uint32_t MPU_ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
BaseType_t MPU_xTaskNotifyStateClear( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
BaseType_t MPU_xTaskNotifyStateClear( TaskHandle_t xTask ) FREERTOS_SYSTEM_CALL;
|
||||||
|
uint32_t MPU_ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear ) FREERTOS_SYSTEM_CALL;
|
||||||
BaseType_t MPU_xTaskIncrementTick( void ) FREERTOS_SYSTEM_CALL;
|
BaseType_t MPU_xTaskIncrementTick( void ) FREERTOS_SYSTEM_CALL;
|
||||||
TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) FREERTOS_SYSTEM_CALL;
|
TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void ) FREERTOS_SYSTEM_CALL;
|
||||||
void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) FREERTOS_SYSTEM_CALL;
|
void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) FREERTOS_SYSTEM_CALL;
|
||||||
|
@ -123,6 +124,7 @@ TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void ) FREERTOS_SYSTEM_CALL;
|
||||||
BaseType_t MPU_xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
BaseType_t MPU_xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait ) FREERTOS_SYSTEM_CALL;
|
||||||
const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||||
void MPU_vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload ) FREERTOS_SYSTEM_CALL;
|
void MPU_vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload ) FREERTOS_SYSTEM_CALL;
|
||||||
|
UBaseType_t MPU_uxTimerGetReloadMode( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||||
TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||||
TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer ) FREERTOS_SYSTEM_CALL;
|
||||||
BaseType_t MPU_xTimerCreateTimerTask( void ) FREERTOS_SYSTEM_CALL;
|
BaseType_t MPU_xTimerCreateTimerTask( void ) FREERTOS_SYSTEM_CALL;
|
||||||
|
|
|
@ -82,6 +82,7 @@ only for ports that are using the MPU. */
|
||||||
#define xTaskNotifyWait MPU_xTaskNotifyWait
|
#define xTaskNotifyWait MPU_xTaskNotifyWait
|
||||||
#define ulTaskNotifyTake MPU_ulTaskNotifyTake
|
#define ulTaskNotifyTake MPU_ulTaskNotifyTake
|
||||||
#define xTaskNotifyStateClear MPU_xTaskNotifyStateClear
|
#define xTaskNotifyStateClear MPU_xTaskNotifyStateClear
|
||||||
|
#define ulTaskNotifyValueClear MPU_ulTaskNotifyValueClear
|
||||||
#define xTaskCatchUpTicks MPU_xTaskCatchUpTicks
|
#define xTaskCatchUpTicks MPU_xTaskCatchUpTicks
|
||||||
|
|
||||||
#define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle
|
#define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle
|
||||||
|
@ -128,6 +129,7 @@ only for ports that are using the MPU. */
|
||||||
#define xTimerPendFunctionCall MPU_xTimerPendFunctionCall
|
#define xTimerPendFunctionCall MPU_xTimerPendFunctionCall
|
||||||
#define pcTimerGetName MPU_pcTimerGetName
|
#define pcTimerGetName MPU_pcTimerGetName
|
||||||
#define vTimerSetReloadMode MPU_vTimerSetReloadMode
|
#define vTimerSetReloadMode MPU_vTimerSetReloadMode
|
||||||
|
#define uxTimerGetReloadMode MPU_uxTimerGetReloadMode
|
||||||
#define xTimerGetPeriod MPU_xTimerGetPeriod
|
#define xTimerGetPeriod MPU_xTimerGetPeriod
|
||||||
#define xTimerGetExpiryTime MPU_xTimerGetExpiryTime
|
#define xTimerGetExpiryTime MPU_xTimerGetExpiryTime
|
||||||
#define xTimerGenericCommand MPU_xTimerGenericCommand
|
#define xTimerGenericCommand MPU_xTimerGenericCommand
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
* (such as xStreamBufferSend()) inside a critical section and set the send
|
* (such as xStreamBufferSend()) inside a critical section and set the send
|
||||||
* block time to 0. Likewise, if there are to be multiple different readers
|
* block time to 0. Likewise, if there are to be multiple different readers
|
||||||
* then the application writer must place each call to a reading API function
|
* then the application writer must place each call to a reading API function
|
||||||
* (such as xStreamBufferRead()) inside a critical section section and set the
|
* (such as xStreamBufferReceive()) inside a critical section section and set the
|
||||||
* receive block time to 0.
|
* receive block time to 0.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -241,7 +241,7 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
|
||||||
* (such as xStreamBufferSend()) inside a critical section and set the send
|
* (such as xStreamBufferSend()) inside a critical section and set the send
|
||||||
* block time to 0. Likewise, if there are to be multiple different readers
|
* block time to 0. Likewise, if there are to be multiple different readers
|
||||||
* then the application writer must place each call to a reading API function
|
* then the application writer must place each call to a reading API function
|
||||||
* (such as xStreamBufferRead()) inside a critical section and set the receive
|
* (such as xStreamBufferReceive()) inside a critical section and set the receive
|
||||||
* block time to 0.
|
* block time to 0.
|
||||||
*
|
*
|
||||||
* Use xStreamBufferSend() to write to a stream buffer from a task. Use
|
* Use xStreamBufferSend() to write to a stream buffer from a task. Use
|
||||||
|
@ -339,7 +339,7 @@ size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer,
|
||||||
* (such as xStreamBufferSend()) inside a critical section and set the send
|
* (such as xStreamBufferSend()) inside a critical section and set the send
|
||||||
* block time to 0. Likewise, if there are to be multiple different readers
|
* block time to 0. Likewise, if there are to be multiple different readers
|
||||||
* then the application writer must place each call to a reading API function
|
* then the application writer must place each call to a reading API function
|
||||||
* (such as xStreamBufferRead()) inside a critical section and set the receive
|
* (such as xStreamBufferReceive()) inside a critical section and set the receive
|
||||||
* block time to 0.
|
* block time to 0.
|
||||||
*
|
*
|
||||||
* Use xStreamBufferSend() to write to a stream buffer from a task. Use
|
* Use xStreamBufferSend() to write to a stream buffer from a task. Use
|
||||||
|
@ -439,7 +439,7 @@ size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer,
|
||||||
* (such as xStreamBufferSend()) inside a critical section and set the send
|
* (such as xStreamBufferSend()) inside a critical section and set the send
|
||||||
* block time to 0. Likewise, if there are to be multiple different readers
|
* block time to 0. Likewise, if there are to be multiple different readers
|
||||||
* then the application writer must place each call to a reading API function
|
* then the application writer must place each call to a reading API function
|
||||||
* (such as xStreamBufferRead()) inside a critical section and set the receive
|
* (such as xStreamBufferReceive()) inside a critical section and set the receive
|
||||||
* block time to 0.
|
* block time to 0.
|
||||||
*
|
*
|
||||||
* Use xStreamBufferReceive() to read from a stream buffer from a task. Use
|
* Use xStreamBufferReceive() to read from a stream buffer from a task. Use
|
||||||
|
|
159
include/task.h
159
include/task.h
|
@ -841,6 +841,39 @@ void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xT
|
||||||
*/
|
*/
|
||||||
BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
|
BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* task. h
|
||||||
|
* <pre>BaseType_t xTaskAbortDelayFromISR( TaskHandle_t xTask, BaseType_t * const pxHigherPriorityTaskWoken )</pre>
|
||||||
|
*
|
||||||
|
* INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this
|
||||||
|
* function to be available.
|
||||||
|
*
|
||||||
|
* A version of xTaskAbortDelay() that can be used from an interrupt service routine.
|
||||||
|
*
|
||||||
|
* A task will enter the Blocked state when it is waiting for an event. The
|
||||||
|
* event it is waiting for can be a temporal event (waiting for a time), such
|
||||||
|
* as when vTaskDelay() is called, or an event on an object, such as when
|
||||||
|
* xQueueReceive() or ulTaskNotifyTake() is called. If the handle of a task
|
||||||
|
* that is in the Blocked state is used in a call to xTaskAbortDelay() then the
|
||||||
|
* task will leave the Blocked state, and return from whichever function call
|
||||||
|
* placed the task into the Blocked state.
|
||||||
|
*
|
||||||
|
* @param xTask The handle of the task to remove from the Blocked state.
|
||||||
|
*
|
||||||
|
* @param pxHigherPriorityTaskWoken xTaskAbortDelayFromISR() will set
|
||||||
|
* *pxHigherPriorityTaskWoken to pdTRUE if a task was removed from the Blocked state,
|
||||||
|
* and the task that was removed from the Blocked state has a priority higher than the
|
||||||
|
* currently running task. If xTaskAbortDelayFromISR() sets this value to pdTRUE then
|
||||||
|
* a context switch should be requested before the interrupt is exited.
|
||||||
|
*
|
||||||
|
* @return If the task referenced by xTask was not in the Blocked state then
|
||||||
|
* pdFAIL is returned. Otherwise pdPASS is returned.
|
||||||
|
*
|
||||||
|
* \defgroup xTaskAbortDelay xTaskAbortDelayFromISR
|
||||||
|
* \ingroup TaskCtrl
|
||||||
|
*/
|
||||||
|
BaseType_t xTaskAbortDelayFromISR( TaskHandle_t xTask, BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* task. h
|
* task. h
|
||||||
* <pre>UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask );</pre>
|
* <pre>UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask );</pre>
|
||||||
|
@ -2201,6 +2234,121 @@ uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait
|
||||||
*/
|
*/
|
||||||
BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask );
|
BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* task. h
|
||||||
|
* <PRE>uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear );</pre>
|
||||||
|
*
|
||||||
|
* Clears the bits specified by the ulBitsToClear bit mask in the notification
|
||||||
|
* value of the task referenced by xTask.
|
||||||
|
*
|
||||||
|
* Set ulBitsToClear to to 0xffffffff (UINT_MAX on 32-bit architectures) to clear
|
||||||
|
* the notification value to 0. Set ulBitsToClear to 0 to query the task's
|
||||||
|
* notification value without clearing any bits.
|
||||||
|
*
|
||||||
|
* @return The value of the target task's notification value before the bits
|
||||||
|
* specified by ulBitsToClear were cleared.
|
||||||
|
* \defgroup ulTaskNotifyValueClear ulTaskNotifyValueClear
|
||||||
|
* \ingroup TaskNotifications
|
||||||
|
*/
|
||||||
|
uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* task.h
|
||||||
|
* <pre>void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )</pre>
|
||||||
|
*
|
||||||
|
* Capture the current time for future use with xTaskCheckForTimeOut().
|
||||||
|
*
|
||||||
|
* @param pxTimeOut Pointer to a timeout object into which the current time
|
||||||
|
* is to be captured. The captured time includes the tick count and the number
|
||||||
|
* of times the tick count has overflowed since the system first booted.
|
||||||
|
* \defgroup vTaskSetTimeOutState vTaskSetTimeOutState
|
||||||
|
* \ingroup TaskCtrl
|
||||||
|
*/
|
||||||
|
void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* task.h
|
||||||
|
* <pre>BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait );</pre>
|
||||||
|
*
|
||||||
|
* Determines if pxTicksToWait ticks has passed since a time was captured
|
||||||
|
* using a call to vTaskSetTimeOutState(). The captured time includes the tick
|
||||||
|
* count and the number of times the tick count has overflowed.
|
||||||
|
*
|
||||||
|
* @param pxTimeOut The time status as captured previously using
|
||||||
|
* vTaskSetTimeOutState. If the timeout has not yet occurred, it is updated
|
||||||
|
* to reflect the current time status.
|
||||||
|
* @param pxTicksToWait The number of ticks to check for timeout i.e. if
|
||||||
|
* pxTicksToWait ticks have passed since pxTimeOut was last updated (either by
|
||||||
|
* vTaskSetTimeOutState() or xTaskCheckForTimeOut()), the timeout has occurred.
|
||||||
|
* If the timeout has not occurred, pxTIcksToWait is updated to reflect the
|
||||||
|
* number of remaining ticks.
|
||||||
|
*
|
||||||
|
* @return If timeout has occurred, pdTRUE is returned. Otherwise pdFALSE is
|
||||||
|
* returned and pxTicksToWait is updated to reflect the number of remaining
|
||||||
|
* ticks.
|
||||||
|
*
|
||||||
|
* @see https://www.freertos.org/xTaskCheckForTimeOut.html
|
||||||
|
*
|
||||||
|
* Example Usage:
|
||||||
|
* <pre>
|
||||||
|
// Driver library function used to receive uxWantedBytes from an Rx buffer
|
||||||
|
// that is filled by a UART interrupt. If there are not enough bytes in the
|
||||||
|
// Rx buffer then the task enters the Blocked state until it is notified that
|
||||||
|
// more data has been placed into the buffer. If there is still not enough
|
||||||
|
// data then the task re-enters the Blocked state, and xTaskCheckForTimeOut()
|
||||||
|
// is used to re-calculate the Block time to ensure the total amount of time
|
||||||
|
// spent in the Blocked state does not exceed MAX_TIME_TO_WAIT. This
|
||||||
|
// continues until either the buffer contains at least uxWantedBytes bytes,
|
||||||
|
// or the total amount of time spent in the Blocked state reaches
|
||||||
|
// MAX_TIME_TO_WAIT – at which point the task reads however many bytes are
|
||||||
|
// available up to a maximum of uxWantedBytes.
|
||||||
|
|
||||||
|
size_t xUART_Receive( uint8_t *pucBuffer, size_t uxWantedBytes )
|
||||||
|
{
|
||||||
|
size_t uxReceived = 0;
|
||||||
|
TickType_t xTicksToWait = MAX_TIME_TO_WAIT;
|
||||||
|
TimeOut_t xTimeOut;
|
||||||
|
|
||||||
|
// Initialize xTimeOut. This records the time at which this function
|
||||||
|
// was entered.
|
||||||
|
vTaskSetTimeOutState( &xTimeOut );
|
||||||
|
|
||||||
|
// Loop until the buffer contains the wanted number of bytes, or a
|
||||||
|
// timeout occurs.
|
||||||
|
while( UART_bytes_in_rx_buffer( pxUARTInstance ) < uxWantedBytes )
|
||||||
|
{
|
||||||
|
// The buffer didn't contain enough data so this task is going to
|
||||||
|
// enter the Blocked state. Adjusting xTicksToWait to account for
|
||||||
|
// any time that has been spent in the Blocked state within this
|
||||||
|
// function so far to ensure the total amount of time spent in the
|
||||||
|
// Blocked state does not exceed MAX_TIME_TO_WAIT.
|
||||||
|
if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) != pdFALSE )
|
||||||
|
{
|
||||||
|
//Timed out before the wanted number of bytes were available,
|
||||||
|
// exit the loop.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for a maximum of xTicksToWait ticks to be notified that the
|
||||||
|
// receive interrupt has placed more data into the buffer.
|
||||||
|
ulTaskNotifyTake( pdTRUE, xTicksToWait );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to read uxWantedBytes from the receive buffer into pucBuffer.
|
||||||
|
// The actual number of bytes read (which might be less than
|
||||||
|
// uxWantedBytes) is returned.
|
||||||
|
uxReceived = UART_read_from_receive_buffer( pxUARTInstance,
|
||||||
|
pucBuffer,
|
||||||
|
uxWantedBytes );
|
||||||
|
|
||||||
|
return uxReceived;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
* \defgroup xTaskCheckForTimeOut xTaskCheckForTimeOut
|
||||||
|
* \ingroup TaskCtrl
|
||||||
|
*/
|
||||||
|
BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
/*-----------------------------------------------------------
|
/*-----------------------------------------------------------
|
||||||
* SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES
|
* SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES
|
||||||
*----------------------------------------------------------*/
|
*----------------------------------------------------------*/
|
||||||
|
@ -2317,17 +2465,6 @@ TickType_t uxTaskResetEventItemValue( void ) PRIVILEGED_FUNCTION;
|
||||||
*/
|
*/
|
||||||
TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION;
|
TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
/*
|
|
||||||
* Capture the current time status for future reference.
|
|
||||||
*/
|
|
||||||
void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Compare the time status now with that previously captured to see if the
|
|
||||||
* timeout has expired.
|
|
||||||
*/
|
|
||||||
BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ) PRIVILEGED_FUNCTION;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shortcut used by the queue implementation to prevent unnecessary call to
|
* Shortcut used by the queue implementation to prevent unnecessary call to
|
||||||
* taskYIELD();
|
* taskYIELD();
|
||||||
|
|
|
@ -1234,8 +1234,8 @@ const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint
|
||||||
/**
|
/**
|
||||||
* void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload );
|
* void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload );
|
||||||
*
|
*
|
||||||
* Updates a timer to be either an autoreload timer, in which case the timer
|
* Updates a timer to be either an auto-reload timer, in which case the timer
|
||||||
* automatically resets itself each time it expires, or a one shot timer, in
|
* automatically resets itself each time it expires, or a one-shot timer, in
|
||||||
* which case the timer will only expire once unless it is manually restarted.
|
* which case the timer will only expire once unless it is manually restarted.
|
||||||
*
|
*
|
||||||
* @param xTimer The handle of the timer being updated.
|
* @param xTimer The handle of the timer being updated.
|
||||||
|
@ -1248,6 +1248,20 @@ const char * pcTimerGetName( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION; /*lint
|
||||||
*/
|
*/
|
||||||
void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload ) PRIVILEGED_FUNCTION;
|
void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer );
|
||||||
|
*
|
||||||
|
* Queries a timer to determine if it is an auto-reload timer, in which case the timer
|
||||||
|
* automatically resets itself each time it expires, or a one-shot timer, in
|
||||||
|
* which case the timer will only expire once unless it is manually restarted.
|
||||||
|
*
|
||||||
|
* @param xTimer The handle of the timer being queried.
|
||||||
|
*
|
||||||
|
* @return If the timer is an auto-reload timer then pdTRUE is returned, otherwise
|
||||||
|
* pdFALSE is returned.
|
||||||
|
*/
|
||||||
|
UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TickType_t xTimerGetPeriod( TimerHandle_t xTimer );
|
* TickType_t xTimerGetPeriod( TimerHandle_t xTimer );
|
||||||
*
|
*
|
||||||
|
|
2
portable/ARMClang/Use-the-GCC-ports.txt
Normal file
2
portable/ARMClang/Use-the-GCC-ports.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
The FreeRTOS GCC port layer also builds and works with the ARMClang compiler.
|
||||||
|
To use the ARMClang compiler build the port files from FreeRTOS/Source/portable/GCC.
|
|
@ -210,13 +210,6 @@ uint32_t ulSetInterruptMaskFromISR( void ) /* __attribute__(( naked )) PRIVILEGE
|
||||||
" bx lr \n"
|
" bx lr \n"
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* To avoid compiler warnings. The return statement will never be reached,
|
|
||||||
* but some compilers warn if it is not included, while others won't compile
|
|
||||||
* if it is. */
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -228,14 +221,6 @@ void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask ) /
|
||||||
" bx lr \n"
|
" bx lr \n"
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* Just to avoid compiler warning. ulMask is used from the asm code but
|
|
||||||
* the compiler can't see that. Some compilers generate warnings without
|
|
||||||
* the following line, while others generate warnings if the line is
|
|
||||||
* included. */
|
|
||||||
( void ) ulMask;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -205,13 +205,6 @@ uint32_t ulSetInterruptMaskFromISR( void ) /* __attribute__(( naked )) PRIVILEGE
|
||||||
" bx lr \n"
|
" bx lr \n"
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* To avoid compiler warnings. The return statement will never be reached,
|
|
||||||
* but some compilers warn if it is not included, while others won't compile
|
|
||||||
* if it is. */
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -223,14 +216,6 @@ void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask ) /
|
||||||
" bx lr \n"
|
" bx lr \n"
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* Just to avoid compiler warning. ulMask is used from the asm code but
|
|
||||||
* the compiler can't see that. Some compilers generate warnings without
|
|
||||||
* the following line, while others generate warnings if the line is
|
|
||||||
* included. */
|
|
||||||
( void ) ulMask;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -185,13 +185,6 @@ uint32_t ulSetInterruptMaskFromISR( void ) /* __attribute__(( naked )) PRIVILEGE
|
||||||
" bx lr \n"
|
" bx lr \n"
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* To avoid compiler warnings. The return statement will never be reached,
|
|
||||||
* but some compilers warn if it is not included, while others won't compile
|
|
||||||
* if it is. */
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -203,14 +196,6 @@ void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask ) /
|
||||||
" bx lr \n"
|
" bx lr \n"
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* Just to avoid compiler warning. ulMask is used from the asm code but
|
|
||||||
* the compiler can't see that. Some compilers generate warnings without
|
|
||||||
* the following line, while others generate warnings if the line is
|
|
||||||
* included. */
|
|
||||||
( void ) ulMask;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -180,13 +180,6 @@ uint32_t ulSetInterruptMaskFromISR( void ) /* __attribute__(( naked )) PRIVILEGE
|
||||||
" bx lr \n"
|
" bx lr \n"
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* To avoid compiler warnings. The return statement will never be reached,
|
|
||||||
* but some compilers warn if it is not included, while others won't compile
|
|
||||||
* if it is. */
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -198,14 +191,6 @@ void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask ) /
|
||||||
" bx lr \n"
|
" bx lr \n"
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* Just to avoid compiler warning. ulMask is used from the asm code but
|
|
||||||
* the compiler can't see that. Some compilers generate warnings without
|
|
||||||
* the following line, while others generate warnings if the line is
|
|
||||||
* included. */
|
|
||||||
( void ) ulMask;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -292,6 +292,13 @@ typedef struct MPU_SETTINGS
|
||||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
* the source code because to do so would cause other compilers to generate
|
||||||
|
* warnings. */
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -292,6 +292,13 @@ typedef struct MPU_SETTINGS
|
||||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
* the source code because to do so would cause other compilers to generate
|
||||||
|
* warnings. */
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -292,6 +292,13 @@ typedef struct MPU_SETTINGS
|
||||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
* the source code because to do so would cause other compilers to generate
|
||||||
|
* warnings. */
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -292,6 +292,13 @@ typedef struct MPU_SETTINGS
|
||||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
* the source code because to do so would cause other compilers to generate
|
||||||
|
* warnings. */
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -586,6 +586,19 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
|
||||||
#endif
|
#endif
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configUSE_TASK_NOTIFICATIONS == 1 )
|
||||||
|
uint32_t MPU_ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear ) /* FREERTOS_SYSTEM_CALL */
|
||||||
|
{
|
||||||
|
uint32_t ulReturn;
|
||||||
|
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
|
||||||
|
|
||||||
|
ulReturn = ulTaskNotifyValueClear( xTask, ulBitsToClear );
|
||||||
|
vPortResetPrivilege( xRunningPrivileged );
|
||||||
|
return ulReturn;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||||
QueueHandle_t MPU_xQueueGenericCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize, uint8_t ucQueueType ) /* FREERTOS_SYSTEM_CALL */
|
QueueHandle_t MPU_xQueueGenericCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize, uint8_t ucQueueType ) /* FREERTOS_SYSTEM_CALL */
|
||||||
{
|
{
|
||||||
|
@ -1041,6 +1054,19 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
|
||||||
#endif
|
#endif
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configUSE_TIMERS == 1 )
|
||||||
|
UBaseType_t MPU_uxTimerGetReloadMode( TimerHandle_t xTimer )
|
||||||
|
{
|
||||||
|
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
|
||||||
|
UBaseType_t uxReturn;
|
||||||
|
|
||||||
|
uxReturn = uxTimerGetReloadMode( xTimer );
|
||||||
|
vPortResetPrivilege( xRunningPrivileged );
|
||||||
|
return uxReturn;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#if( configUSE_TIMERS == 1 )
|
#if( configUSE_TIMERS == 1 )
|
||||||
const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) /* FREERTOS_SYSTEM_CALL */
|
const char * MPU_pcTimerGetName( TimerHandle_t xTimer ) /* FREERTOS_SYSTEM_CALL */
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,15 +34,16 @@
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
/* Constants required to manipulate the NVIC. */
|
/* 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_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||||
#define portNVIC_SYSPRI2 ( ( volatile uint32_t *) 0xe000ed20 )
|
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
#define portNVIC_SYSTICK_CLK 0x00000004
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
#define portNVIC_SYSTICK_INT 0x00000002
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
#define portNVIC_SYSTICK_ENABLE 0x00000001
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
#define portNVIC_PENDSVSET 0x10000000
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
|
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||||
#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 )
|
||||||
|
@ -50,6 +51,16 @@
|
||||||
/* Constants required to set up the initial stack. */
|
/* Constants required to set up the initial stack. */
|
||||||
#define portINITIAL_XPSR ( 0x01000000 )
|
#define portINITIAL_XPSR ( 0x01000000 )
|
||||||
|
|
||||||
|
/* The systick is a 24-bit counter. */
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/* A fiddle factor to estimate the number of SysTick counts that would have
|
||||||
|
occurred while the SysTick counter is stopped during tickless idle
|
||||||
|
calculations. */
|
||||||
|
#ifndef portMISSED_COUNTS_FACTOR
|
||||||
|
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Let the user override the pre-loading of the initial LR with the address of
|
/* Let the user override the pre-loading of the initial LR with the address of
|
||||||
prvTaskExitError() in case it messes up unwinding of the stack in the
|
prvTaskExitError() in case it messes up unwinding of the stack in the
|
||||||
debugger. */
|
debugger. */
|
||||||
|
@ -60,9 +71,11 @@ debugger. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup the timer to generate the tick interrupts.
|
* Setup the timer to generate the tick interrupts. The implementation in this
|
||||||
|
* file is weak to allow application writers to change the timer used to
|
||||||
|
* generate the tick interrupt.
|
||||||
*/
|
*/
|
||||||
static void prvSetupTimerInterrupt( void );
|
void vPortSetupTimerInterrupt( void );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exception handlers.
|
* Exception handlers.
|
||||||
|
@ -89,6 +102,31 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The number of SysTick increments that make up one tick period.
|
||||||
|
*/
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The maximum number of tick periods that can be suppressed is limited by the
|
||||||
|
* 24 bit resolution of the SysTick timer.
|
||||||
|
*/
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
|
||||||
|
* power functionality only.
|
||||||
|
*/
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
static uint32_t ulStoppedTimerCompensation = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See header file for description.
|
* See header file for description.
|
||||||
*/
|
*/
|
||||||
|
@ -176,12 +214,12 @@ void vPortStartFirstTask( void )
|
||||||
BaseType_t xPortStartScheduler( void )
|
BaseType_t xPortStartScheduler( void )
|
||||||
{
|
{
|
||||||
/* 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;
|
||||||
|
|
||||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||||
here already. */
|
here already. */
|
||||||
prvSetupTimerInterrupt();
|
vPortSetupTimerInterrupt();
|
||||||
|
|
||||||
/* Initialise the critical nesting count ready for the first task. */
|
/* Initialise the critical nesting count ready for the first task. */
|
||||||
uxCriticalNesting = 0;
|
uxCriticalNesting = 0;
|
||||||
|
@ -214,7 +252,7 @@ void vPortEndScheduler( void )
|
||||||
void vPortYield( void )
|
void vPortYield( void )
|
||||||
{
|
{
|
||||||
/* 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 completely
|
/* Barriers are normally not required but do ensure the code is completely
|
||||||
within the specified behaviour for the architecture. */
|
within the specified behaviour for the architecture. */
|
||||||
|
@ -251,13 +289,6 @@ uint32_t ulSetInterruptMaskFromISR( void )
|
||||||
" bx lr "
|
" bx lr "
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* To avoid compiler warnings. The return statement will nevere be reached,
|
|
||||||
but some compilers warn if it is not included, while others won't compile if
|
|
||||||
it is. */
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -268,13 +299,6 @@ void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask )
|
||||||
" bx lr "
|
" bx lr "
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* Just to avoid compiler warning. ulMask is used from the asm code but
|
|
||||||
the compiler can't see that. Some compilers generate warnings without the
|
|
||||||
following line, while others generate warnings if the line is included. */
|
|
||||||
( void ) ulMask;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -337,7 +361,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 );
|
||||||
|
@ -348,15 +372,189 @@ uint32_t ulPreviousMask;
|
||||||
* Setup the systick timer to generate the tick interrupts at the required
|
* Setup the systick timer to generate the tick interrupts at the required
|
||||||
* frequency.
|
* frequency.
|
||||||
*/
|
*/
|
||||||
void prvSetupTimerInterrupt( void )
|
__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
|
||||||
{
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR;
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
/* Stop and reset the SysTick. */
|
/* 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;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
|
||||||
|
__attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||||
|
{
|
||||||
|
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
|
||||||
|
TickType_t xModifiableIdleTime;
|
||||||
|
|
||||||
|
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||||
|
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||||
|
{
|
||||||
|
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the SysTick momentarily. The time the SysTick is stopped for
|
||||||
|
is accounted for as best it can be, but using the tickless mode will
|
||||||
|
inevitably result in some tiny drift of the time maintained by the
|
||||||
|
kernel with respect to calendar time. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||||
|
tick periods. -1 is used because this code will execute part way
|
||||||
|
through one of the tick periods. */
|
||||||
|
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||||
|
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||||
|
{
|
||||||
|
ulReloadValue -= ulStoppedTimerCompensation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||||
|
method as that will mask interrupts that should exit sleep mode. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* If a context switch is pending or a task is waiting for the scheduler
|
||||||
|
to be unsuspended then abandon the low power entry. */
|
||||||
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||||
|
above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set the new reload value. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||||
|
|
||||||
|
/* Clear the SysTick count flag and set the count value back to
|
||||||
|
zero. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||||
|
set its parameter to 0 to indicate that its implementation contains
|
||||||
|
its own wait for interrupt or wait for event instruction, and so wfi
|
||||||
|
should not be executed again. However, the original expected idle
|
||||||
|
time variable must remain unmodified, so a copy is taken. */
|
||||||
|
xModifiableIdleTime = xExpectedIdleTime;
|
||||||
|
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||||
|
if( xModifiableIdleTime > 0 )
|
||||||
|
{
|
||||||
|
__asm volatile( "dsb" ::: "memory" );
|
||||||
|
__asm volatile( "wfi" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
}
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||||
|
out of sleep mode to execute immediately. see comments above
|
||||||
|
__disable_interrupt() call above. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable interrupts again because the clock is about to be stopped
|
||||||
|
and interrupts that execute while the clock is stopped will increase
|
||||||
|
any slippage between the time maintained by the RTOS and calendar
|
||||||
|
time. */
|
||||||
|
__asm volatile( "cpsid i" ::: "memory" );
|
||||||
|
__asm volatile( "dsb" );
|
||||||
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
|
/* Disable the SysTick clock without reading the
|
||||||
|
portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||||
|
portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
|
||||||
|
the time the SysTick is stopped for is accounted for as best it can
|
||||||
|
be, but using the tickless mode will inevitably result in some tiny
|
||||||
|
drift of the time maintained by the kernel with respect to calendar
|
||||||
|
time*/
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
|
||||||
|
|
||||||
|
/* Determine if the SysTick clock has already counted to zero and
|
||||||
|
been set back to the current reload value (the reload back being
|
||||||
|
correct for the entire expected idle time) or if the SysTick is yet
|
||||||
|
to count to zero (in which case an interrupt other than the SysTick
|
||||||
|
must have brought the system out of sleep mode). */
|
||||||
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt is already pending, and the SysTick count
|
||||||
|
reloaded with ulReloadValue. Reset the
|
||||||
|
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
|
period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
underflowed because the post sleep hook did something
|
||||||
|
that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* As the pending tick will be processed as soon as this
|
||||||
|
function exits, the tick value maintained by the tick is stepped
|
||||||
|
forward by one less than the time spent waiting. */
|
||||||
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep.
|
||||||
|
Work out how long the sleep lasted rounded to complete tick
|
||||||
|
periods (not the ulReload value which accounted for part
|
||||||
|
ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* How many complete tick periods passed while the processor
|
||||||
|
was waiting? */
|
||||||
|
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||||
|
|
||||||
|
/* The reload value is set to whatever fraction of a single tick
|
||||||
|
period remains. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||||
|
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||||
|
value. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Exit with interrpts enabled. */
|
||||||
|
__asm volatile( "cpsie i" ::: "memory" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
|
@ -101,6 +101,13 @@ extern void vClearInterruptMaskFromISR( uint32_t ulMask ) __attribute__((naked)
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Tickless idle/low power functionality. */
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
|
|
@ -210,13 +210,6 @@ uint32_t ulSetInterruptMaskFromISR( void ) /* __attribute__(( naked )) PRIVILEGE
|
||||||
" bx lr \n"
|
" bx lr \n"
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* To avoid compiler warnings. The return statement will never be reached,
|
|
||||||
* but some compilers warn if it is not included, while others won't compile
|
|
||||||
* if it is. */
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -228,14 +221,6 @@ void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask ) /
|
||||||
" bx lr \n"
|
" bx lr \n"
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* Just to avoid compiler warning. ulMask is used from the asm code but
|
|
||||||
* the compiler can't see that. Some compilers generate warnings without
|
|
||||||
* the following line, while others generate warnings if the line is
|
|
||||||
* included. */
|
|
||||||
( void ) ulMask;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -205,13 +205,6 @@ uint32_t ulSetInterruptMaskFromISR( void ) /* __attribute__(( naked )) PRIVILEGE
|
||||||
" bx lr \n"
|
" bx lr \n"
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* To avoid compiler warnings. The return statement will never be reached,
|
|
||||||
* but some compilers warn if it is not included, while others won't compile
|
|
||||||
* if it is. */
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -223,14 +216,6 @@ void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask ) /
|
||||||
" bx lr \n"
|
" bx lr \n"
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* Just to avoid compiler warning. ulMask is used from the asm code but
|
|
||||||
* the compiler can't see that. Some compilers generate warnings without
|
|
||||||
* the following line, while others generate warnings if the line is
|
|
||||||
* included. */
|
|
||||||
( void ) ulMask;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -166,6 +166,8 @@ not necessary for to use this port. They are defined so the common demo files
|
||||||
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||||
{
|
{
|
||||||
uint32_t ulCurrentInterrupt;
|
uint32_t ulCurrentInterrupt;
|
||||||
|
|
|
@ -185,13 +185,6 @@ uint32_t ulSetInterruptMaskFromISR( void ) /* __attribute__(( naked )) PRIVILEGE
|
||||||
" bx lr \n"
|
" bx lr \n"
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* To avoid compiler warnings. The return statement will never be reached,
|
|
||||||
* but some compilers warn if it is not included, while others won't compile
|
|
||||||
* if it is. */
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -203,14 +196,6 @@ void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask ) /
|
||||||
" bx lr \n"
|
" bx lr \n"
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* Just to avoid compiler warning. ulMask is used from the asm code but
|
|
||||||
* the compiler can't see that. Some compilers generate warnings without
|
|
||||||
* the following line, while others generate warnings if the line is
|
|
||||||
* included. */
|
|
||||||
( void ) ulMask;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -180,13 +180,6 @@ uint32_t ulSetInterruptMaskFromISR( void ) /* __attribute__(( naked )) PRIVILEGE
|
||||||
" bx lr \n"
|
" bx lr \n"
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* To avoid compiler warnings. The return statement will never be reached,
|
|
||||||
* but some compilers warn if it is not included, while others won't compile
|
|
||||||
* if it is. */
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -198,14 +191,6 @@ void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask ) /
|
||||||
" bx lr \n"
|
" bx lr \n"
|
||||||
::: "memory"
|
::: "memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
#if !defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
|
||||||
/* Just to avoid compiler warning. ulMask is used from the asm code but
|
|
||||||
* the compiler can't see that. Some compilers generate warnings without
|
|
||||||
* the following line, while others generate warnings if the line is
|
|
||||||
* included. */
|
|
||||||
( void ) ulMask;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
*----------------------------------------------------------*/
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||||
all the API functions to use the MPU wrappers. That should only be done when
|
* all the API functions to use the MPU wrappers. That should only be done when
|
||||||
task.h is included from an application file. */
|
* task.h is included from an application file. */
|
||||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
/* Scheduler includes. */
|
/* Scheduler includes. */
|
||||||
|
@ -46,7 +46,7 @@ task.h is included from an application file. */
|
||||||
#define portNVIC_SYSTICK_CLK ( 1UL << 2UL )
|
#define portNVIC_SYSTICK_CLK ( 1UL << 2UL )
|
||||||
#else
|
#else
|
||||||
/* The way the SysTick is clocked is not modified in case it is not the same
|
/* The way the SysTick is clocked is not modified in case it is not the same
|
||||||
as the core. */
|
* as the core. */
|
||||||
#define portNVIC_SYSTICK_CLK ( 0 )
|
#define portNVIC_SYSTICK_CLK ( 0 )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -99,8 +99,9 @@ task.h is included from an application file. */
|
||||||
#define portOFFSET_TO_PC ( 6 )
|
#define portOFFSET_TO_PC ( 6 )
|
||||||
|
|
||||||
/* For strict compliance with the Cortex-M spec the task start address should
|
/* For strict compliance with the Cortex-M spec the task start address should
|
||||||
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
|
* have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
|
||||||
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configure a number of standard MPU regions that are used by all tasks.
|
* Configure a number of standard MPU regions that are used by all tasks.
|
||||||
|
@ -171,8 +172,8 @@ extern void vPortResetPrivilege( BaseType_t xRunningPrivileged );
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Each task maintains its own interrupt status in the critical nesting
|
/* Each task maintains its own interrupt status in the critical nesting
|
||||||
variable. Note this is not saved as part of the task context as context
|
* variable. Note this is not saved as part of the task context as context
|
||||||
switches can only occur when uxCriticalNesting is zero. */
|
* switches can only occur when uxCriticalNesting is zero. */
|
||||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -185,7 +186,6 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||||
static uint32_t ulMaxPRIGROUPValue = 0;
|
static uint32_t ulMaxPRIGROUPValue = 0;
|
||||||
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||||
#endif /* configASSERT_DEFINED */
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -194,7 +194,7 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged )
|
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged )
|
||||||
{
|
{
|
||||||
/* Simulate the stack frame as it would be created by a context switch
|
/* Simulate the stack frame as it would be created by a context switch
|
||||||
interrupt. */
|
* interrupt. */
|
||||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
|
@ -240,10 +240,25 @@ void vPortSVCHandler( void )
|
||||||
static void prvSVCHandler( uint32_t *pulParam )
|
static void prvSVCHandler( uint32_t *pulParam )
|
||||||
{
|
{
|
||||||
uint8_t ucSVCNumber;
|
uint8_t ucSVCNumber;
|
||||||
|
uint32_t ulPC;
|
||||||
|
#if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )
|
||||||
|
#if defined( __ARMCC_VERSION )
|
||||||
|
/* Declaration when these variable are defined in code instead of being
|
||||||
|
* exported from linker scripts. */
|
||||||
|
extern uint32_t * __syscalls_flash_start__;
|
||||||
|
extern uint32_t * __syscalls_flash_end__;
|
||||||
|
#else
|
||||||
|
/* Declaration when these variable are exported from linker scripts. */
|
||||||
|
extern uint32_t __syscalls_flash_start__[];
|
||||||
|
extern uint32_t __syscalls_flash_end__[];
|
||||||
|
#endif /* #if defined( __ARMCC_VERSION ) */
|
||||||
|
#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
|
||||||
|
|
||||||
|
/* The stack contains: r0, r1, r2, r3, r12, LR, PC and xPSR. The first
|
||||||
|
* argument (r0) is pulParam[ 0 ]. */
|
||||||
|
ulPC = pulParam[ portOFFSET_TO_PC ];
|
||||||
|
ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ];
|
||||||
|
|
||||||
/* The stack contains: r0, r1, r2, r3, r12, r14, the return address and
|
|
||||||
xPSR. The first argument (r0) is pulParam[ 0 ]. */
|
|
||||||
ucSVCNumber = ( ( uint8_t * ) pulParam[ portOFFSET_TO_PC ] )[ -2 ];
|
|
||||||
switch( ucSVCNumber )
|
switch( ucSVCNumber )
|
||||||
{
|
{
|
||||||
case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI;
|
case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI;
|
||||||
|
@ -252,14 +267,32 @@ uint8_t ucSVCNumber;
|
||||||
|
|
||||||
case portSVC_YIELD : portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
case portSVC_YIELD : portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
/* Barriers are normally not required
|
/* Barriers are normally not required
|
||||||
but do ensure the code is completely
|
* but do ensure the code is completely
|
||||||
within the specified behaviour for the
|
* within the specified behaviour for the
|
||||||
architecture. */
|
* architecture. */
|
||||||
__asm volatile( "dsb" ::: "memory" );
|
__asm volatile( "dsb" ::: "memory" );
|
||||||
__asm volatile( "isb" );
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
#if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )
|
||||||
|
case portSVC_RAISE_PRIVILEGE : /* Only raise the privilege, if the
|
||||||
|
* svc was raised from any of the
|
||||||
|
* system calls. */
|
||||||
|
if( ulPC >= ( uint32_t ) __syscalls_flash_start__ &&
|
||||||
|
ulPC <= ( uint32_t ) __syscalls_flash_end__ )
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" mrs r1, control \n" /* Obtain current control value. */
|
||||||
|
" bic r1, #1 \n" /* Set privilege bit. */
|
||||||
|
" msr control, r1 \n" /* Write back new control value. */
|
||||||
|
::: "r1", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#else
|
||||||
case portSVC_RAISE_PRIVILEGE : __asm volatile
|
case portSVC_RAISE_PRIVILEGE : __asm volatile
|
||||||
(
|
(
|
||||||
" mrs r1, control \n" /* Obtain current control value. */
|
" mrs r1, control \n" /* Obtain current control value. */
|
||||||
|
@ -268,6 +301,7 @@ uint8_t ucSVCNumber;
|
||||||
::: "r1", "memory"
|
::: "r1", "memory"
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
|
||||||
|
|
||||||
default : /* Unknown SVC call. */
|
default : /* Unknown SVC call. */
|
||||||
break;
|
break;
|
||||||
|
@ -287,9 +321,23 @@ static void prvRestoreContextOfFirstTask( void )
|
||||||
" ldr r1, [r3] \n"
|
" ldr r1, [r3] \n"
|
||||||
" ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */
|
" ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */
|
||||||
" add r1, r1, #4 \n" /* Move onto the second item in the TCB... */
|
" add r1, r1, #4 \n" /* Move onto the second item in the TCB... */
|
||||||
|
" \n"
|
||||||
|
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
" ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */
|
||||||
|
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" bic r3, #1 \n" /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
|
||||||
|
" str r3, [r2] \n" /* Disable MPU. */
|
||||||
|
" \n"
|
||||||
" ldr r2, =0xe000ed9c \n" /* Region Base Address register. */
|
" ldr r2, =0xe000ed9c \n" /* Region Base Address register. */
|
||||||
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */
|
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */
|
||||||
" stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */
|
" stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */
|
||||||
|
" \n"
|
||||||
|
" ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */
|
||||||
|
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" orr r3, #1 \n" /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
|
||||||
|
" str r3, [r2] \n" /* Enable MPU. */
|
||||||
|
" dsb \n" /* Force memory writes before continuing. */
|
||||||
|
" \n"
|
||||||
" ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */
|
" ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */
|
||||||
" msr control, r3 \n"
|
" msr control, r3 \n"
|
||||||
" msr psp, r0 \n" /* Restore the task stack pointer. */
|
" msr psp, r0 \n" /* Restore the task stack pointer. */
|
||||||
|
@ -310,7 +358,7 @@ static void prvRestoreContextOfFirstTask( void )
|
||||||
BaseType_t xPortStartScheduler( void )
|
BaseType_t xPortStartScheduler( void )
|
||||||
{
|
{
|
||||||
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See
|
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See
|
||||||
http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
* http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
||||||
configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) );
|
configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) );
|
||||||
|
|
||||||
#if( configASSERT_DEFINED == 1 )
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
@ -320,15 +368,15 @@ BaseType_t xPortStartScheduler( void )
|
||||||
volatile uint8_t ucMaxPriorityValue;
|
volatile uint8_t ucMaxPriorityValue;
|
||||||
|
|
||||||
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||||
functions can be called. ISR safe functions are those that end in
|
* functions can be called. ISR safe functions are those that end in
|
||||||
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
* "FromISR". FreeRTOS maintains separate thread and ISR API functions
|
||||||
ensure interrupt entry is as fast and simple as possible.
|
* to ensure interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
Save the interrupt priority value that is about to be clobbered. */
|
* Save the interrupt priority value that is about to be clobbered. */
|
||||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||||
|
|
||||||
/* Determine the number of priority bits available. First write to all
|
/* Determine the number of priority bits available. First write to all
|
||||||
possible bits. */
|
* possible bits. */
|
||||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||||
|
|
||||||
/* Read the value back to see how many bits stuck. */
|
/* Read the value back to see how many bits stuck. */
|
||||||
|
@ -338,7 +386,7 @@ BaseType_t xPortStartScheduler( void )
|
||||||
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||||
|
|
||||||
/* Calculate the maximum acceptable priority group value for the number
|
/* Calculate the maximum acceptable priority group value for the number
|
||||||
of bits read back. */
|
* of bits read back. */
|
||||||
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
||||||
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||||
{
|
{
|
||||||
|
@ -349,8 +397,8 @@ BaseType_t xPortStartScheduler( void )
|
||||||
#ifdef __NVIC_PRIO_BITS
|
#ifdef __NVIC_PRIO_BITS
|
||||||
{
|
{
|
||||||
/* Check the CMSIS configuration that defines the number of
|
/* Check the CMSIS configuration that defines the number of
|
||||||
priority bits matches the number of priority bits actually queried
|
* priority bits matches the number of priority bits actually queried
|
||||||
from the hardware. */
|
* from the hardware. */
|
||||||
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
|
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -358,26 +406,26 @@ BaseType_t xPortStartScheduler( void )
|
||||||
#ifdef configPRIO_BITS
|
#ifdef configPRIO_BITS
|
||||||
{
|
{
|
||||||
/* Check the FreeRTOS configuration that defines the number of
|
/* Check the FreeRTOS configuration that defines the number of
|
||||||
priority bits matches the number of priority bits actually queried
|
* priority bits matches the number of priority bits actually queried
|
||||||
from the hardware. */
|
* from the hardware. */
|
||||||
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
|
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Shift the priority group value back to its position within the AIRCR
|
/* Shift the priority group value back to its position within the AIRCR
|
||||||
register. */
|
* register. */
|
||||||
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||||
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||||
|
|
||||||
/* Restore the clobbered interrupt priority register to its original
|
/* Restore the clobbered interrupt priority register to its original
|
||||||
value. */
|
* value. */
|
||||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||||
}
|
}
|
||||||
#endif /* conifgASSERT_DEFINED */
|
#endif /* conifgASSERT_DEFINED */
|
||||||
|
|
||||||
/* Make PendSV and SysTick the same priority as the kernel, and the SVC
|
/* Make PendSV and SysTick the same priority as the kernel, and the SVC
|
||||||
handler higher priority so it can be used to exit a critical section (where
|
* handler higher priority so it can be used to exit a critical section (where
|
||||||
lower priorities are masked). */
|
* lower priorities are masked). */
|
||||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
|
@ -385,7 +433,7 @@ BaseType_t xPortStartScheduler( void )
|
||||||
prvSetupMPU();
|
prvSetupMPU();
|
||||||
|
|
||||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||||
here already. */
|
* here already. */
|
||||||
vPortSetupTimerInterrupt();
|
vPortSetupTimerInterrupt();
|
||||||
|
|
||||||
/* Initialise the critical nesting count ready for the first task. */
|
/* Initialise the critical nesting count ready for the first task. */
|
||||||
|
@ -413,7 +461,7 @@ BaseType_t xPortStartScheduler( void )
|
||||||
void vPortEndScheduler( void )
|
void vPortEndScheduler( void )
|
||||||
{
|
{
|
||||||
/* Not implemented in ports where there is nothing to return to.
|
/* Not implemented in ports where there is nothing to return to.
|
||||||
Artificially force an assert. */
|
* Artificially force an assert. */
|
||||||
configASSERT( uxCriticalNesting == 1000UL );
|
configASSERT( uxCriticalNesting == 1000UL );
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
@ -471,9 +519,23 @@ void xPortPendSVHandler( void )
|
||||||
" ldr r1, [r3] \n"
|
" ldr r1, [r3] \n"
|
||||||
" ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */
|
" ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */
|
||||||
" add r1, r1, #4 \n" /* Move onto the second item in the TCB... */
|
" add r1, r1, #4 \n" /* Move onto the second item in the TCB... */
|
||||||
|
" \n"
|
||||||
|
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
" ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */
|
||||||
|
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" bic r3, #1 \n" /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
|
||||||
|
" str r3, [r2] \n" /* Disable MPU. */
|
||||||
|
" \n"
|
||||||
" ldr r2, =0xe000ed9c \n" /* Region Base Address register. */
|
" ldr r2, =0xe000ed9c \n" /* Region Base Address register. */
|
||||||
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */
|
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */
|
||||||
" stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */
|
" stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */
|
||||||
|
" \n"
|
||||||
|
" ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */
|
||||||
|
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" orr r3, #1 \n" /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
|
||||||
|
" str r3, [r2] \n" /* Enable MPU. */
|
||||||
|
" dsb \n" /* Force memory writes before continuing. */
|
||||||
|
" \n"
|
||||||
" ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */
|
" ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */
|
||||||
" msr control, r3 \n"
|
" msr control, r3 \n"
|
||||||
" \n"
|
" \n"
|
||||||
|
@ -542,8 +604,8 @@ extern uint32_t __privileged_data_end__[];
|
||||||
( portMPU_REGION_ENABLE );
|
( portMPU_REGION_ENABLE );
|
||||||
|
|
||||||
/* Setup the first 16K for privileged only access (even though less
|
/* Setup the first 16K for privileged only access (even though less
|
||||||
than 10K is actually being used). This is where the kernel code is
|
* than 10K is actually being used). This is where the kernel code is
|
||||||
placed. */
|
* placed. */
|
||||||
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 ) |
|
||||||
( portPRIVILEGED_FLASH_REGION );
|
( portPRIVILEGED_FLASH_REGION );
|
||||||
|
@ -554,7 +616,7 @@ extern uint32_t __privileged_data_end__[];
|
||||||
( 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
|
||||||
is placed. */
|
* is placed. */
|
||||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
( portPRIVILEGED_RAM_REGION );
|
( portPRIVILEGED_RAM_REGION );
|
||||||
|
@ -565,7 +627,7 @@ extern uint32_t __privileged_data_end__[];
|
||||||
( portMPU_REGION_ENABLE );
|
( portMPU_REGION_ENABLE );
|
||||||
|
|
||||||
/* By default allow everything to access the general peripherals. The
|
/* By default allow everything to access the general peripherals. The
|
||||||
system peripherals and registers are protected. */
|
* system peripherals and registers are protected. */
|
||||||
portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) |
|
portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) |
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
( portGENERAL_PERIPHERALS_REGION );
|
( portGENERAL_PERIPHERALS_REGION );
|
||||||
|
@ -588,7 +650,7 @@ static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes )
|
||||||
uint32_t ulRegionSize, ulReturnValue = 4;
|
uint32_t ulRegionSize, ulReturnValue = 4;
|
||||||
|
|
||||||
/* 32 is the smallest region size, 31 is the largest valid value for
|
/* 32 is the smallest region size, 31 is the largest valid value for
|
||||||
ulReturnValue. */
|
* ulReturnValue. */
|
||||||
for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) )
|
for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) )
|
||||||
{
|
{
|
||||||
if( ulActualSizeInBytes <= ulRegionSize )
|
if( ulActualSizeInBytes <= ulRegionSize )
|
||||||
|
@ -602,7 +664,7 @@ uint32_t ulRegionSize, ulReturnValue = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shift the code by one before returning so it can be written directly
|
/* Shift the code by one before returning so it can be written directly
|
||||||
into the the correct bit position of the attribute register. */
|
* into the the correct bit position of the attribute register. */
|
||||||
return ( ulReturnValue << 1UL );
|
return ( ulReturnValue << 1UL );
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
@ -661,7 +723,7 @@ uint32_t ul;
|
||||||
( portMPU_REGION_ENABLE );
|
( portMPU_REGION_ENABLE );
|
||||||
|
|
||||||
/* Re-instate the privileged only RAM region as xRegion[ 0 ] will have
|
/* Re-instate the privileged only RAM region as xRegion[ 0 ] will have
|
||||||
just removed the privileged only parameters. */
|
* just removed the privileged only parameters. */
|
||||||
xMPUSettings->xRegion[ 1 ].ulRegionBaseAddress =
|
xMPUSettings->xRegion[ 1 ].ulRegionBaseAddress =
|
||||||
( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
|
@ -683,9 +745,9 @@ uint32_t ul;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* This function is called automatically when the task is created - in
|
/* This function is called automatically when the task is created - in
|
||||||
which case the stack region parameters will be valid. At all other
|
* which case the stack region parameters will be valid. At all other
|
||||||
times the stack parameters will not be valid and it is assumed that the
|
* times the stack parameters will not be valid and it is assumed that the
|
||||||
stack region has already been configured. */
|
* stack region has already been configured. */
|
||||||
if( ulStackDepth > 0 )
|
if( ulStackDepth > 0 )
|
||||||
{
|
{
|
||||||
/* Define the region that allows access to the stack. */
|
/* Define the region that allows access to the stack. */
|
||||||
|
@ -708,8 +770,8 @@ uint32_t ul;
|
||||||
if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL )
|
if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL )
|
||||||
{
|
{
|
||||||
/* Translate the generic region definition contained in
|
/* Translate the generic region definition contained in
|
||||||
xRegions into the CM3 specific MPU settings that are then
|
* xRegions into the CM3 specific MPU settings that are then
|
||||||
stored in xMPUSettings. */
|
* stored in xMPUSettings. */
|
||||||
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress =
|
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress =
|
||||||
( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) |
|
( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) |
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
|
@ -750,48 +812,46 @@ uint32_t ul;
|
||||||
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||||
|
|
||||||
/* The following assertion will fail if a service routine (ISR) for
|
/* The following assertion will fail if a service routine (ISR) for
|
||||||
an interrupt that has been assigned a priority above
|
* an interrupt that has been assigned a priority above
|
||||||
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||||
function. ISR safe FreeRTOS API functions must *only* be called
|
* function. ISR safe FreeRTOS API functions must *only* be called
|
||||||
from interrupts that have been assigned a priority at or below
|
* from interrupts that have been assigned a priority at or below
|
||||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
Numerically low interrupt priority numbers represent logically high
|
* Numerically low interrupt priority numbers represent logically high
|
||||||
interrupt priorities, therefore the priority of the interrupt must
|
* interrupt priorities, therefore the priority of the interrupt must
|
||||||
be set to a value equal to or numerically *higher* than
|
* be set to a value equal to or numerically *higher* than
|
||||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
Interrupts that use the FreeRTOS API must not be left at their
|
* Interrupts that use the FreeRTOS API must not be left at their
|
||||||
default priority of zero as that is the highest possible priority,
|
* default priority of zero as that is the highest possible priority,
|
||||||
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
* which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||||
and therefore also guaranteed to be invalid.
|
* and therefore also guaranteed to be invalid.
|
||||||
|
|
||||||
FreeRTOS maintains separate thread and ISR API functions to ensure
|
* FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||||
interrupt entry is as fast and simple as possible.
|
* interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
The following links provide detailed information:
|
* The following links provide detailed information:
|
||||||
http://www.freertos.org/RTOS-Cortex-M3-M4.html
|
* http://www.freertos.org/RTOS-Cortex-M3-M4.html
|
||||||
http://www.freertos.org/FAQHelp.html */
|
* http://www.freertos.org/FAQHelp.html */
|
||||||
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
||||||
that define each interrupt's priority to be split between bits that
|
* that define each interrupt's priority to be split between bits that
|
||||||
define the interrupt's pre-emption priority bits and bits that define
|
* define the interrupt's pre-emption priority bits and bits that define
|
||||||
the interrupt's sub-priority. For simplicity all bits must be defined
|
* the interrupt's sub-priority. For simplicity all bits must be defined
|
||||||
to be pre-emption priority bits. The following assertion will fail if
|
* to be pre-emption priority bits. The following assertion will fail if
|
||||||
this is not the case (if some bits represent a sub-priority).
|
* this is not the case (if some bits represent a sub-priority).
|
||||||
|
|
||||||
If the application only uses CMSIS libraries for interrupt
|
* If the application only uses CMSIS libraries for interrupt
|
||||||
configuration then the correct setting can be achieved on all Cortex-M
|
* configuration then the correct setting can be achieved on all Cortex-M
|
||||||
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
* devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||||
scheduler. Note however that some vendor specific peripheral libraries
|
* scheduler. Note however that some vendor specific peripheral libraries
|
||||||
assume a non-zero priority group setting, in which cases using a value
|
* assume a non-zero priority group setting, in which cases using a value
|
||||||
of zero will result in unpredicable behaviour. */
|
* of zero will result in unpredicable behaviour. */
|
||||||
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* configASSERT_DEFINED */
|
#endif /* configASSERT_DEFINED */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,7 @@ typedef unsigned long UBaseType_t;
|
||||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
|
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
|
||||||
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
|
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
|
||||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
|
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
|
||||||
|
#define portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ( 0x02UL << 24UL )
|
||||||
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
|
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
|
||||||
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
|
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
|
||||||
|
|
||||||
|
@ -293,6 +294,11 @@ portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||||
|
|
||||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||||
|
|
||||||
|
#ifndef configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY
|
||||||
|
#warning "configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY is not defined. We recommend defining it to 1 in FreeRTOSConfig.h for better security."
|
||||||
|
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 0
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -134,7 +134,7 @@ void vPortSetupTimerInterrupt( void );
|
||||||
* Standard FreeRTOS exception handlers.
|
* Standard FreeRTOS exception handlers.
|
||||||
*/
|
*/
|
||||||
void xPortPendSVHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
void xPortPendSVHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||||
void xPortSysTickHandler( void ) __attribute__ ((optimize("3"))) PRIVILEGED_FUNCTION;
|
void xPortSysTickHandler( void ) PRIVILEGED_FUNCTION;
|
||||||
void vPortSVCHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
void vPortSVCHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -260,10 +260,25 @@ void vPortSVCHandler( void )
|
||||||
static void prvSVCHandler( uint32_t *pulParam )
|
static void prvSVCHandler( uint32_t *pulParam )
|
||||||
{
|
{
|
||||||
uint8_t ucSVCNumber;
|
uint8_t ucSVCNumber;
|
||||||
|
uint32_t ulPC;
|
||||||
|
#if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )
|
||||||
|
#if defined( __ARMCC_VERSION )
|
||||||
|
/* Declaration when these variable are defined in code instead of being
|
||||||
|
* exported from linker scripts. */
|
||||||
|
extern uint32_t * __syscalls_flash_start__;
|
||||||
|
extern uint32_t * __syscalls_flash_end__;
|
||||||
|
#else
|
||||||
|
/* Declaration when these variable are exported from linker scripts. */
|
||||||
|
extern uint32_t __syscalls_flash_start__[];
|
||||||
|
extern uint32_t __syscalls_flash_end__[];
|
||||||
|
#endif /* #if defined( __ARMCC_VERSION ) */
|
||||||
|
#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
|
||||||
|
|
||||||
|
/* The stack contains: r0, r1, r2, r3, r12, LR, PC and xPSR. The first
|
||||||
|
argument (r0) is pulParam[ 0 ]. */
|
||||||
|
ulPC = pulParam[ portOFFSET_TO_PC ];
|
||||||
|
ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ];
|
||||||
|
|
||||||
/* The stack contains: r0, r1, r2, r3, r12, r14, the return address and
|
|
||||||
xPSR. The first argument (r0) is pulParam[ 0 ]. */
|
|
||||||
ucSVCNumber = ( ( uint8_t * ) pulParam[ portOFFSET_TO_PC ] )[ -2 ];
|
|
||||||
switch( ucSVCNumber )
|
switch( ucSVCNumber )
|
||||||
{
|
{
|
||||||
case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI;
|
case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI;
|
||||||
|
@ -280,6 +295,23 @@ uint8_t ucSVCNumber;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )
|
||||||
|
case portSVC_RAISE_PRIVILEGE : /* Only raise the privilege, if the
|
||||||
|
* svc was raised from any of the
|
||||||
|
* system calls. */
|
||||||
|
if( ulPC >= ( uint32_t ) __syscalls_flash_start__ &&
|
||||||
|
ulPC <= ( uint32_t ) __syscalls_flash_end__ )
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" mrs r1, control \n" /* Obtain current control value. */
|
||||||
|
" bic r1, #1 \n" /* Set privilege bit. */
|
||||||
|
" msr control, r1 \n" /* Write back new control value. */
|
||||||
|
::: "r1", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#else
|
||||||
case portSVC_RAISE_PRIVILEGE : __asm volatile
|
case portSVC_RAISE_PRIVILEGE : __asm volatile
|
||||||
(
|
(
|
||||||
" mrs r1, control \n" /* Obtain current control value. */
|
" mrs r1, control \n" /* Obtain current control value. */
|
||||||
|
@ -288,6 +320,7 @@ uint8_t ucSVCNumber;
|
||||||
::: "r1", "memory"
|
::: "r1", "memory"
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
|
||||||
|
|
||||||
default : /* Unknown SVC call. */
|
default : /* Unknown SVC call. */
|
||||||
break;
|
break;
|
||||||
|
@ -307,9 +340,23 @@ static void prvRestoreContextOfFirstTask( void )
|
||||||
" ldr r1, [r3] \n"
|
" ldr r1, [r3] \n"
|
||||||
" ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */
|
" ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */
|
||||||
" add r1, r1, #4 \n" /* Move onto the second item in the TCB... */
|
" add r1, r1, #4 \n" /* Move onto the second item in the TCB... */
|
||||||
|
" \n"
|
||||||
|
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
" ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */
|
||||||
|
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" bic r3, #1 \n" /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
|
||||||
|
" str r3, [r2] \n" /* Disable MPU. */
|
||||||
|
" \n"
|
||||||
" ldr r2, =0xe000ed9c \n" /* Region Base Address register. */
|
" ldr r2, =0xe000ed9c \n" /* Region Base Address register. */
|
||||||
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */
|
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers from TCB. */
|
||||||
" stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */
|
" stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */
|
||||||
|
" \n"
|
||||||
|
" ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */
|
||||||
|
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" orr r3, #1 \n" /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
|
||||||
|
" str r3, [r2] \n" /* Enable MPU. */
|
||||||
|
" dsb \n" /* Force memory writes before continuing. */
|
||||||
|
" \n"
|
||||||
" ldmia r0!, {r3-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry. */
|
" ldmia r0!, {r3-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry. */
|
||||||
" msr control, r3 \n"
|
" msr control, r3 \n"
|
||||||
" msr psp, r0 \n" /* Restore the task stack pointer. */
|
" msr psp, r0 \n" /* Restore the task stack pointer. */
|
||||||
|
@ -506,9 +553,23 @@ void xPortPendSVHandler( void )
|
||||||
" ldr r1, [r3] \n"
|
" ldr r1, [r3] \n"
|
||||||
" ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */
|
" ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */
|
||||||
" add r1, r1, #4 \n" /* Move onto the second item in the TCB... */
|
" add r1, r1, #4 \n" /* Move onto the second item in the TCB... */
|
||||||
|
" \n"
|
||||||
|
" dmb \n" /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
" ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */
|
||||||
|
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" bic r3, #1 \n" /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
|
||||||
|
" str r3, [r2] \n" /* Disable MPU. */
|
||||||
|
" \n"
|
||||||
" ldr r2, =0xe000ed9c \n" /* Region Base Address register. */
|
" ldr r2, =0xe000ed9c \n" /* Region Base Address register. */
|
||||||
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */
|
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers from TCB. */
|
||||||
" stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */
|
" stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */
|
||||||
|
" \n"
|
||||||
|
" ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */
|
||||||
|
" ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */
|
||||||
|
" orr r3, #1 \n" /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
|
||||||
|
" str r3, [r2] \n" /* Enable MPU. */
|
||||||
|
" dsb \n" /* Force memory writes before continuing. */
|
||||||
|
" \n"
|
||||||
" ldmia r0!, {r3-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry. */
|
" ldmia r0!, {r3-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry. */
|
||||||
" msr control, r3 \n"
|
" msr control, r3 \n"
|
||||||
" \n"
|
" \n"
|
||||||
|
@ -576,12 +637,22 @@ static void vPortEnableVFP( void )
|
||||||
|
|
||||||
static void prvSetupMPU( void )
|
static void prvSetupMPU( void )
|
||||||
{
|
{
|
||||||
extern uint32_t __privileged_functions_end__[];
|
#if defined( __ARMCC_VERSION )
|
||||||
extern uint32_t __FLASH_segment_start__[];
|
/* Declaration when these variable are defined in code instead of being
|
||||||
extern uint32_t __FLASH_segment_end__[];
|
* exported from linker scripts. */
|
||||||
extern uint32_t __privileged_data_start__[];
|
extern uint32_t * __privileged_functions_end__;
|
||||||
extern uint32_t __privileged_data_end__[];
|
extern uint32_t * __FLASH_segment_start__;
|
||||||
|
extern uint32_t * __FLASH_segment_end__;
|
||||||
|
extern uint32_t * __privileged_data_start__;
|
||||||
|
extern uint32_t * __privileged_data_end__;
|
||||||
|
#else
|
||||||
|
/* Declaration when these variable are exported from linker scripts. */
|
||||||
|
extern uint32_t __privileged_functions_end__[];
|
||||||
|
extern uint32_t __FLASH_segment_start__[];
|
||||||
|
extern uint32_t __FLASH_segment_end__[];
|
||||||
|
extern uint32_t __privileged_data_start__[];
|
||||||
|
extern uint32_t __privileged_data_end__[];
|
||||||
|
#endif
|
||||||
/* 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 )
|
||||||
{
|
{
|
||||||
|
@ -693,10 +764,21 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||||
|
|
||||||
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth )
|
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth )
|
||||||
{
|
{
|
||||||
extern uint32_t __SRAM_segment_start__[];
|
#if defined( __ARMCC_VERSION )
|
||||||
extern uint32_t __SRAM_segment_end__[];
|
/* Declaration when these variable are defined in code instead of being
|
||||||
extern uint32_t __privileged_data_start__[];
|
* exported from linker scripts. */
|
||||||
extern uint32_t __privileged_data_end__[];
|
extern uint32_t * __SRAM_segment_start__;
|
||||||
|
extern uint32_t * __SRAM_segment_end__;
|
||||||
|
extern uint32_t * __privileged_data_start__;
|
||||||
|
extern uint32_t * __privileged_data_end__;
|
||||||
|
#else
|
||||||
|
/* Declaration when these variable are exported from linker scripts. */
|
||||||
|
extern uint32_t __SRAM_segment_start__[];
|
||||||
|
extern uint32_t __SRAM_segment_end__[];
|
||||||
|
extern uint32_t __privileged_data_start__[];
|
||||||
|
extern uint32_t __privileged_data_end__[];
|
||||||
|
#endif
|
||||||
|
|
||||||
int32_t lIndex;
|
int32_t lIndex;
|
||||||
uint32_t ul;
|
uint32_t ul;
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,7 @@ typedef unsigned long UBaseType_t;
|
||||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
|
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
|
||||||
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
|
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
|
||||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
|
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
|
||||||
|
#define portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ( 0x02UL << 24UL )
|
||||||
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
|
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
|
||||||
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
|
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
|
||||||
|
|
||||||
|
@ -293,6 +294,11 @@ portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||||
|
|
||||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||||
|
|
||||||
|
#ifndef configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY
|
||||||
|
#warning "configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY is not defined. We recommend defining it to 1 in FreeRTOSConfig.h for better security."
|
||||||
|
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 0
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
#ifndef __FREERTOS_RISC_V_EXTENSIONS_H__
|
#ifndef __FREERTOS_RISC_V_EXTENSIONS_H__
|
||||||
#define __FREERTOS_RISC_V_EXTENSIONS_H__
|
#define __FREERTOS_RISC_V_EXTENSIONS_H__
|
||||||
|
|
||||||
#define portasmHAS_CLINT 0
|
#define portasmHAS_MTIME 0
|
||||||
|
|
||||||
/* Constants to define the additional registers found on the Pulpino RI5KY. */
|
/* Constants to define the additional registers found on the Pulpino RI5KY. */
|
||||||
#define lpstart0 0x7b0
|
#define lpstart0 0x7b0
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
#ifndef __FREERTOS_RISC_V_EXTENSIONS_H__
|
#ifndef __FREERTOS_RISC_V_EXTENSIONS_H__
|
||||||
#define __FREERTOS_RISC_V_EXTENSIONS_H__
|
#define __FREERTOS_RISC_V_EXTENSIONS_H__
|
||||||
|
|
||||||
#define portasmHAS_CLINT 1
|
#define portasmHAS_MTIME 1
|
||||||
#define portasmADDITIONAL_CONTEXT_SIZE 0 /* Must be even number on 32-bit cores. */
|
#define portasmADDITIONAL_CONTEXT_SIZE 0 /* Must be even number on 32-bit cores. */
|
||||||
|
|
||||||
.macro portasmSAVE_ADDITIONAL_REGISTERS
|
.macro portasmSAVE_ADDITIONAL_REGISTERS
|
||||||
|
|
|
@ -34,8 +34,19 @@
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "portmacro.h"
|
#include "portmacro.h"
|
||||||
|
|
||||||
#ifndef configCLINT_BASE_ADDRESS
|
/* Standard includes. */
|
||||||
#warning configCLINT_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a Core Local Interrupter (CLINT) then set configCLINT_BASE_ADDRESS to the CLINT base address. Otherwise set configCLINT_BASE_ADDRESS to 0.
|
#include "string.h"
|
||||||
|
|
||||||
|
#ifdef configCLINT_BASE_ADDRESS
|
||||||
|
#warning The configCLINT_BASE_ADDRESS constant has been deprecated. configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS are currently being derived from the (possibly 0) configCLINT_BASE_ADDRESS setting. Please update to define configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS dirctly in place of configCLINT_BASE_ADDRESS.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configMTIME_BASE_ADDRESS
|
||||||
|
#warning configMTIME_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a memory-mapped mtime register then set configMTIME_BASE_ADDRESS to the mapped address. Otherwise set configMTIME_BASE_ADDRESS to 0.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configMTIMECMP_BASE_ADDRESS
|
||||||
|
#warning configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a memory-mapped mtimecmp register then set configMTIMECMP_BASE_ADDRESS to the mapped address. Otherwise set configMTIMECMP_BASE_ADDRESS to 0.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Let the user override the pre-loading of the initial LR with the address of
|
/* Let the user override the pre-loading of the initial LR with the address of
|
||||||
|
@ -57,6 +68,11 @@ interrupt stack after the scheduler has started. */
|
||||||
#ifdef configISR_STACK_SIZE_WORDS
|
#ifdef configISR_STACK_SIZE_WORDS
|
||||||
static __attribute__ ((aligned(16))) StackType_t xISRStack[ configISR_STACK_SIZE_WORDS ] = { 0 };
|
static __attribute__ ((aligned(16))) StackType_t xISRStack[ configISR_STACK_SIZE_WORDS ] = { 0 };
|
||||||
const StackType_t xISRStackTop = ( StackType_t ) &( xISRStack[ configISR_STACK_SIZE_WORDS & ~portBYTE_ALIGNMENT_MASK ] );
|
const StackType_t xISRStackTop = ( StackType_t ) &( xISRStack[ configISR_STACK_SIZE_WORDS & ~portBYTE_ALIGNMENT_MASK ] );
|
||||||
|
|
||||||
|
/* Don't use 0xa5 as the stack fill bytes as that is used by the kernerl for
|
||||||
|
the task stacks, and so will legitimately appear in many positions within
|
||||||
|
the ISR stack. */
|
||||||
|
#define portISR_STACK_FILL_BYTE 0xee
|
||||||
#else
|
#else
|
||||||
extern const uint32_t __freertos_irq_stack_top[];
|
extern const uint32_t __freertos_irq_stack_top[];
|
||||||
const StackType_t xISRStackTop = ( StackType_t ) __freertos_irq_stack_top;
|
const StackType_t xISRStackTop = ( StackType_t ) __freertos_irq_stack_top;
|
||||||
|
@ -74,20 +90,16 @@ void vPortSetupTimerInterrupt( void ) __attribute__(( weak ));
|
||||||
/* Used to program the machine timer compare register. */
|
/* Used to program the machine timer compare register. */
|
||||||
uint64_t ullNextTime = 0ULL;
|
uint64_t ullNextTime = 0ULL;
|
||||||
const uint64_t *pullNextTime = &ullNextTime;
|
const uint64_t *pullNextTime = &ullNextTime;
|
||||||
const size_t uxTimerIncrementsForOneTick = ( size_t ) ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ); /* Assumes increment won't go over 32-bits. */
|
const size_t uxTimerIncrementsForOneTick = ( size_t ) ( ( configCPU_CLOCK_HZ ) / ( configTICK_RATE_HZ ) ); /* Assumes increment won't go over 32-bits. */
|
||||||
volatile uint64_t * const pullMachineTimerCompareRegisterBase = ( volatile uint64_t * const ) ( configCLINT_BASE_ADDRESS + 0x4000 );
|
uint32_t const ullMachineTimerCompareRegisterBase = configMTIMECMP_BASE_ADDRESS;
|
||||||
volatile uint64_t * pullMachineTimerCompareRegister = 0;
|
volatile uint64_t * pullMachineTimerCompareRegister = NULL;
|
||||||
|
|
||||||
/* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task
|
/* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task
|
||||||
stack checking. A problem in the ISR stack will trigger an assert, not call the
|
stack checking. A problem in the ISR stack will trigger an assert, not call the
|
||||||
stack overflow hook function (because the stack overflow hook is specific to a
|
stack overflow hook function (because the stack overflow hook is specific to a
|
||||||
task stack, not the ISR stack). */
|
task stack, not the ISR stack). */
|
||||||
#if( configCHECK_FOR_STACK_OVERFLOW > 2 )
|
#if defined( configISR_STACK_SIZE_WORDS ) && ( configCHECK_FOR_STACK_OVERFLOW > 2 )
|
||||||
#warning This path not tested, or even compiled yet.
|
#warning This path not tested, or even compiled yet.
|
||||||
/* Don't use 0xa5 as the stack fill bytes as that is used by the kernerl for
|
|
||||||
the task stacks, and so will legitimately appear in many positions within
|
|
||||||
the ISR stack. */
|
|
||||||
#define portISR_STACK_FILL_BYTE 0xee
|
|
||||||
|
|
||||||
static const uint8_t ucExpectedStackBytes[] = {
|
static const uint8_t ucExpectedStackBytes[] = {
|
||||||
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
|
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
|
||||||
|
@ -104,17 +116,17 @@ task stack, not the ISR stack). */
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#if( configCLINT_BASE_ADDRESS != 0 )
|
#if( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 )
|
||||||
|
|
||||||
void vPortSetupTimerInterrupt( void )
|
void vPortSetupTimerInterrupt( void )
|
||||||
{
|
{
|
||||||
uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;
|
uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;
|
||||||
volatile uint32_t * const pulTimeHigh = ( volatile uint32_t * const ) ( configCLINT_BASE_ADDRESS + 0xBFFC );
|
volatile uint32_t * const pulTimeHigh = ( volatile uint32_t * const ) ( ( configMTIME_BASE_ADDRESS ) + 4UL ); /* 8-byte typer so high 32-bit word is 4 bytes up. */
|
||||||
volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configCLINT_BASE_ADDRESS + 0xBFF8 );
|
volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configMTIME_BASE_ADDRESS );
|
||||||
volatile uint32_t ulHartId = 0;
|
volatile uint32_t ulHartId;
|
||||||
|
|
||||||
__asm volatile( "csrr %0, mhartid" : "=r"( ulHartId ) );
|
__asm volatile( "csrr %0, mhartid" : "=r"( ulHartId ) );
|
||||||
pullMachineTimerCompareRegister = &( pullMachineTimerCompareRegisterBase[ ulHartId ] );
|
pullMachineTimerCompareRegister = ( volatile uint64_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) );
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -123,7 +135,7 @@ task stack, not the ISR stack). */
|
||||||
} while( ulCurrentTimeHigh != *pulTimeHigh );
|
} while( ulCurrentTimeHigh != *pulTimeHigh );
|
||||||
|
|
||||||
ullNextTime = ( uint64_t ) ulCurrentTimeHigh;
|
ullNextTime = ( uint64_t ) ulCurrentTimeHigh;
|
||||||
ullNextTime <<= 32ULL;
|
ullNextTime <<= 32ULL; /* High 4-byte word is 32-bits up. */
|
||||||
ullNextTime |= ( uint64_t ) ulCurrentTimeLow;
|
ullNextTime |= ( uint64_t ) ulCurrentTimeLow;
|
||||||
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
|
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
|
||||||
*pullMachineTimerCompareRegister = ullNextTime;
|
*pullMachineTimerCompareRegister = ullNextTime;
|
||||||
|
@ -132,7 +144,7 @@ task stack, not the ISR stack). */
|
||||||
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
|
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* ( configCLINT_BASE_ADDRESS != 0 ) */
|
#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIME_BASE_ADDRESS != 0 ) */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
BaseType_t xPortStartScheduler( void )
|
BaseType_t xPortStartScheduler( void )
|
||||||
|
@ -152,6 +164,12 @@ extern void xPortStartFirstTask( void );
|
||||||
stack that was being used by main() prior to the scheduler being
|
stack that was being used by main() prior to the scheduler being
|
||||||
started. */
|
started. */
|
||||||
configASSERT( ( xISRStackTop & portBYTE_ALIGNMENT_MASK ) == 0 );
|
configASSERT( ( xISRStackTop & portBYTE_ALIGNMENT_MASK ) == 0 );
|
||||||
|
|
||||||
|
#ifdef configISR_STACK_SIZE_WORDS
|
||||||
|
{
|
||||||
|
memset( ( void * ) xISRStack, portISR_STACK_FILL_BYTE, sizeof( xISRStack ) );
|
||||||
|
}
|
||||||
|
#endif /* configISR_STACK_SIZE_WORDS */
|
||||||
}
|
}
|
||||||
#endif /* configASSERT_DEFINED */
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
@ -160,7 +178,7 @@ extern void xPortStartFirstTask( void );
|
||||||
configure whichever clock is to be used to generate the tick interrupt. */
|
configure whichever clock is to be used to generate the tick interrupt. */
|
||||||
vPortSetupTimerInterrupt();
|
vPortSetupTimerInterrupt();
|
||||||
|
|
||||||
#if( configCLINT_BASE_ADDRESS != 0 )
|
#if( ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) )
|
||||||
{
|
{
|
||||||
/* Enable mtime and external interrupts. 1<<7 for timer interrupt, 1<<11
|
/* Enable mtime and external interrupts. 1<<7 for timer interrupt, 1<<11
|
||||||
for external interrupt. _RB_ What happens here when mtime is not present as
|
for external interrupt. _RB_ What happens here when mtime is not present as
|
||||||
|
@ -172,7 +190,7 @@ extern void xPortStartFirstTask( void );
|
||||||
/* Enable external interrupts. */
|
/* Enable external interrupts. */
|
||||||
__asm volatile( "csrs mie, %0" :: "r"(0x800) );
|
__asm volatile( "csrs mie, %0" :: "r"(0x800) );
|
||||||
}
|
}
|
||||||
#endif /* configCLINT_BASE_ADDRESS */
|
#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) */
|
||||||
|
|
||||||
xPortStartFirstTask();
|
xPortStartFirstTask();
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,17 @@
|
||||||
|
|
||||||
/* Check the freertos_risc_v_chip_specific_extensions.h and/or command line
|
/* Check the freertos_risc_v_chip_specific_extensions.h and/or command line
|
||||||
definitions. */
|
definitions. */
|
||||||
#ifndef portasmHAS_CLINT
|
#if defined( portasmHAS_CLINT ) && defined( portasmHAS_MTIME )
|
||||||
#error freertos_risc_v_chip_specific_extensions.h must define portasmHAS_CLINT to either 1 (CLINT present) or 0 (clint not present).
|
#error The portasmHAS_CLINT constant has been depracted. Please replace it with portasmHAS_CLINT. portasmHAS_CLINT and portasmHAS_MTIME cannot both be defined at once.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef portasmHAS_CLINT
|
||||||
|
#warning The portasmHAS_CLINT constant has been depracted. Please replace it with portasmHAS_CLINT. For now portasmHAS_MTIME is derived from portasmHAS_CLINT.
|
||||||
|
#define portasmHAS_MTIME portasmHAS_CLINT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef portasmHAS_MTIME
|
||||||
|
#error freertos_risc_v_chip_specific_extensions.h must define portasmHAS_MTIME to either 1 (MTIME clock present) or 0 (MTIME clock not present).
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef portasmHANDLE_INTERRUPT
|
#ifndef portasmHANDLE_INTERRUPT
|
||||||
|
@ -153,7 +162,7 @@ test_if_asynchronous:
|
||||||
|
|
||||||
handle_asynchronous:
|
handle_asynchronous:
|
||||||
|
|
||||||
#if( portasmHAS_CLINT != 0 )
|
#if( portasmHAS_MTIME != 0 )
|
||||||
|
|
||||||
test_if_mtimer: /* If there is a CLINT then the mtimer is used to generate the tick interrupt. */
|
test_if_mtimer: /* If there is a CLINT then the mtimer is used to generate the tick interrupt. */
|
||||||
|
|
||||||
|
@ -172,7 +181,7 @@ handle_asynchronous:
|
||||||
li t4, -1
|
li t4, -1
|
||||||
lw t2, 0(t1) /* Load the low word of ullNextTime into t2. */
|
lw t2, 0(t1) /* Load the low word of ullNextTime into t2. */
|
||||||
lw t3, 4(t1) /* Load the high word of ullNextTime into t3. */
|
lw t3, 4(t1) /* Load the high word of ullNextTime into t3. */
|
||||||
sw t4, 0(t0) /* Low word no smaller than old value. */
|
sw t4, 0(t0) /* Low word no smaller than old value to start with - will be overwritten below. */
|
||||||
sw t3, 4(t0) /* Store high word of ullNextTime into compare register. No smaller than new value. */
|
sw t3, 4(t0) /* Store high word of ullNextTime into compare register. No smaller than new value. */
|
||||||
sw t2, 0(t0) /* Store low word of ullNextTime into compare register. */
|
sw t2, 0(t0) /* Store low word of ullNextTime into compare register. */
|
||||||
lw t0, uxTimerIncrementsForOneTick /* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */
|
lw t0, uxTimerIncrementsForOneTick /* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */
|
||||||
|
@ -205,7 +214,7 @@ handle_asynchronous:
|
||||||
addi t1, t1, 4 /* 0x80000007 + 4 = 0x8000000b == Machine external interrupt. */
|
addi t1, t1, 4 /* 0x80000007 + 4 = 0x8000000b == Machine external interrupt. */
|
||||||
bne a0, t1, as_yet_unhandled /* Something as yet unhandled. */
|
bne a0, t1, as_yet_unhandled /* Something as yet unhandled. */
|
||||||
|
|
||||||
#endif /* portasmHAS_CLINT */
|
#endif /* portasmHAS_MTIME */
|
||||||
|
|
||||||
load_x sp, xISRStackTop /* Switch to ISR stack before function call. */
|
load_x sp, xISRStackTop /* Switch to ISR stack before function call. */
|
||||||
jal portasmHANDLE_INTERRUPT /* Jump to the interrupt handler if there is no CLINT or if there is a CLINT and it has been determined that an external interrupt is pending. */
|
jal portasmHANDLE_INTERRUPT /* Jump to the interrupt handler if there is no CLINT or if there is a CLINT and it has been determined that an external interrupt is pending. */
|
||||||
|
@ -223,11 +232,13 @@ test_if_environment_call:
|
||||||
j processed_source
|
j processed_source
|
||||||
|
|
||||||
is_exception:
|
is_exception:
|
||||||
ebreak
|
csrr t0, mcause /* For viewing in the debugger only. */
|
||||||
j is_exception
|
csrr t1, mepc /* For viewing in the debugger only */
|
||||||
|
csrr t2, mstatus
|
||||||
|
j is_exception /* No other exceptions handled yet. */
|
||||||
|
|
||||||
as_yet_unhandled:
|
as_yet_unhandled:
|
||||||
ebreak
|
csrr t0, mcause /* For viewing in the debugger only. */
|
||||||
j as_yet_unhandled
|
j as_yet_unhandled
|
||||||
|
|
||||||
processed_source:
|
processed_source:
|
||||||
|
@ -282,7 +293,7 @@ processed_source:
|
||||||
.func
|
.func
|
||||||
xPortStartFirstTask:
|
xPortStartFirstTask:
|
||||||
|
|
||||||
#if( portasmHAS_CLINT != 0 )
|
#if( portasmHAS_MTIME != 0 )
|
||||||
/* If there is a clint then interrupts can branch directly to the FreeRTOS
|
/* If there is a clint then interrupts can branch directly to the FreeRTOS
|
||||||
trap handler. Otherwise the interrupt controller will need to be configured
|
trap handler. Otherwise the interrupt controller will need to be configured
|
||||||
outside of this file. */
|
outside of this file. */
|
||||||
|
@ -298,6 +309,7 @@ xPortStartFirstTask:
|
||||||
portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
|
portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
|
||||||
|
|
||||||
load_x t0, 29 * portWORD_SIZE( sp ) /* mstatus */
|
load_x t0, 29 * portWORD_SIZE( sp ) /* mstatus */
|
||||||
|
addi t0, t0, 0x08 /* Set MIE bit so the first task starts with interrupts enabled - required as returns with ret not eret. */
|
||||||
csrrw x0, mstatus, t0 /* Interrupts enabled from here! */
|
csrrw x0, mstatus, t0 /* Interrupts enabled from here! */
|
||||||
|
|
||||||
load_x x5, 2 * portWORD_SIZE( sp ) /* t0 */
|
load_x x5, 2 * portWORD_SIZE( sp ) /* t0 */
|
||||||
|
|
|
@ -65,6 +65,13 @@ typedef portBASE_TYPE BaseType_t;
|
||||||
typedef portUBASE_TYPE UBaseType_t;
|
typedef portUBASE_TYPE UBaseType_t;
|
||||||
typedef portUBASE_TYPE TickType_t;
|
typedef portUBASE_TYPE TickType_t;
|
||||||
|
|
||||||
|
/* Legacy type definitions. */
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT float
|
||||||
|
#define portDOUBLE double
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT short
|
||||||
|
|
||||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||||
not need to be guarded with a critical section. */
|
not need to be guarded with a critical section. */
|
||||||
#define portTICK_TYPE_IS_ATOMIC 1
|
#define portTICK_TYPE_IS_ATOMIC 1
|
||||||
|
@ -146,6 +153,30 @@ not necessary for to use this port. They are defined so the common demo files
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
/* configCLINT_BASE_ADDRESS is a legacy definition that was replaced by the
|
||||||
|
configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS definitions. For
|
||||||
|
backward compatibility derive the newer definitions from the old if the old
|
||||||
|
definition is found. */
|
||||||
|
#if defined( configCLINT_BASE_ADDRESS ) && !defined( configMTIME_BASE_ADDRESS ) && ( configCLINT_BASE_ADDRESS == 0 )
|
||||||
|
/* Legacy case where configCLINT_BASE_ADDRESS was defined as 0 to indicate
|
||||||
|
there was no CLINT. Equivalent now is to set the MTIME and MTIMECMP
|
||||||
|
addresses to 0. */
|
||||||
|
#define configMTIME_BASE_ADDRESS ( 0 )
|
||||||
|
#define configMTIMECMP_BASE_ADDRESS ( 0 )
|
||||||
|
#elif defined( configCLINT_BASE_ADDRESS ) && !defined( configMTIME_BASE_ADDRESS )
|
||||||
|
/* Legacy case where configCLINT_BASE_ADDRESS was set to the base address of
|
||||||
|
the CLINT. Equivalent now is to derive the MTIME and MTIMECMP addresses
|
||||||
|
from the CLINT address. */
|
||||||
|
#define configMTIME_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0xBFF8UL )
|
||||||
|
#define configMTIMECMP_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0x4000UL )
|
||||||
|
#elif !defined( configMTIME_BASE_ADDRESS ) || !defined( configMTIMECMP_BASE_ADDRESS )
|
||||||
|
#error configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. Set them to zero if there is no MTIME (machine time) clock. See https://www.freertos.org/Using-FreeRTOS-on-RISC-V.html
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,13 +37,15 @@
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
/* Constants required to manipulate the NVIC. */
|
/* 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_SYSPRI2 ( ( volatile uint32_t *) 0xe000ed20 )
|
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||||
#define portNVIC_SYSTICK_CLK 0x00000004
|
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t *) 0xe000ed20 ) )
|
||||||
#define portNVIC_SYSTICK_INT 0x00000002
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
#define portNVIC_SYSTICK_ENABLE 0x00000001
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
#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 )
|
||||||
|
@ -62,10 +64,40 @@ FreeRTOS.org versions prior to V4.3.0 did not include this definition. */
|
||||||
variable. */
|
variable. */
|
||||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||||
|
|
||||||
|
/* The systick is a 24-bit counter. */
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/* A fiddle factor to estimate the number of SysTick counts that would have
|
||||||
|
occurred while the SysTick counter is stopped during tickless idle
|
||||||
|
calculations. */
|
||||||
|
#ifndef portMISSED_COUNTS_FACTOR
|
||||||
|
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The number of SysTick increments that make up one tick period. */
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/* The maximum number of tick periods that can be suppressed is limited by the
|
||||||
|
24 bit resolution of the SysTick timer. */
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/* Compensate for the CPU cycles that pass while the SysTick is stopped (low
|
||||||
|
power functionality only. */
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
static uint32_t ulStoppedTimerCompensation = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup the timer to generate the tick interrupts.
|
* Setup the timer to generate the tick interrupts. The implementation in this
|
||||||
|
* file is weak to allow application writers to change the timer used to
|
||||||
|
* generate the tick interrupt.
|
||||||
*/
|
*/
|
||||||
static void prvSetupTimerInterrupt( void );
|
#pragma weak vPortSetupTimerInterrupt
|
||||||
|
void vPortSetupTimerInterrupt( void );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exception handlers.
|
* Exception handlers.
|
||||||
|
@ -125,12 +157,12 @@ static void prvTaskExitError( void )
|
||||||
BaseType_t xPortStartScheduler( void )
|
BaseType_t xPortStartScheduler( void )
|
||||||
{
|
{
|
||||||
/* Make PendSV and SysTick the lowest priority interrupts. */
|
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||||
*(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
*(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||||
here already. */
|
here already. */
|
||||||
prvSetupTimerInterrupt();
|
vPortSetupTimerInterrupt();
|
||||||
|
|
||||||
/* Initialise the critical nesting count ready for the first task. */
|
/* Initialise the critical nesting count ready for the first task. */
|
||||||
uxCriticalNesting = 0;
|
uxCriticalNesting = 0;
|
||||||
|
@ -154,7 +186,7 @@ void vPortEndScheduler( void )
|
||||||
void vPortYield( void )
|
void vPortYield( void )
|
||||||
{
|
{
|
||||||
/* 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;
|
||||||
|
|
||||||
/* Barriers are normally not required but do ensure the code is completely
|
/* Barriers are normally not required but do ensure the code is completely
|
||||||
within the specified behaviour for the architecture. */
|
within the specified behaviour for the architecture. */
|
||||||
|
@ -193,7 +225,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||||
|
@ -204,15 +236,189 @@ uint32_t ulPreviousMask;
|
||||||
* Setup the systick timer to generate the tick interrupts at the required
|
* Setup the systick timer to generate the tick interrupts at the required
|
||||||
* frequency.
|
* frequency.
|
||||||
*/
|
*/
|
||||||
static void prvSetupTimerInterrupt( void )
|
void vPortSetupTimerInterrupt( void )
|
||||||
{
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
{
|
||||||
|
ulTimerCountsForOneTick = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR;
|
||||||
|
}
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
/* Stop and reset the SysTick. */
|
/* 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;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
|
||||||
|
__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. */
|
||||||
|
__disable_interrupt();
|
||||||
|
__DSB();
|
||||||
|
__ISB();
|
||||||
|
|
||||||
|
/* If a context switch is pending or a task is waiting for the scheduler
|
||||||
|
to be unsuspended then abandon the low power entry. */
|
||||||
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above __disable_interrupt()
|
||||||
|
call above. */
|
||||||
|
__enable_interrupt();
|
||||||
|
}
|
||||||
|
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 )
|
||||||
|
{
|
||||||
|
__DSB();
|
||||||
|
__WFI();
|
||||||
|
__ISB();
|
||||||
|
}
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||||
|
out of sleep mode to execute immediately. see comments above
|
||||||
|
__disable_interrupt() call above. */
|
||||||
|
__enable_interrupt();
|
||||||
|
__DSB();
|
||||||
|
__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. */
|
||||||
|
__disable_interrupt();
|
||||||
|
__DSB();
|
||||||
|
__ISB();
|
||||||
|
|
||||||
|
/* Disable the SysTick clock without reading the
|
||||||
|
portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||||
|
portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
|
||||||
|
the time the SysTick is stopped for is accounted for as best it can
|
||||||
|
be, but using the tickless mode will inevitably result in some tiny
|
||||||
|
drift of the time maintained by the kernel with respect to calendar
|
||||||
|
time*/
|
||||||
|
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
|
||||||
|
|
||||||
|
/* Determine if the SysTick clock has already counted to zero and
|
||||||
|
been set back to the current reload value (the reload back being
|
||||||
|
correct for the entire expected idle time) or if the SysTick is yet
|
||||||
|
to count to zero (in which case an interrupt other than the SysTick
|
||||||
|
must have brought the system out of sleep mode). */
|
||||||
|
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||||
|
{
|
||||||
|
uint32_t ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* The tick interrupt is already pending, and the SysTick count
|
||||||
|
reloaded with ulReloadValue. Reset the
|
||||||
|
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||||
|
period. */
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||||
|
|
||||||
|
/* Don't allow a tiny value, or values that have somehow
|
||||||
|
underflowed because the post sleep hook did something
|
||||||
|
that took too long. */
|
||||||
|
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||||
|
{
|
||||||
|
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||||
|
}
|
||||||
|
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||||
|
|
||||||
|
/* As the pending tick will be processed as soon as this
|
||||||
|
function exits, the tick value maintained by the tick is stepped
|
||||||
|
forward by one less than the time spent waiting. */
|
||||||
|
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something other than the tick interrupt ended the sleep.
|
||||||
|
Work out how long the sleep lasted rounded to complete tick
|
||||||
|
periods (not the ulReload value which accounted for part
|
||||||
|
ticks). */
|
||||||
|
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG ;
|
||||||
|
|
||||||
|
/* How many complete tick periods passed while the processor
|
||||||
|
was waiting? */
|
||||||
|
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||||
|
|
||||||
|
/* The reload value is set to whatever fraction of a single tick
|
||||||
|
period remains. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||||
|
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||||
|
value. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Exit with interrpts enabled. */
|
||||||
|
__enable_interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
|
@ -103,6 +103,13 @@ extern void vClearInterruptMaskFromISR( uint32_t ulMask );
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Tickless idle/low power functionality. */
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
|
|
@ -292,6 +292,13 @@ typedef struct MPU_SETTINGS
|
||||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
* the source code because to do so would cause other compilers to generate
|
||||||
|
* warnings. */
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -292,6 +292,13 @@ typedef struct MPU_SETTINGS
|
||||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
* the source code because to do so would cause other compilers to generate
|
||||||
|
* warnings. */
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -164,6 +164,34 @@ not necessary for to use this port. They are defined so the common demo files
|
||||||
/* portNOP() is not required by this port. */
|
/* portNOP() is not required by this port. */
|
||||||
#define portNOP()
|
#define portNOP()
|
||||||
|
|
||||||
|
#define portINLINE __inline
|
||||||
|
|
||||||
|
#ifndef portFORCE_INLINE
|
||||||
|
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrentInterrupt;
|
||||||
|
BaseType_t xReturn;
|
||||||
|
|
||||||
|
/* Obtain the number of the currently executing interrupt. */
|
||||||
|
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||||
|
|
||||||
|
if( ulCurrentInterrupt == 0 )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
|
|
@ -292,6 +292,13 @@ typedef struct MPU_SETTINGS
|
||||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
* the source code because to do so would cause other compilers to generate
|
||||||
|
* warnings. */
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -292,6 +292,13 @@ typedef struct MPU_SETTINGS
|
||||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
* the source code because to do so would cause other compilers to generate
|
||||||
|
* warnings. */
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
#pragma diag_suppress=Pa082
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -77,6 +77,12 @@ typedef unsigned long UBaseType_t;
|
||||||
#define portBYTE_ALIGNMENT 8
|
#define portBYTE_ALIGNMENT 8
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Compiler directives. */
|
||||||
|
#define portWEAK_SYMBOL __attribute__( ( weak ) )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
/* Scheduler utilities. */
|
/* Scheduler utilities. */
|
||||||
#define portYIELD() \
|
#define portYIELD() \
|
||||||
{ \
|
{ \
|
||||||
|
@ -157,6 +163,34 @@ not necessary for to use this port. They are defined so the common demo files
|
||||||
/* portNOP() is not required by this port. */
|
/* portNOP() is not required by this port. */
|
||||||
#define portNOP()
|
#define portNOP()
|
||||||
|
|
||||||
|
#define portINLINE __inline
|
||||||
|
|
||||||
|
#ifndef portFORCE_INLINE
|
||||||
|
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrentInterrupt;
|
||||||
|
BaseType_t xReturn;
|
||||||
|
|
||||||
|
/* Obtain the number of the currently executing interrupt. */
|
||||||
|
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||||
|
|
||||||
|
if( ulCurrentInterrupt == 0 )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
|
|
@ -33,8 +33,8 @@
|
||||||
#include <intrinsics.h>
|
#include <intrinsics.h>
|
||||||
|
|
||||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||||
all the API functions to use the MPU wrappers. That should only be done when
|
* all the API functions to use the MPU wrappers. That should only be done when
|
||||||
task.h is included from an application file. */
|
* task.h is included from an application file. */
|
||||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
/* Scheduler includes. */
|
/* Scheduler includes. */
|
||||||
|
@ -43,8 +43,6 @@ task.h is included from an application file. */
|
||||||
|
|
||||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
#warning This is not yet a documented port as it has not been fully tested, so no demo projects that use this port are provided.
|
|
||||||
|
|
||||||
#ifndef __ARMVFP__
|
#ifndef __ARMVFP__
|
||||||
#error This port can only be used when the project options are configured to enable hardware floating point support.
|
#error This port can only be used when the project options are configured to enable hardware floating point support.
|
||||||
#endif
|
#endif
|
||||||
|
@ -94,7 +92,7 @@ task.h is included from an application file. */
|
||||||
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
|
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
|
||||||
|
|
||||||
/* Constants used to detect a Cortex-M7 r0p1 core, which should use the ARM_CM7
|
/* Constants used to detect a Cortex-M7 r0p1 core, which should use the ARM_CM7
|
||||||
r0p1 port. */
|
* r0p1 port. */
|
||||||
#define portCPUID ( * ( ( volatile uint32_t * ) 0xE000ed00 ) )
|
#define portCPUID ( * ( ( volatile uint32_t * ) 0xE000ed00 ) )
|
||||||
#define portCORTEX_M7_r0p1_ID ( 0x410FC271UL )
|
#define portCORTEX_M7_r0p1_ID ( 0x410FC271UL )
|
||||||
#define portCORTEX_M7_r0p0_ID ( 0x410FC270UL )
|
#define portCORTEX_M7_r0p0_ID ( 0x410FC270UL )
|
||||||
|
@ -222,10 +220,10 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged )
|
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged )
|
||||||
{
|
{
|
||||||
/* Simulate the stack frame as it would be created by a context switch
|
/* Simulate the stack frame as it would be created by a context switch
|
||||||
interrupt. */
|
* interrupt. */
|
||||||
|
|
||||||
/* Offset added to account for the way the MCU uses the stack on entry/exit
|
/* Offset added to account for the way the MCU uses the stack on entry/exit
|
||||||
of interrupts, and to ensure alignment. */
|
* of interrupts, and to ensure alignment. */
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
|
|
||||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||||
|
@ -239,7 +237,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
|
||||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||||
|
|
||||||
/* A save method is being used that requires each task to maintain its
|
/* A save method is being used that requires each task to maintain its
|
||||||
own exec return value. */
|
* own exec return value. */
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
*pxTopOfStack = portINITIAL_EXC_RETURN;
|
*pxTopOfStack = portINITIAL_EXC_RETURN;
|
||||||
|
|
||||||
|
@ -261,10 +259,16 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
|
||||||
void vPortSVCHandler_C( uint32_t *pulParam )
|
void vPortSVCHandler_C( uint32_t *pulParam )
|
||||||
{
|
{
|
||||||
uint8_t ucSVCNumber;
|
uint8_t ucSVCNumber;
|
||||||
|
uint32_t ulPC;
|
||||||
|
#if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )
|
||||||
|
extern uint32_t __syscalls_flash_start__[];
|
||||||
|
extern uint32_t __syscalls_flash_end__[];
|
||||||
|
#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
|
||||||
|
|
||||||
/* The stack contains: r0, r1, r2, r3, r12, r14, the return address and
|
/* The stack contains: r0, r1, r2, r3, r12, LR, PC and xPSR. The first
|
||||||
xPSR. The first argument (r0) is pulParam[ 0 ]. */
|
* argument (r0) is pulParam[ 0 ]. */
|
||||||
ucSVCNumber = ( ( uint8_t * ) pulParam[ portOFFSET_TO_PC ] )[ -2 ];
|
ulPC = pulParam[ portOFFSET_TO_PC ];
|
||||||
|
ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ];
|
||||||
switch( ucSVCNumber )
|
switch( ucSVCNumber )
|
||||||
{
|
{
|
||||||
case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI;
|
case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI;
|
||||||
|
@ -273,14 +277,31 @@ uint8_t ucSVCNumber;
|
||||||
|
|
||||||
case portSVC_YIELD : portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
case portSVC_YIELD : portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
/* Barriers are normally not required
|
/* Barriers are normally not required
|
||||||
but do ensure the code is completely
|
* but do ensure the code is completely
|
||||||
within the specified behaviour for the
|
* within the specified behaviour for the
|
||||||
architecture. */
|
* architecture. */
|
||||||
__asm volatile( "dsb" ::: "memory" );
|
__asm volatile( "dsb" ::: "memory" );
|
||||||
__asm volatile( "isb" );
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )
|
||||||
|
case portSVC_RAISE_PRIVILEGE : /* Only raise the privilege, if the
|
||||||
|
* svc was raised from any of the
|
||||||
|
* system calls. */
|
||||||
|
if( ulPC >= ( uint32_t ) __syscalls_flash_start__ &&
|
||||||
|
ulPC <= ( uint32_t ) __syscalls_flash_end__ )
|
||||||
|
{
|
||||||
|
__asm volatile
|
||||||
|
(
|
||||||
|
" mrs r1, control \n" /* Obtain current control value. */
|
||||||
|
" bic r1, r1, #1 \n" /* Set privilege bit. */
|
||||||
|
" msr control, r1 \n" /* Write back new control value. */
|
||||||
|
::: "r1", "memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#else
|
||||||
case portSVC_RAISE_PRIVILEGE : __asm volatile
|
case portSVC_RAISE_PRIVILEGE : __asm volatile
|
||||||
(
|
(
|
||||||
" mrs r1, control \n" /* Obtain current control value. */
|
" mrs r1, control \n" /* Obtain current control value. */
|
||||||
|
@ -289,6 +310,7 @@ uint8_t ucSVCNumber;
|
||||||
::: "r1", "memory"
|
::: "r1", "memory"
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
|
||||||
|
|
||||||
default : /* Unknown SVC call. */
|
default : /* Unknown SVC call. */
|
||||||
break;
|
break;
|
||||||
|
@ -302,12 +324,12 @@ uint8_t ucSVCNumber;
|
||||||
BaseType_t xPortStartScheduler( void )
|
BaseType_t xPortStartScheduler( void )
|
||||||
{
|
{
|
||||||
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
|
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
|
||||||
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
* See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
||||||
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
|
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
|
||||||
|
|
||||||
/* This port can be used on all revisions of the Cortex-M7 core other than
|
/* This port can be used on all revisions of the Cortex-M7 core other than
|
||||||
the r0p1 parts. r0p1 parts should use the port from the
|
* the r0p1 parts. r0p1 parts should use the port from the
|
||||||
/source/portable/GCC/ARM_CM7/r0p1 directory. */
|
* /source/portable/GCC/ARM_CM7/r0p1 directory. */
|
||||||
configASSERT( portCPUID != portCORTEX_M7_r0p1_ID );
|
configASSERT( portCPUID != portCORTEX_M7_r0p1_ID );
|
||||||
configASSERT( portCPUID != portCORTEX_M7_r0p0_ID );
|
configASSERT( portCPUID != portCORTEX_M7_r0p0_ID );
|
||||||
|
|
||||||
|
@ -318,15 +340,15 @@ BaseType_t xPortStartScheduler( void )
|
||||||
volatile uint8_t ucMaxPriorityValue;
|
volatile uint8_t ucMaxPriorityValue;
|
||||||
|
|
||||||
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||||
functions can be called. ISR safe functions are those that end in
|
* functions can be called. ISR safe functions are those that end in
|
||||||
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||||
ensure interrupt entry is as fast and simple as possible.
|
* ensure interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
Save the interrupt priority value that is about to be clobbered. */
|
Save the interrupt priority value that is about to be clobbered. */
|
||||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||||
|
|
||||||
/* Determine the number of priority bits available. First write to all
|
/* Determine the number of priority bits available. First write to all
|
||||||
possible bits. */
|
* possible bits. */
|
||||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||||
|
|
||||||
/* Read the value back to see how many bits stuck. */
|
/* Read the value back to see how many bits stuck. */
|
||||||
|
@ -336,7 +358,7 @@ BaseType_t xPortStartScheduler( void )
|
||||||
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||||
|
|
||||||
/* Calculate the maximum acceptable priority group value for the number
|
/* Calculate the maximum acceptable priority group value for the number
|
||||||
of bits read back. */
|
* of bits read back. */
|
||||||
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
||||||
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||||
{
|
{
|
||||||
|
@ -347,8 +369,8 @@ BaseType_t xPortStartScheduler( void )
|
||||||
#ifdef __NVIC_PRIO_BITS
|
#ifdef __NVIC_PRIO_BITS
|
||||||
{
|
{
|
||||||
/* Check the CMSIS configuration that defines the number of
|
/* Check the CMSIS configuration that defines the number of
|
||||||
priority bits matches the number of priority bits actually queried
|
* priority bits matches the number of priority bits actually queried
|
||||||
from the hardware. */
|
* from the hardware. */
|
||||||
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
|
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -356,19 +378,19 @@ BaseType_t xPortStartScheduler( void )
|
||||||
#ifdef configPRIO_BITS
|
#ifdef configPRIO_BITS
|
||||||
{
|
{
|
||||||
/* Check the FreeRTOS configuration that defines the number of
|
/* Check the FreeRTOS configuration that defines the number of
|
||||||
priority bits matches the number of priority bits actually queried
|
* priority bits matches the number of priority bits actually queried
|
||||||
from the hardware. */
|
* from the hardware. */
|
||||||
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
|
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Shift the priority group value back to its position within the AIRCR
|
/* Shift the priority group value back to its position within the AIRCR
|
||||||
register. */
|
* register. */
|
||||||
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||||
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||||
|
|
||||||
/* Restore the clobbered interrupt priority register to its original
|
/* Restore the clobbered interrupt priority register to its original
|
||||||
value. */
|
* value. */
|
||||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||||
}
|
}
|
||||||
#endif /* conifgASSERT_DEFINED */
|
#endif /* conifgASSERT_DEFINED */
|
||||||
|
@ -381,7 +403,7 @@ BaseType_t xPortStartScheduler( void )
|
||||||
prvSetupMPU();
|
prvSetupMPU();
|
||||||
|
|
||||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||||
here already. */
|
* here already. */
|
||||||
vPortSetupTimerInterrupt();
|
vPortSetupTimerInterrupt();
|
||||||
|
|
||||||
/* Initialise the critical nesting count ready for the first task. */
|
/* Initialise the critical nesting count ready for the first task. */
|
||||||
|
@ -404,7 +426,7 @@ BaseType_t xPortStartScheduler( void )
|
||||||
void vPortEndScheduler( void )
|
void vPortEndScheduler( void )
|
||||||
{
|
{
|
||||||
/* Not implemented in ports where there is nothing to return to.
|
/* Not implemented in ports where there is nothing to return to.
|
||||||
Artificially force an assert. */
|
* Artificially force an assert. */
|
||||||
configASSERT( uxCriticalNesting == 1000UL );
|
configASSERT( uxCriticalNesting == 1000UL );
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
@ -419,10 +441,10 @@ void vPortEnterCritical( void )
|
||||||
vPortResetPrivilege( xRunningPrivileged );
|
vPortResetPrivilege( xRunningPrivileged );
|
||||||
|
|
||||||
/* This is not the interrupt safe version of the enter critical function so
|
/* This is not the interrupt safe version of the enter critical function so
|
||||||
assert() if it is being called from an interrupt context. Only API
|
* assert() if it is being called from an interrupt context. Only API
|
||||||
functions that end in "FromISR" can be used in an interrupt. Only assert if
|
* functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||||
the critical nesting count is 1 to protect against recursive calls if the
|
* the critical nesting count is 1 to protect against recursive calls if the
|
||||||
assert function also uses a critical section. */
|
* assert function also uses a critical section. */
|
||||||
if( uxCriticalNesting == 1 )
|
if( uxCriticalNesting == 1 )
|
||||||
{
|
{
|
||||||
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
||||||
|
@ -449,16 +471,16 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
|
||||||
void xPortSysTickHandler( void )
|
void xPortSysTickHandler( void )
|
||||||
{
|
{
|
||||||
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
|
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
|
||||||
executes all interrupts must be unmasked. There is therefore no need to
|
* executes all interrupts must be unmasked. There is therefore no need to
|
||||||
save and then restore the interrupt mask value as its value is already
|
* save and then restore the interrupt mask value as its value is already
|
||||||
known. */
|
* known. */
|
||||||
portDISABLE_INTERRUPTS();
|
portDISABLE_INTERRUPTS();
|
||||||
{
|
{
|
||||||
/* Increment the RTOS tick. */
|
/* Increment the RTOS tick. */
|
||||||
if( xTaskIncrementTick() != pdFALSE )
|
if( xTaskIncrementTick() != pdFALSE )
|
||||||
{
|
{
|
||||||
/* A context switch is required. Context switching is performed in
|
/* A context switch is required. Context switching is performed in
|
||||||
the PendSV interrupt. Pend the PendSV interrupt. */
|
* the PendSV interrupt. Pend the PendSV interrupt. */
|
||||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -504,8 +526,8 @@ extern uint32_t __privileged_data_end__[];
|
||||||
( portMPU_REGION_ENABLE );
|
( portMPU_REGION_ENABLE );
|
||||||
|
|
||||||
/* Setup the first 16K for privileged only access (even though less
|
/* Setup the first 16K for privileged only access (even though less
|
||||||
than 10K is actually being used). This is where the kernel code is
|
* than 10K is actually being used). This is where the kernel code is
|
||||||
placed. */
|
* placed. */
|
||||||
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 ) |
|
||||||
( portPRIVILEGED_FLASH_REGION );
|
( portPRIVILEGED_FLASH_REGION );
|
||||||
|
@ -516,7 +538,7 @@ extern uint32_t __privileged_data_end__[];
|
||||||
( 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
|
||||||
is placed. */
|
* is placed. */
|
||||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
( portPRIVILEGED_RAM_REGION );
|
( portPRIVILEGED_RAM_REGION );
|
||||||
|
@ -527,7 +549,7 @@ extern uint32_t __privileged_data_end__[];
|
||||||
( portMPU_REGION_ENABLE );
|
( portMPU_REGION_ENABLE );
|
||||||
|
|
||||||
/* By default allow everything to access the general peripherals. The
|
/* By default allow everything to access the general peripherals. The
|
||||||
system peripherals and registers are protected. */
|
* system peripherals and registers are protected. */
|
||||||
portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) |
|
portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) |
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
( portGENERAL_PERIPHERALS_REGION );
|
( portGENERAL_PERIPHERALS_REGION );
|
||||||
|
@ -550,7 +572,7 @@ static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes )
|
||||||
uint32_t ulRegionSize, ulReturnValue = 4;
|
uint32_t ulRegionSize, ulReturnValue = 4;
|
||||||
|
|
||||||
/* 32 is the smallest region size, 31 is the largest valid value for
|
/* 32 is the smallest region size, 31 is the largest valid value for
|
||||||
ulReturnValue. */
|
* ulReturnValue. */
|
||||||
for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) )
|
for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) )
|
||||||
{
|
{
|
||||||
if( ulActualSizeInBytes <= ulRegionSize )
|
if( ulActualSizeInBytes <= ulRegionSize )
|
||||||
|
@ -564,7 +586,7 @@ uint32_t ulRegionSize, ulReturnValue = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shift the code by one before returning so it can be written directly
|
/* Shift the code by one before returning so it can be written directly
|
||||||
into the the correct bit position of the attribute register. */
|
* into the the correct bit position of the attribute register. */
|
||||||
return ( ulReturnValue << 1UL );
|
return ( ulReturnValue << 1UL );
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
@ -593,7 +615,7 @@ uint32_t ul;
|
||||||
( portMPU_REGION_ENABLE );
|
( portMPU_REGION_ENABLE );
|
||||||
|
|
||||||
/* Re-instate the privileged only RAM region as xRegion[ 0 ] will have
|
/* Re-instate the privileged only RAM region as xRegion[ 0 ] will have
|
||||||
just removed the privileged only parameters. */
|
* just removed the privileged only parameters. */
|
||||||
xMPUSettings->xRegion[ 1 ].ulRegionBaseAddress =
|
xMPUSettings->xRegion[ 1 ].ulRegionBaseAddress =
|
||||||
( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
|
@ -615,9 +637,9 @@ uint32_t ul;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* This function is called automatically when the task is created - in
|
/* This function is called automatically when the task is created - in
|
||||||
which case the stack region parameters will be valid. At all other
|
* which case the stack region parameters will be valid. At all other
|
||||||
times the stack parameters will not be valid and it is assumed that the
|
* times the stack parameters will not be valid and it is assumed that the
|
||||||
stack region has already been configured. */
|
* stack region has already been configured. */
|
||||||
if( ulStackDepth > 0 )
|
if( ulStackDepth > 0 )
|
||||||
{
|
{
|
||||||
/* Define the region that allows access to the stack. */
|
/* Define the region that allows access to the stack. */
|
||||||
|
@ -640,8 +662,8 @@ uint32_t ul;
|
||||||
if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL )
|
if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL )
|
||||||
{
|
{
|
||||||
/* Translate the generic region definition contained in
|
/* Translate the generic region definition contained in
|
||||||
xRegions into the CM3 specific MPU settings that are then
|
* xRegions into the CM3 specific MPU settings that are then
|
||||||
stored in xMPUSettings. */
|
* stored in xMPUSettings. */
|
||||||
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress =
|
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress =
|
||||||
( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) |
|
( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) |
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
|
@ -682,66 +704,46 @@ uint32_t ul;
|
||||||
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||||
|
|
||||||
/* The following assertion will fail if a service routine (ISR) for
|
/* The following assertion will fail if a service routine (ISR) for
|
||||||
an interrupt that has been assigned a priority above
|
* an interrupt that has been assigned a priority above
|
||||||
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||||
function. ISR safe FreeRTOS API functions must *only* be called
|
* function. ISR safe FreeRTOS API functions must *only* be called
|
||||||
from interrupts that have been assigned a priority at or below
|
* from interrupts that have been assigned a priority at or below
|
||||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
Numerically low interrupt priority numbers represent logically high
|
* Numerically low interrupt priority numbers represent logically high
|
||||||
interrupt priorities, therefore the priority of the interrupt must
|
* interrupt priorities, therefore the priority of the interrupt must
|
||||||
be set to a value equal to or numerically *higher* than
|
* be set to a value equal to or numerically *higher* than
|
||||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
Interrupts that use the FreeRTOS API must not be left at their
|
* Interrupts that use the FreeRTOS API must not be left at their
|
||||||
default priority of zero as that is the highest possible priority,
|
* default priority of zero as that is the highest possible priority,
|
||||||
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
* which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||||
and therefore also guaranteed to be invalid.
|
* and therefore also guaranteed to be invalid.
|
||||||
|
|
||||||
FreeRTOS maintains separate thread and ISR API functions to ensure
|
* FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||||
interrupt entry is as fast and simple as possible.
|
* interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
The following links provide detailed information:
|
* The following links provide detailed information:
|
||||||
http://www.freertos.org/RTOS-Cortex-M3-M4.html
|
* http://www.freertos.org/RTOS-Cortex-M3-M4.html
|
||||||
http://www.freertos.org/FAQHelp.html */
|
* http://www.freertos.org/FAQHelp.html */
|
||||||
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
||||||
that define each interrupt's priority to be split between bits that
|
* that define each interrupt's priority to be split between bits that
|
||||||
define the interrupt's pre-emption priority bits and bits that define
|
* define the interrupt's pre-emption priority bits and bits that define
|
||||||
the interrupt's sub-priority. For simplicity all bits must be defined
|
* the interrupt's sub-priority. For simplicity all bits must be defined
|
||||||
to be pre-emption priority bits. The following assertion will fail if
|
* to be pre-emption priority bits. The following assertion will fail if
|
||||||
this is not the case (if some bits represent a sub-priority).
|
* this is not the case (if some bits represent a sub-priority).
|
||||||
|
|
||||||
If the application only uses CMSIS libraries for interrupt
|
* If the application only uses CMSIS libraries for interrupt
|
||||||
configuration then the correct setting can be achieved on all Cortex-M
|
* configuration then the correct setting can be achieved on all Cortex-M
|
||||||
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
* devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||||
scheduler. Note however that some vendor specific peripheral libraries
|
* scheduler. Note however that some vendor specific peripheral libraries
|
||||||
assume a non-zero priority group setting, in which cases using a value
|
* assume a non-zero priority group setting, in which cases using a value
|
||||||
of zero will result in unpredictable behaviour. */
|
* of zero will result in unpredictable behaviour. */
|
||||||
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* configASSERT_DEFINED */
|
#endif /* configASSERT_DEFINED */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -78,12 +78,26 @@ xPortPendSVHandler:
|
||||||
ldr r0, [r1]
|
ldr r0, [r1]
|
||||||
/* Move onto the second item in the TCB... */
|
/* Move onto the second item in the TCB... */
|
||||||
add r1, r1, #4
|
add r1, r1, #4
|
||||||
|
|
||||||
|
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
|
||||||
|
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||||
|
bic r3, r3, #1 /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
|
||||||
|
str r3, [r2] /* Disable MPU. */
|
||||||
|
|
||||||
/* Region Base Address register. */
|
/* Region Base Address register. */
|
||||||
ldr r2, =0xe000ed9c
|
ldr r2, =0xe000ed9c
|
||||||
/* Read 4 sets of MPU registers. */
|
/* Read 4 sets of MPU registers. */
|
||||||
ldmia r1!, {r4-r11}
|
ldmia r1!, {r4-r11}
|
||||||
/* Write 4 sets of MPU registers. */
|
/* Write 4 sets of MPU registers. */
|
||||||
stmia r2!, {r4-r11}
|
stmia r2!, {r4-r11}
|
||||||
|
|
||||||
|
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
|
||||||
|
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||||
|
orr r3, r3, #1 /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
|
||||||
|
str r3, [r2] /* Enable MPU. */
|
||||||
|
dsb /* Force memory writes before continuing. */
|
||||||
|
|
||||||
/* Pop the registers that are not automatically saved on exception entry. */
|
/* Pop the registers that are not automatically saved on exception entry. */
|
||||||
ldmia r0!, {r3-r11, r14}
|
ldmia r0!, {r3-r11, r14}
|
||||||
msr control, r3
|
msr control, r3
|
||||||
|
@ -151,12 +165,26 @@ vPortRestoreContextOfFirstTask:
|
||||||
ldr r0, [r1]
|
ldr r0, [r1]
|
||||||
/* Move onto the second item in the TCB... */
|
/* Move onto the second item in the TCB... */
|
||||||
add r1, r1, #4
|
add r1, r1, #4
|
||||||
|
|
||||||
|
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
|
||||||
|
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||||
|
bic r3, r3, #1 /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
|
||||||
|
str r3, [r2] /* Disable MPU. */
|
||||||
|
|
||||||
/* Region Base Address register. */
|
/* Region Base Address register. */
|
||||||
ldr r2, =0xe000ed9c
|
ldr r2, =0xe000ed9c
|
||||||
/* Read 4 sets of MPU registers. */
|
/* Read 4 sets of MPU registers. */
|
||||||
ldmia r1!, {r4-r11}
|
ldmia r1!, {r4-r11}
|
||||||
/* Write 4 sets of MPU registers. */
|
/* Write 4 sets of MPU registers. */
|
||||||
stmia r2!, {r4-r11}
|
stmia r2!, {r4-r11}
|
||||||
|
|
||||||
|
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
|
||||||
|
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||||
|
orr r3, r3, #1 /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
|
||||||
|
str r3, [r2] /* Enable MPU. */
|
||||||
|
dsb /* Force memory writes before continuing. */
|
||||||
|
|
||||||
/* Pop the registers that are not automatically saved on exception entry. */
|
/* Pop the registers that are not automatically saved on exception entry. */
|
||||||
ldmia r0!, {r3-r11, r14}
|
ldmia r0!, {r3-r11, r14}
|
||||||
msr control, r3
|
msr control, r3
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
* 1 tab == 4 spaces!
|
* 1 tab == 4 spaces!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef PORTMACRO_H
|
#ifndef PORTMACRO_H
|
||||||
#define PORTMACRO_H
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
@ -79,6 +80,7 @@ typedef unsigned long UBaseType_t;
|
||||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
|
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
|
||||||
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
|
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
|
||||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
|
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
|
||||||
|
#define portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ( 0x02UL << 24UL )
|
||||||
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
|
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
|
||||||
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
|
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
|
||||||
|
|
||||||
|
@ -106,7 +108,6 @@ typedef struct MPU_SETTINGS
|
||||||
xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS ];
|
xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS ];
|
||||||
} xMPU_SETTINGS;
|
} xMPU_SETTINGS;
|
||||||
|
|
||||||
|
|
||||||
/* Architecture specifics. */
|
/* Architecture specifics. */
|
||||||
#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 )
|
||||||
|
@ -119,6 +120,7 @@ typedef struct MPU_SETTINGS
|
||||||
#define portSVC_RAISE_PRIVILEGE 2
|
#define portSVC_RAISE_PRIVILEGE 2
|
||||||
|
|
||||||
/* Scheduler utilities. */
|
/* Scheduler utilities. */
|
||||||
|
|
||||||
#define portYIELD() __asm volatile ( " SVC %0 \n" :: "i" (portSVC_YIELD) : "memory" )
|
#define portYIELD() __asm volatile ( " SVC %0 \n" :: "i" (portSVC_YIELD) : "memory" )
|
||||||
#define portYIELD_WITHIN_API() \
|
#define portYIELD_WITHIN_API() \
|
||||||
{ \
|
{ \
|
||||||
|
@ -132,7 +134,6 @@ typedef struct MPU_SETTINGS
|
||||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD_WITHIN_API()
|
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD_WITHIN_API()
|
||||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Architecture specific optimisations. */
|
/* Architecture specific optimisations. */
|
||||||
|
@ -190,6 +191,36 @@ not necessary for to use this port. They are defined so the common demo files
|
||||||
|
|
||||||
/* portNOP() is not required by this port. */
|
/* portNOP() is not required by this port. */
|
||||||
#define portNOP()
|
#define portNOP()
|
||||||
|
|
||||||
|
#define portINLINE __inline
|
||||||
|
|
||||||
|
#ifndef portFORCE_INLINE
|
||||||
|
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrentInterrupt;
|
||||||
|
BaseType_t xReturn;
|
||||||
|
|
||||||
|
/* Obtain the number of the currently executing interrupt. */
|
||||||
|
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||||
|
|
||||||
|
if( ulCurrentInterrupt == 0 )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
extern BaseType_t xIsPrivileged( void );
|
extern BaseType_t xIsPrivileged( void );
|
||||||
|
@ -214,11 +245,19 @@ extern void vResetPrivilege( void );
|
||||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY
|
||||||
|
#warning "configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY is not defined. We recommend defining it to 1 in FreeRTOSConfig.h for better security."
|
||||||
|
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 0
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
the source code because to do so would cause other compilers to generate
|
the source code because to do so would cause other compilers to generate
|
||||||
warnings. */
|
warnings. */
|
||||||
#pragma diag_suppress=Pe191
|
#pragma diag_suppress=Pe191
|
||||||
#pragma diag_suppress=Pa082
|
#pragma diag_suppress=Pa082
|
||||||
|
#pragma diag_suppress=Be006
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,12 @@ typedef unsigned long UBaseType_t;
|
||||||
#define portBYTE_ALIGNMENT 8
|
#define portBYTE_ALIGNMENT 8
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Compiler directives. */
|
||||||
|
#define portWEAK_SYMBOL __attribute__( ( weak ) )
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
/* Scheduler utilities. */
|
/* Scheduler utilities. */
|
||||||
#define portYIELD() \
|
#define portYIELD() \
|
||||||
{ \
|
{ \
|
||||||
|
@ -160,6 +166,34 @@ not necessary for to use this port. They are defined so the common demo files
|
||||||
/* portNOP() is not required by this port. */
|
/* portNOP() is not required by this port. */
|
||||||
#define portNOP()
|
#define portNOP()
|
||||||
|
|
||||||
|
#define portINLINE __inline
|
||||||
|
|
||||||
|
#ifndef portFORCE_INLINE
|
||||||
|
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||||
|
{
|
||||||
|
uint32_t ulCurrentInterrupt;
|
||||||
|
BaseType_t xReturn;
|
||||||
|
|
||||||
|
/* Obtain the number of the currently executing interrupt. */
|
||||||
|
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||||
|
|
||||||
|
if( ulCurrentInterrupt == 0 )
|
||||||
|
{
|
||||||
|
xReturn = pdFALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xReturn = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
#ifndef __FREERTOS_RISC_V_EXTENSIONS_H__
|
#ifndef __FREERTOS_RISC_V_EXTENSIONS_H__
|
||||||
#define __FREERTOS_RISC_V_EXTENSIONS_H__
|
#define __FREERTOS_RISC_V_EXTENSIONS_H__
|
||||||
|
|
||||||
#define portasmHAS_CLINT 1
|
#define portasmHAS_MTIME 1
|
||||||
#define portasmADDITIONAL_CONTEXT_SIZE 0 /* Must be even number on 32-bit cores. */
|
#define portasmADDITIONAL_CONTEXT_SIZE 0 /* Must be even number on 32-bit cores. */
|
||||||
|
|
||||||
portasmSAVE_ADDITIONAL_REGISTERS MACRO
|
portasmSAVE_ADDITIONAL_REGISTERS MACRO
|
||||||
|
|
|
@ -34,8 +34,19 @@
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "portmacro.h"
|
#include "portmacro.h"
|
||||||
|
|
||||||
#ifndef configCLINT_BASE_ADDRESS
|
/* Standard includes. */
|
||||||
#warning configCLINT_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a Core Local Interrupter (CLINT) then set configCLINT_BASE_ADDRESS to the CLINT base address. Otherwise set configCLINT_BASE_ADDRESS to 0.
|
#include "string.h"
|
||||||
|
|
||||||
|
#ifdef configCLINT_BASE_ADDRESS
|
||||||
|
#warning The configCLINT_BASE_ADDRESS constant has been deprecated. configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS are currently being derived from the (possibly 0) configCLINT_BASE_ADDRESS setting. Please update to define configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS dirctly in place of configCLINT_BASE_ADDRESS.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configMTIME_BASE_ADDRESS
|
||||||
|
#warning configMTIME_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a memory-mapped mtime register then set configMTIME_BASE_ADDRESS to the mapped address. Otherwise set configMTIME_BASE_ADDRESS to 0.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef configMTIMECMP_BASE_ADDRESS
|
||||||
|
#warning configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a memory-mapped mtimecmp register then set configMTIMECMP_BASE_ADDRESS to the mapped address. Otherwise set configMTIMECMP_BASE_ADDRESS to 0.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Let the user override the pre-loading of the initial LR with the address of
|
/* Let the user override the pre-loading of the initial LR with the address of
|
||||||
|
@ -57,6 +68,11 @@ interrupt stack after the scheduler has started. */
|
||||||
#ifdef configISR_STACK_SIZE_WORDS
|
#ifdef configISR_STACK_SIZE_WORDS
|
||||||
static __attribute__ ((aligned(16))) StackType_t xISRStack[ configISR_STACK_SIZE_WORDS ] = { 0 };
|
static __attribute__ ((aligned(16))) StackType_t xISRStack[ configISR_STACK_SIZE_WORDS ] = { 0 };
|
||||||
const StackType_t xISRStackTop = ( StackType_t ) &( xISRStack[ configISR_STACK_SIZE_WORDS & ~portBYTE_ALIGNMENT_MASK ] );
|
const StackType_t xISRStackTop = ( StackType_t ) &( xISRStack[ configISR_STACK_SIZE_WORDS & ~portBYTE_ALIGNMENT_MASK ] );
|
||||||
|
|
||||||
|
/* Don't use 0xa5 as the stack fill bytes as that is used by the kernerl for
|
||||||
|
the task stacks, and so will legitimately appear in many positions within
|
||||||
|
the ISR stack. */
|
||||||
|
#define portISR_STACK_FILL_BYTE 0xee
|
||||||
#else
|
#else
|
||||||
extern const uint32_t __freertos_irq_stack_top[];
|
extern const uint32_t __freertos_irq_stack_top[];
|
||||||
const StackType_t xISRStackTop = ( StackType_t ) __freertos_irq_stack_top;
|
const StackType_t xISRStackTop = ( StackType_t ) __freertos_irq_stack_top;
|
||||||
|
@ -74,20 +90,16 @@ void vPortSetupTimerInterrupt( void ) __attribute__(( weak ));
|
||||||
/* Used to program the machine timer compare register. */
|
/* Used to program the machine timer compare register. */
|
||||||
uint64_t ullNextTime = 0ULL;
|
uint64_t ullNextTime = 0ULL;
|
||||||
const uint64_t *pullNextTime = &ullNextTime;
|
const uint64_t *pullNextTime = &ullNextTime;
|
||||||
const size_t uxTimerIncrementsForOneTick = ( size_t ) ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ); /* Assumes increment won't go over 32-bits. */
|
const size_t uxTimerIncrementsForOneTick = ( size_t ) ( ( configCPU_CLOCK_HZ ) / ( configTICK_RATE_HZ ) ); /* Assumes increment won't go over 32-bits. */
|
||||||
volatile uint64_t * const pullMachineTimerCompareRegisterBase = ( uint64_t * ) ( configCLINT_BASE_ADDRESS + 0x4000 );
|
uint32_t const ullMachineTimerCompareRegisterBase = configMTIMECMP_BASE_ADDRESS;
|
||||||
volatile uint64_t * pullMachineTimerCompareRegister = 0;
|
volatile uint64_t * pullMachineTimerCompareRegister = NULL;
|
||||||
|
|
||||||
/* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task
|
/* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task
|
||||||
stack checking. A problem in the ISR stack will trigger an assert, not call the
|
stack checking. A problem in the ISR stack will trigger an assert, not call the
|
||||||
stack overflow hook function (because the stack overflow hook is specific to a
|
stack overflow hook function (because the stack overflow hook is specific to a
|
||||||
task stack, not the ISR stack). */
|
task stack, not the ISR stack). */
|
||||||
#if( configCHECK_FOR_STACK_OVERFLOW > 2 )
|
#if defined( configISR_STACK_SIZE_WORDS ) && ( configCHECK_FOR_STACK_OVERFLOW > 2 )
|
||||||
#warning This path not tested, or even compiled yet.
|
#warning This path not tested, or even compiled yet.
|
||||||
/* Don't use 0xa5 as the stack fill bytes as that is used by the kernerl for
|
|
||||||
the task stacks, and so will legitimately appear in many positions within
|
|
||||||
the ISR stack. */
|
|
||||||
#define portISR_STACK_FILL_BYTE 0xee
|
|
||||||
|
|
||||||
static const uint8_t ucExpectedStackBytes[] = {
|
static const uint8_t ucExpectedStackBytes[] = {
|
||||||
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
|
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
|
||||||
|
@ -104,17 +116,17 @@ task stack, not the ISR stack). */
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#if( configCLINT_BASE_ADDRESS != 0 )
|
#if( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 )
|
||||||
|
|
||||||
void vPortSetupTimerInterrupt( void )
|
void vPortSetupTimerInterrupt( void )
|
||||||
{
|
{
|
||||||
uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;
|
uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;
|
||||||
volatile uint32_t * const pulTimeHigh = ( uint32_t * ) ( configCLINT_BASE_ADDRESS + 0xBFFC );
|
volatile uint32_t * const pulTimeHigh = ( uint32_t * ) ( ( configMTIME_BASE_ADDRESS ) + 4UL ); /* 8-byte typer so high 32-bit word is 4 bytes up. */
|
||||||
volatile uint32_t * const pulTimeLow = ( uint32_t * ) ( configCLINT_BASE_ADDRESS + 0xBFF8 );
|
volatile uint32_t * const pulTimeLow = ( uint32_t * ) ( configMTIME_BASE_ADDRESS );
|
||||||
volatile uint32_t ulHartId = 0;
|
volatile uint32_t ulHartId;
|
||||||
|
|
||||||
__asm volatile( "csrr %0, 0xf14" : "=r"( ulHartId ) ); /* 0xf14 is hartid. */
|
__asm volatile( "csrr %0, 0xf14" : "=r"( ulHartId ) ); /* 0xf14 is hartid. */
|
||||||
pullMachineTimerCompareRegister = &( pullMachineTimerCompareRegisterBase[ ulHartId ] );
|
pullMachineTimerCompareRegister = ( volatile uint64_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) );
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -123,7 +135,7 @@ task stack, not the ISR stack). */
|
||||||
} while( ulCurrentTimeHigh != *pulTimeHigh );
|
} while( ulCurrentTimeHigh != *pulTimeHigh );
|
||||||
|
|
||||||
ullNextTime = ( uint64_t ) ulCurrentTimeHigh;
|
ullNextTime = ( uint64_t ) ulCurrentTimeHigh;
|
||||||
ullNextTime <<= 32ULL;
|
ullNextTime <<= 32ULL; /* High 4-byte word is 32-bits up. */
|
||||||
ullNextTime |= ( uint64_t ) ulCurrentTimeLow;
|
ullNextTime |= ( uint64_t ) ulCurrentTimeLow;
|
||||||
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
|
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
|
||||||
*pullMachineTimerCompareRegister = ullNextTime;
|
*pullMachineTimerCompareRegister = ullNextTime;
|
||||||
|
@ -132,7 +144,7 @@ task stack, not the ISR stack). */
|
||||||
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
|
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* ( configCLINT_BASE_ADDRESS != 0 ) */
|
#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIME_BASE_ADDRESS != 0 ) */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
BaseType_t xPortStartScheduler( void )
|
BaseType_t xPortStartScheduler( void )
|
||||||
|
@ -152,6 +164,12 @@ extern void xPortStartFirstTask( void );
|
||||||
stack that was being used by main() prior to the scheduler being
|
stack that was being used by main() prior to the scheduler being
|
||||||
started. */
|
started. */
|
||||||
configASSERT( ( xISRStackTop & portBYTE_ALIGNMENT_MASK ) == 0 );
|
configASSERT( ( xISRStackTop & portBYTE_ALIGNMENT_MASK ) == 0 );
|
||||||
|
|
||||||
|
#ifdef configISR_STACK_SIZE_WORDS
|
||||||
|
{
|
||||||
|
memset( ( void * ) xISRStack, portISR_STACK_FILL_BYTE, sizeof( xISRStack ) );
|
||||||
|
}
|
||||||
|
#endif /* configISR_STACK_SIZE_WORDS */
|
||||||
}
|
}
|
||||||
#endif /* configASSERT_DEFINED */
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
@ -160,7 +178,7 @@ extern void xPortStartFirstTask( void );
|
||||||
configure whichever clock is to be used to generate the tick interrupt. */
|
configure whichever clock is to be used to generate the tick interrupt. */
|
||||||
vPortSetupTimerInterrupt();
|
vPortSetupTimerInterrupt();
|
||||||
|
|
||||||
#if( configCLINT_BASE_ADDRESS != 0 )
|
#if( ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) )
|
||||||
{
|
{
|
||||||
/* Enable mtime and external interrupts. 1<<7 for timer interrupt, 1<<11
|
/* Enable mtime and external interrupts. 1<<7 for timer interrupt, 1<<11
|
||||||
for external interrupt. _RB_ What happens here when mtime is not present as
|
for external interrupt. _RB_ What happens here when mtime is not present as
|
||||||
|
@ -172,7 +190,7 @@ extern void xPortStartFirstTask( void );
|
||||||
/* Enable external interrupts. */
|
/* Enable external interrupts. */
|
||||||
__asm volatile( "csrs 0x304, %0" :: "r"(0x800) ); /* 304 is mie. */
|
__asm volatile( "csrs 0x304, %0" :: "r"(0x800) ); /* 304 is mie. */
|
||||||
}
|
}
|
||||||
#endif /* configCLINT_BASE_ADDRESS */
|
#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) */
|
||||||
|
|
||||||
xPortStartFirstTask();
|
xPortStartFirstTask();
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,17 @@
|
||||||
|
|
||||||
/* Check the freertos_risc_v_chip_specific_extensions.h and/or command line
|
/* Check the freertos_risc_v_chip_specific_extensions.h and/or command line
|
||||||
definitions. */
|
definitions. */
|
||||||
#ifndef portasmHAS_CLINT
|
#if defined( portasmHAS_CLINT ) && defined( portasmHAS_MTIME )
|
||||||
#error freertos_risc_v_chip_specific_extensions.h must define portasmHAS_CLINT to either 1 (CLINT present) or 0 (clint not present).
|
#error The portasmHAS_CLINT constant has been depracted. Please replace it with portasmHAS_CLINT. portasmHAS_CLINT and portasmHAS_MTIME cannot both be defined at once.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef portasmHAS_CLINT
|
||||||
|
#warning The portasmHAS_CLINT constant has been depracted. Please replace it with portasmHAS_CLINT. For now portasmHAS_MTIME is derived from portasmHAS_CLINT.
|
||||||
|
#define portasmHAS_MTIME portasmHAS_CLINT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef portasmHAS_MTIME
|
||||||
|
#error freertos_risc_v_chip_specific_extensions.h must define portasmHAS_MTIME to either 1 (MTIME clock present) or 0 (MTIME clock not present).
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef portasmHANDLE_INTERRUPT
|
#ifndef portasmHANDLE_INTERRUPT
|
||||||
|
@ -99,12 +108,12 @@ at the top of this file. */
|
||||||
EXTERN pxCurrentTCB
|
EXTERN pxCurrentTCB
|
||||||
EXTERN ulPortTrapHandler
|
EXTERN ulPortTrapHandler
|
||||||
EXTERN vTaskSwitchContext
|
EXTERN vTaskSwitchContext
|
||||||
|
EXTERN xTaskIncrementTick
|
||||||
EXTERN Timer_IRQHandler
|
EXTERN Timer_IRQHandler
|
||||||
EXTERN pullMachineTimerCompareRegister
|
EXTERN pullMachineTimerCompareRegister
|
||||||
EXTERN pullNextTime
|
EXTERN pullNextTime
|
||||||
EXTERN uxTimerIncrementsForOneTick /* size_t type so 32-bit on 32-bit core and 64-bits on 64-bit core. */
|
EXTERN uxTimerIncrementsForOneTick /* size_t type so 32-bit on 32-bit core and 64-bits on 64-bit core. */
|
||||||
EXTERN xISRStackTop
|
EXTERN xISRStackTop
|
||||||
EXTERN xTaskIncrementTick
|
|
||||||
EXTERN portasmHANDLE_INTERRUPT
|
EXTERN portasmHANDLE_INTERRUPT
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
@ -161,7 +170,7 @@ test_if_asynchronous:
|
||||||
|
|
||||||
handle_asynchronous:
|
handle_asynchronous:
|
||||||
|
|
||||||
#if( portasmHAS_CLINT != 0 )
|
#if( portasmHAS_MTIME != 0 )
|
||||||
|
|
||||||
test_if_mtimer: /* If there is a CLINT then the mtimer is used to generate the tick interrupt. */
|
test_if_mtimer: /* If there is a CLINT then the mtimer is used to generate the tick interrupt. */
|
||||||
|
|
||||||
|
@ -180,7 +189,7 @@ handle_asynchronous:
|
||||||
li t4, -1
|
li t4, -1
|
||||||
lw t2, 0(t1) /* Load the low word of ullNextTime into t2. */
|
lw t2, 0(t1) /* Load the low word of ullNextTime into t2. */
|
||||||
lw t3, 4(t1) /* Load the high word of ullNextTime into t3. */
|
lw t3, 4(t1) /* Load the high word of ullNextTime into t3. */
|
||||||
sw t4, 0(t0) /* Low word no smaller than old value. */
|
sw t4, 0(t0) /* Low word no smaller than old value to start with - will be overwritten below. */
|
||||||
sw t3, 4(t0) /* Store high word of ullNextTime into compare register. No smaller than new value. */
|
sw t3, 4(t0) /* Store high word of ullNextTime into compare register. No smaller than new value. */
|
||||||
sw t2, 0(t0) /* Store low word of ullNextTime into compare register. */
|
sw t2, 0(t0) /* Store low word of ullNextTime into compare register. */
|
||||||
lw t0, uxTimerIncrementsForOneTick /* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */
|
lw t0, uxTimerIncrementsForOneTick /* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */
|
||||||
|
@ -213,7 +222,7 @@ handle_asynchronous:
|
||||||
addi t1, t1, 4 /* 0x80000007 + 4 = 0x8000000b == Machine external interrupt. */
|
addi t1, t1, 4 /* 0x80000007 + 4 = 0x8000000b == Machine external interrupt. */
|
||||||
bne a0, t1, as_yet_unhandled /* Something as yet unhandled. */
|
bne a0, t1, as_yet_unhandled /* Something as yet unhandled. */
|
||||||
|
|
||||||
#endif /* portasmHAS_CLINT */
|
#endif /* portasmHAS_MTIME */
|
||||||
|
|
||||||
load_x sp, xISRStackTop /* Switch to ISR stack before function call. */
|
load_x sp, xISRStackTop /* Switch to ISR stack before function call. */
|
||||||
jal portasmHANDLE_INTERRUPT /* Jump to the interrupt handler if there is no CLINT or if there is a CLINT and it has been determined that an external interrupt is pending. */
|
jal portasmHANDLE_INTERRUPT /* Jump to the interrupt handler if there is no CLINT or if there is a CLINT and it has been determined that an external interrupt is pending. */
|
||||||
|
@ -231,11 +240,13 @@ test_if_environment_call:
|
||||||
j processed_source
|
j processed_source
|
||||||
|
|
||||||
is_exception:
|
is_exception:
|
||||||
ebreak
|
csrr t0, CSR_MCAUSE /* For viewing in the debugger only. */
|
||||||
j is_exception
|
csrr t1, CSR_MEPC /* For viewing in the debugger only */
|
||||||
|
csrr t2, CSR_MSTATUS
|
||||||
|
j is_exception /* No other exceptions handled yet. */
|
||||||
|
|
||||||
as_yet_unhandled:
|
as_yet_unhandled:
|
||||||
ebreak
|
csrr t0, mcause /* For viewing in the debugger only. */
|
||||||
j as_yet_unhandled
|
j as_yet_unhandled
|
||||||
|
|
||||||
processed_source:
|
processed_source:
|
||||||
|
@ -288,7 +299,7 @@ processed_source:
|
||||||
|
|
||||||
xPortStartFirstTask:
|
xPortStartFirstTask:
|
||||||
|
|
||||||
#if( portasmHAS_CLINT != 0 )
|
#if( portasmHAS_MTIME != 0 )
|
||||||
/* If there is a clint then interrupts can branch directly to the FreeRTOS
|
/* If there is a clint then interrupts can branch directly to the FreeRTOS
|
||||||
trap handler. Otherwise the interrupt controller will need to be configured
|
trap handler. Otherwise the interrupt controller will need to be configured
|
||||||
outside of this file. */
|
outside of this file. */
|
||||||
|
@ -304,6 +315,7 @@ xPortStartFirstTask:
|
||||||
portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
|
portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
|
||||||
|
|
||||||
load_x t0, 29 * portWORD_SIZE( sp ) /* mstatus */
|
load_x t0, 29 * portWORD_SIZE( sp ) /* mstatus */
|
||||||
|
addi t0, t0, 0x08 /* Set MIE bit so the first task starts with interrupts enabled - required as returns with ret not eret. */
|
||||||
csrrw x0, CSR_MSTATUS, t0 /* Interrupts enabled from here! */
|
csrrw x0, CSR_MSTATUS, t0 /* Interrupts enabled from here! */
|
||||||
|
|
||||||
load_x x5, 2 * portWORD_SIZE( sp ) /* t0 */
|
load_x x5, 2 * portWORD_SIZE( sp ) /* t0 */
|
||||||
|
|
|
@ -67,6 +67,13 @@ typedef portBASE_TYPE BaseType_t;
|
||||||
typedef portUBASE_TYPE UBaseType_t;
|
typedef portUBASE_TYPE UBaseType_t;
|
||||||
typedef portUBASE_TYPE TickType_t;
|
typedef portUBASE_TYPE TickType_t;
|
||||||
|
|
||||||
|
/* Legacy type definitions. */
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT float
|
||||||
|
#define portDOUBLE double
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT short
|
||||||
|
|
||||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||||
not need to be guarded with a critical section. */
|
not need to be guarded with a critical section. */
|
||||||
#define portTICK_TYPE_IS_ATOMIC 1
|
#define portTICK_TYPE_IS_ATOMIC 1
|
||||||
|
@ -140,6 +147,27 @@ the source code because to do so would cause other compilers to generate
|
||||||
warnings. */
|
warnings. */
|
||||||
#pragma diag_suppress=Pa082
|
#pragma diag_suppress=Pa082
|
||||||
|
|
||||||
|
/* configCLINT_BASE_ADDRESS is a legacy definition that was replaced by the
|
||||||
|
configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS definitions. For
|
||||||
|
backward compatibility derive the newer definitions from the old if the old
|
||||||
|
definition is found. */
|
||||||
|
#if defined( configCLINT_BASE_ADDRESS ) && !defined( configMTIME_BASE_ADDRESS ) && ( configCLINT_BASE_ADDRESS == 0 )
|
||||||
|
/* Legacy case where configCLINT_BASE_ADDRESS was defined as 0 to indicate
|
||||||
|
there was no CLINT. Equivalent now is to set the MTIME and MTIMECMP
|
||||||
|
addresses to 0. */
|
||||||
|
#define configMTIME_BASE_ADDRESS ( 0 )
|
||||||
|
#define configMTIMECMP_BASE_ADDRESS ( 0 )
|
||||||
|
#elif defined( configCLINT_BASE_ADDRESS ) && !defined( configMTIME_BASE_ADDRESS )
|
||||||
|
/* Legacy case where configCLINT_BASE_ADDRESS was set to the base address of
|
||||||
|
the CLINT. Equivalent now is to derive the MTIME and MTIMECMP addresses
|
||||||
|
from the CLINT address. */
|
||||||
|
#define configMTIME_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0xBFF8UL )
|
||||||
|
#define configMTIMECMP_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0x4000UL )
|
||||||
|
#elif !defined( configMTIME_BASE_ADDRESS ) || !defined( configMTIMECMP_BASE_ADDRESS )
|
||||||
|
#error configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. Set them to zero if there is no MTIME (machine time) clock. See https://www.freertos.org/Using-FreeRTOS-on-RISC-V.html
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ static uint32_t prvProcessTickInterrupt( void );
|
||||||
* attempt to obtain pvInterruptEventMutex if a critical section is used inside
|
* attempt to obtain pvInterruptEventMutex if a critical section is used inside
|
||||||
* an interrupt handler itself.
|
* an interrupt handler itself.
|
||||||
*/
|
*/
|
||||||
static volatile BaseType_t xInsideInterrupt = pdFALSE;
|
volatile BaseType_t xInsideInterrupt = pdFALSE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called when the process exits to let Windows know the high timer resolution
|
* Called when the process exits to let Windows know the high timer resolution
|
||||||
|
@ -394,7 +394,7 @@ CONTEXT xContext;
|
||||||
xInsideInterrupt = pdFALSE;
|
xInsideInterrupt = pdFALSE;
|
||||||
WaitForMultipleObjects( sizeof( pvObjectList ) / sizeof( void * ), pvObjectList, TRUE, INFINITE );
|
WaitForMultipleObjects( sizeof( pvObjectList ) / sizeof( void * ), pvObjectList, TRUE, INFINITE );
|
||||||
|
|
||||||
/* /* Cannot be in a critical section to get here. Tasks that exist a
|
/* Cannot be in a critical section to get here. Tasks that exist a
|
||||||
critical section will block on a yield mutex to wait for an interrupt to
|
critical section will block on a yield mutex to wait for an interrupt to
|
||||||
process if an interrupt was set pending while the task was inside the
|
process if an interrupt was set pending while the task was inside the
|
||||||
critical section. xInsideInterrupt prevents interrupts that contain
|
critical section. xInsideInterrupt prevents interrupts that contain
|
||||||
|
|
|
@ -74,6 +74,11 @@ typedef unsigned long UBaseType_t;
|
||||||
|
|
||||||
#define portYIELD() vPortGenerateSimulatedInterrupt( portINTERRUPT_YIELD )
|
#define portYIELD() vPortGenerateSimulatedInterrupt( portINTERRUPT_YIELD )
|
||||||
|
|
||||||
|
|
||||||
|
extern volatile BaseType_t xInsideInterrupt;
|
||||||
|
#define portSOFTWARE_BARRIER() while( xInsideInterrupt != pdFALSE )
|
||||||
|
|
||||||
|
|
||||||
/* Simulated interrupts return pdFALSE if no context switch should be performed,
|
/* Simulated interrupts return pdFALSE if no context switch should be performed,
|
||||||
or a non-zero number if a context switch should be performed. */
|
or a non-zero number if a context switch should be performed. */
|
||||||
#define portYIELD_FROM_ISR( x ) ( void ) x
|
#define portYIELD_FROM_ISR( x ) ( void ) x
|
||||||
|
|
|
@ -34,15 +34,16 @@
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
/* Constants required to manipulate the NVIC. */
|
/* 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_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||||
#define portNVIC_SYSPRI2 ( ( volatile uint32_t *) 0xe000ed20 )
|
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||||
#define portNVIC_SYSTICK_CLK 0x00000004
|
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||||
#define portNVIC_SYSTICK_INT 0x00000002
|
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||||
#define portNVIC_SYSTICK_ENABLE 0x00000001
|
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||||
#define portNVIC_PENDSVSET 0x10000000
|
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||||
|
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||||
#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 )
|
||||||
|
@ -50,17 +51,56 @@
|
||||||
/* Constants required to set up the initial stack. */
|
/* Constants required to set up the initial stack. */
|
||||||
#define portINITIAL_XPSR ( 0x01000000 )
|
#define portINITIAL_XPSR ( 0x01000000 )
|
||||||
|
|
||||||
|
/* The systick is a 24-bit counter. */
|
||||||
|
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||||
|
|
||||||
|
/* A fiddle factor to estimate the number of SysTick counts that would have
|
||||||
|
occurred while the SysTick counter is stopped during tickless idle
|
||||||
|
calculations. */
|
||||||
|
#ifndef portMISSED_COUNTS_FACTOR
|
||||||
|
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Constants used with memory barrier intrinsics. */
|
/* Constants used with memory barrier intrinsics. */
|
||||||
#define portSY_FULL_READ_WRITE ( 15 )
|
#define portSY_FULL_READ_WRITE ( 15 )
|
||||||
|
|
||||||
|
/* Legacy macro for backward compatibility only. This macro used to be used to
|
||||||
|
replace the function that configures the clock used to generate the tick
|
||||||
|
interrupt (prvSetupTimerInterrupt()), but now the function is declared weak so
|
||||||
|
the application writer can override it by simply defining a function of the
|
||||||
|
same name (vApplicationSetupTickInterrupt()). */
|
||||||
|
#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION
|
||||||
|
#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Each task maintains its own interrupt status in the critical nesting
|
/* Each task maintains its own interrupt status in the critical nesting
|
||||||
variable. */
|
variable. */
|
||||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||||
|
|
||||||
|
/* The number of SysTick increments that make up one tick period. */
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
static uint32_t ulTimerCountsForOneTick = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/* The maximum number of tick periods that can be suppressed is limited by the
|
||||||
|
24 bit resolution of the SysTick timer. */
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/* Compensate for the CPU cycles that pass while the SysTick is stopped (low
|
||||||
|
power functionality only.
|
||||||
|
*/
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
static uint32_t ulStoppedTimerCompensation = 0;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup the timer to generate the tick interrupts.
|
* Setup the timer to generate the tick interrupts. The implementation in this
|
||||||
|
* file is weak to allow application writers to change the timer used to
|
||||||
|
* generate the tick interrupt.
|
||||||
*/
|
*/
|
||||||
static void prvSetupTimerInterrupt( void );
|
void vPortSetupTimerInterrupt( void );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exception handlers.
|
* Exception handlers.
|
||||||
|
@ -158,12 +198,12 @@ __asm void prvPortStartFirstTask( void )
|
||||||
BaseType_t xPortStartScheduler( void )
|
BaseType_t xPortStartScheduler( void )
|
||||||
{
|
{
|
||||||
/* 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;
|
||||||
|
|
||||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||||
here already. */
|
here already. */
|
||||||
prvSetupTimerInterrupt();
|
vPortSetupTimerInterrupt();
|
||||||
|
|
||||||
/* Initialise the critical nesting count ready for the first task. */
|
/* Initialise the critical nesting count ready for the first task. */
|
||||||
uxCriticalNesting = 0;
|
uxCriticalNesting = 0;
|
||||||
|
@ -187,7 +227,7 @@ void vPortEndScheduler( void )
|
||||||
void vPortYield( void )
|
void vPortYield( void )
|
||||||
{
|
{
|
||||||
/* 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 completely
|
/* Barriers are normally not required but do ensure the code is completely
|
||||||
within the specified behaviour for the architecture. */
|
within the specified behaviour for the architecture. */
|
||||||
|
@ -287,7 +327,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 );
|
||||||
|
@ -298,15 +338,193 @@ uint32_t ulPreviousMask;
|
||||||
* Setup the systick timer to generate the tick interrupts at the required
|
* Setup the systick timer to generate the tick interrupts at the required
|
||||||
* frequency.
|
* frequency.
|
||||||
*/
|
*/
|
||||||
void prvSetupTimerInterrupt( void )
|
#if( configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 )
|
||||||
{
|
|
||||||
|
__weak void vPortSetupTimerInterrupt( void )
|
||||||
|
{
|
||||||
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
ulTimerCountsForOneTick = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );
|
||||||
|
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||||
|
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR;
|
||||||
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
/* Stop and reset the SysTick. */
|
/* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
|
||||||
|
__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. */
|
||||||
|
__disable_irq();
|
||||||
|
__dsb( portSY_FULL_READ_WRITE );
|
||||||
|
__isb( portSY_FULL_READ_WRITE );
|
||||||
|
|
||||||
|
/* If a context switch is pending or a task is waiting for the scheduler
|
||||||
|
to be unsuspended then abandon the low power entry. */
|
||||||
|
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||||
|
{
|
||||||
|
/* Restart from whatever is left in the count register to complete
|
||||||
|
this tick period. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||||
|
|
||||||
|
/* Restart SysTick. */
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
|
||||||
|
/* Reset the reload register to the value required for normal tick
|
||||||
|
periods. */
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Re-enable interrupts - see comments above __disable_irq() call
|
||||||
|
above. */
|
||||||
|
__enable_irq();
|
||||||
|
}
|
||||||
|
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 )
|
||||||
|
{
|
||||||
|
__dsb( portSY_FULL_READ_WRITE );
|
||||||
|
__wfi();
|
||||||
|
__isb( portSY_FULL_READ_WRITE );
|
||||||
|
}
|
||||||
|
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||||
|
|
||||||
|
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||||
|
out of sleep mode to execute immediately. see comments above
|
||||||
|
__disable_interrupt() call above. */
|
||||||
|
__enable_irq();
|
||||||
|
__dsb( portSY_FULL_READ_WRITE );
|
||||||
|
__isb( portSY_FULL_READ_WRITE );
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
__disable_irq();
|
||||||
|
__dsb( portSY_FULL_READ_WRITE );
|
||||||
|
__isb( portSY_FULL_READ_WRITE );
|
||||||
|
|
||||||
|
/* 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 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
|
||||||
|
again, then set portNVIC_SYSTICK_LOAD back to its standard
|
||||||
|
value. */
|
||||||
|
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||||
|
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
|
vTaskStepTick( ulCompleteTickPeriods );
|
||||||
|
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||||
|
|
||||||
|
/* Exit with interrpts enabled. */
|
||||||
|
__enable_irq();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* #if configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
|
@ -100,6 +100,13 @@ extern void vClearInterruptMaskFromISR( uint32_t ulMask );
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Tickless idle/low power functionality. */
|
||||||
|
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||||
|
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||||
|
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
|
|
@ -51,11 +51,11 @@
|
||||||
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The __weak attribute does not work as you might expect with the Keil tools
|
/* Legacy macro for backward compatibility only. This macro used to be used to
|
||||||
so the configOVERRIDE_DEFAULT_TICK_CONFIGURATION constant must be set to 1 if
|
replace the function that configures the clock used to generate the tick
|
||||||
the application writer wants to provide their own implementation of
|
interrupt (prvSetupTimerInterrupt()), but now the function is declared weak so
|
||||||
vPortSetupTimerInterrupt(). Ensure configOVERRIDE_DEFAULT_TICK_CONFIGURATION
|
the application writer can override it by simply defining a function of the
|
||||||
is defined. */
|
same name (vApplicationSetupTickInterrupt()). */
|
||||||
#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION
|
#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION
|
||||||
#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0
|
#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0
|
||||||
#endif
|
#endif
|
||||||
|
@ -603,7 +603,7 @@ void xPortSysTickHandler( void )
|
||||||
*/
|
*/
|
||||||
#if( configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 )
|
#if( configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 )
|
||||||
|
|
||||||
void vPortSetupTimerInterrupt( void )
|
__weak void vPortSetupTimerInterrupt( void )
|
||||||
{
|
{
|
||||||
/* Calculate the constants required to configure the tick interrupt. */
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
|
|
@ -51,11 +51,11 @@
|
||||||
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The __weak attribute does not work as you might expect with the Keil tools
|
/* Legacy macro for backward compatibility only. This macro used to be used to
|
||||||
so the configOVERRIDE_DEFAULT_TICK_CONFIGURATION constant must be set to 1 if
|
replace the function that configures the clock used to generate the tick
|
||||||
the application writer wants to provide their own implementation of
|
interrupt (prvSetupTimerInterrupt()), but now the function is declared weak so
|
||||||
vPortSetupTimerInterrupt(). Ensure configOVERRIDE_DEFAULT_TICK_CONFIGURATION
|
the application writer can override it by simply defining a function of the
|
||||||
is defined. */
|
same name (vApplicationSetupTickInterrupt()). */
|
||||||
#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION
|
#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION
|
||||||
#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0
|
#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0
|
||||||
#endif
|
#endif
|
||||||
|
@ -693,7 +693,7 @@ void xPortSysTickHandler( void )
|
||||||
*/
|
*/
|
||||||
#if( configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 )
|
#if( configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 )
|
||||||
|
|
||||||
void vPortSetupTimerInterrupt( void )
|
__weak void vPortSetupTimerInterrupt( void )
|
||||||
{
|
{
|
||||||
/* Calculate the constants required to configure the tick interrupt. */
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
*----------------------------------------------------------*/
|
*----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||||
all the API functions to use the MPU wrappers. That should only be done when
|
* all the API functions to use the MPU wrappers. That should only be done when
|
||||||
task.h is included from an application file. */
|
* task.h is included from an application file. */
|
||||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||||
|
|
||||||
/* Scheduler includes. */
|
/* Scheduler includes. */
|
||||||
|
@ -99,18 +99,18 @@ task.h is included from an application file. */
|
||||||
#define portOFFSET_TO_PC ( 6 )
|
#define portOFFSET_TO_PC ( 6 )
|
||||||
|
|
||||||
/* For strict compliance with the Cortex-M spec the task start address should
|
/* For strict compliance with the Cortex-M spec the task start address should
|
||||||
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
|
* have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
|
||||||
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
||||||
|
|
||||||
/* Each task maintains its own interrupt status in the critical nesting
|
/* Each task maintains its own interrupt status in the critical nesting
|
||||||
variable. Note this is not saved as part of the task context as context
|
* variable. Note this is not saved as part of the task context as context
|
||||||
switches can only occur when uxCriticalNesting is zero. */
|
* switches can only occur when uxCriticalNesting is zero. */
|
||||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup the timer to generate the tick interrupts.
|
* Setup the timer to generate the tick interrupts.
|
||||||
*/
|
*/
|
||||||
static void prvSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION;
|
void vSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configure a number of standard MPU regions that are used by all tasks.
|
* Configure a number of standard MPU regions that are used by all tasks.
|
||||||
|
@ -205,7 +205,7 @@ extern void vPortResetPrivilege( BaseType_t xRunningPrivileged );
|
||||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged )
|
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged )
|
||||||
{
|
{
|
||||||
/* Simulate the stack frame as it would be created by a context switch
|
/* Simulate the stack frame as it would be created by a context switch
|
||||||
interrupt. */
|
* interrupt. */
|
||||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
|
@ -216,7 +216,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
|
||||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||||
|
|
||||||
/* A save method is being used that requires each task to maintain its
|
/* A save method is being used that requires each task to maintain its
|
||||||
own exec return value. */
|
* own exec return value. */
|
||||||
pxTopOfStack--;
|
pxTopOfStack--;
|
||||||
*pxTopOfStack = portINITIAL_EXC_RETURN;
|
*pxTopOfStack = portINITIAL_EXC_RETURN;
|
||||||
|
|
||||||
|
@ -238,11 +238,16 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
|
||||||
void prvSVCHandler( uint32_t *pulParam )
|
void prvSVCHandler( uint32_t *pulParam )
|
||||||
{
|
{
|
||||||
uint8_t ucSVCNumber;
|
uint8_t ucSVCNumber;
|
||||||
uint32_t ulReg;
|
uint32_t ulReg, ulPC;
|
||||||
|
#if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )
|
||||||
|
extern uint32_t __syscalls_flash_start__;
|
||||||
|
extern uint32_t __syscalls_flash_end__;
|
||||||
|
#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
|
||||||
|
|
||||||
/* The stack contains: r0, r1, r2, r3, r12, r14, the return address and
|
/* The stack contains: r0, r1, r2, r3, r12, LR, PC and xPSR. The first
|
||||||
xPSR. The first argument (r0) is pulParam[ 0 ]. */
|
* argument (r0) is pulParam[ 0 ]. */
|
||||||
ucSVCNumber = ( ( uint8_t * ) pulParam[ portOFFSET_TO_PC ] )[ -2 ];
|
ulPC = pulParam[ portOFFSET_TO_PC ];
|
||||||
|
ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ];
|
||||||
switch( ucSVCNumber )
|
switch( ucSVCNumber )
|
||||||
{
|
{
|
||||||
case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI;
|
case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI;
|
||||||
|
@ -251,14 +256,30 @@ uint32_t ulReg;
|
||||||
|
|
||||||
case portSVC_YIELD : portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
case portSVC_YIELD : portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||||
/* Barriers are normally not required
|
/* Barriers are normally not required
|
||||||
but do ensure the code is completely
|
* but do ensure the code is completely
|
||||||
within the specified behaviour for the
|
* within the specified behaviour for the
|
||||||
architecture. */
|
* architecture. */
|
||||||
__asm volatile( "dsb" );
|
__asm volatile( "dsb" );
|
||||||
__asm volatile( "isb" );
|
__asm volatile( "isb" );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )
|
||||||
|
case portSVC_RAISE_PRIVILEGE : /* Only raise the privilege, if the
|
||||||
|
* svc was raised from any of the
|
||||||
|
* system calls. */
|
||||||
|
if( ulPC >= ( uint32_t ) __syscalls_flash_start__ &&
|
||||||
|
ulPC <= ( uint32_t ) __syscalls_flash_end__ )
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
mrs ulReg, control /* Obtain current control value. */
|
||||||
|
bic ulReg, #1 /* Set privilege bit. */
|
||||||
|
msr control, ulReg /* Write back new control value. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#else
|
||||||
case portSVC_RAISE_PRIVILEGE : __asm
|
case portSVC_RAISE_PRIVILEGE : __asm
|
||||||
{
|
{
|
||||||
mrs ulReg, control /* Obtain current control value. */
|
mrs ulReg, control /* Obtain current control value. */
|
||||||
|
@ -266,6 +287,7 @@ uint32_t ulReg;
|
||||||
msr control, ulReg /* Write back new control value. */
|
msr control, ulReg /* Write back new control value. */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
|
||||||
|
|
||||||
default : /* Unknown SVC call. */
|
default : /* Unknown SVC call. */
|
||||||
break;
|
break;
|
||||||
|
@ -304,9 +326,23 @@ __asm void prvRestoreContextOfFirstTask( void )
|
||||||
ldr r1, [r3]
|
ldr r1, [r3]
|
||||||
ldr r0, [r1] /* The first item in the TCB is the task top of stack. */
|
ldr r0, [r1] /* The first item in the TCB is the task top of stack. */
|
||||||
add r1, r1, #4 /* Move onto the second item in the TCB... */
|
add r1, r1, #4 /* Move onto the second item in the TCB... */
|
||||||
|
|
||||||
|
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
|
||||||
|
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||||
|
bic r3, r3, #1 /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
|
||||||
|
str r3, [r2] /* Disable MPU. */
|
||||||
|
|
||||||
ldr r2, =0xe000ed9c /* Region Base Address register. */
|
ldr r2, =0xe000ed9c /* Region Base Address register. */
|
||||||
ldmia r1!, {r4-r11} /* Read 4 sets of MPU registers. */
|
ldmia r1!, {r4-r11} /* Read 4 sets of MPU registers. */
|
||||||
stmia r2!, {r4-r11} /* Write 4 sets of MPU registers. */
|
stmia r2!, {r4-r11} /* Write 4 sets of MPU registers. */
|
||||||
|
|
||||||
|
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
|
||||||
|
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||||
|
orr r3, r3, #1 /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
|
||||||
|
str r3, [r2] /* Enable MPU. */
|
||||||
|
dsb /* Force memory writes before continuing. */
|
||||||
|
|
||||||
ldmia r0!, {r3-r11, r14} /* Pop the registers that are not automatically saved on exception entry. */
|
ldmia r0!, {r3-r11, r14} /* Pop the registers that are not automatically saved on exception entry. */
|
||||||
msr control, r3
|
msr control, r3
|
||||||
msr psp, r0 /* Restore the task stack pointer. */
|
msr psp, r0 /* Restore the task stack pointer. */
|
||||||
|
@ -323,7 +359,7 @@ __asm void prvRestoreContextOfFirstTask( void )
|
||||||
BaseType_t xPortStartScheduler( void )
|
BaseType_t xPortStartScheduler( void )
|
||||||
{
|
{
|
||||||
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See
|
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See
|
||||||
http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
* http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
||||||
configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) );
|
configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) );
|
||||||
|
|
||||||
#if( configASSERT_DEFINED == 1 )
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
@ -333,15 +369,15 @@ BaseType_t xPortStartScheduler( void )
|
||||||
volatile uint8_t ucMaxPriorityValue;
|
volatile uint8_t ucMaxPriorityValue;
|
||||||
|
|
||||||
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||||
functions can be called. ISR safe functions are those that end in
|
* functions can be called. ISR safe functions are those that end in
|
||||||
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||||
ensure interrupt entry is as fast and simple as possible.
|
* ensure interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
Save the interrupt priority value that is about to be clobbered. */
|
* Save the interrupt priority value that is about to be clobbered. */
|
||||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||||
|
|
||||||
/* Determine the number of priority bits available. First write to all
|
/* Determine the number of priority bits available. First write to all
|
||||||
possible bits. */
|
* possible bits. */
|
||||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||||
|
|
||||||
/* Read the value back to see how many bits stuck. */
|
/* Read the value back to see how many bits stuck. */
|
||||||
|
@ -351,7 +387,7 @@ BaseType_t xPortStartScheduler( void )
|
||||||
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||||
|
|
||||||
/* Calculate the maximum acceptable priority group value for the number
|
/* Calculate the maximum acceptable priority group value for the number
|
||||||
of bits read back. */
|
* of bits read back. */
|
||||||
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
||||||
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||||
{
|
{
|
||||||
|
@ -362,8 +398,8 @@ BaseType_t xPortStartScheduler( void )
|
||||||
#ifdef __NVIC_PRIO_BITS
|
#ifdef __NVIC_PRIO_BITS
|
||||||
{
|
{
|
||||||
/* Check the CMSIS configuration that defines the number of
|
/* Check the CMSIS configuration that defines the number of
|
||||||
priority bits matches the number of priority bits actually queried
|
* priority bits matches the number of priority bits actually queried
|
||||||
from the hardware. */
|
* from the hardware. */
|
||||||
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
|
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -371,26 +407,26 @@ BaseType_t xPortStartScheduler( void )
|
||||||
#ifdef configPRIO_BITS
|
#ifdef configPRIO_BITS
|
||||||
{
|
{
|
||||||
/* Check the FreeRTOS configuration that defines the number of
|
/* Check the FreeRTOS configuration that defines the number of
|
||||||
priority bits matches the number of priority bits actually queried
|
* priority bits matches the number of priority bits actually queried
|
||||||
from the hardware. */
|
* from the hardware. */
|
||||||
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
|
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Shift the priority group value back to its position within the AIRCR
|
/* Shift the priority group value back to its position within the AIRCR
|
||||||
register. */
|
* register. */
|
||||||
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||||
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||||
|
|
||||||
/* Restore the clobbered interrupt priority register to its original
|
/* Restore the clobbered interrupt priority register to its original
|
||||||
value. */
|
* value. */
|
||||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||||
}
|
}
|
||||||
#endif /* conifgASSERT_DEFINED */
|
#endif /* conifgASSERT_DEFINED */
|
||||||
|
|
||||||
/* Make PendSV and SysTick the same priority as the kernel, and the SVC
|
/* Make PendSV and SysTick the same priority as the kernel, and the SVC
|
||||||
handler higher priority so it can be used to exit a critical section (where
|
* handler higher priority so it can be used to exit a critical section (where
|
||||||
lower priorities are masked). */
|
* lower priorities are masked). */
|
||||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
|
||||||
|
@ -398,8 +434,8 @@ BaseType_t xPortStartScheduler( void )
|
||||||
prvSetupMPU();
|
prvSetupMPU();
|
||||||
|
|
||||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||||
here already. */
|
* here already. */
|
||||||
prvSetupTimerInterrupt();
|
vSetupTimerInterrupt();
|
||||||
|
|
||||||
/* Initialise the critical nesting count ready for the first task. */
|
/* Initialise the critical nesting count ready for the first task. */
|
||||||
uxCriticalNesting = 0;
|
uxCriticalNesting = 0;
|
||||||
|
@ -429,9 +465,9 @@ __asm void prvStartFirstTask( void )
|
||||||
/* Set the msp back to the start of the stack. */
|
/* Set the msp back to the start of the stack. */
|
||||||
msr msp, r0
|
msr msp, r0
|
||||||
/* Clear the bit that indicates the FPU is in use in case the FPU was used
|
/* Clear the bit that indicates the FPU is in use in case the FPU was used
|
||||||
before the scheduler was started - which would otherwise result in the
|
* before the scheduler was started - which would otherwise result in the
|
||||||
unnecessary leaving of space in the SVC stack for lazy saving of FPU
|
* unnecessary leaving of space in the SVC stack for lazy saving of FPU
|
||||||
registers. */
|
* registers. */
|
||||||
mov r0, #0
|
mov r0, #0
|
||||||
msr control, r0
|
msr control, r0
|
||||||
/* Globally enable interrupts. */
|
/* Globally enable interrupts. */
|
||||||
|
@ -447,7 +483,7 @@ __asm void prvStartFirstTask( void )
|
||||||
void vPortEndScheduler( void )
|
void vPortEndScheduler( void )
|
||||||
{
|
{
|
||||||
/* Not implemented in ports where there is nothing to return to.
|
/* Not implemented in ports where there is nothing to return to.
|
||||||
Artificially force an assert. */
|
* Artificially force an assert. */
|
||||||
configASSERT( uxCriticalNesting == 1000UL );
|
configASSERT( uxCriticalNesting == 1000UL );
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
@ -511,9 +547,23 @@ __asm void xPortPendSVHandler( void )
|
||||||
ldr r1, [r3]
|
ldr r1, [r3]
|
||||||
ldr r0, [r1] /* The first item in the TCB is the task top of stack. */
|
ldr r0, [r1] /* The first item in the TCB is the task top of stack. */
|
||||||
add r1, r1, #4 /* Move onto the second item in the TCB... */
|
add r1, r1, #4 /* Move onto the second item in the TCB... */
|
||||||
|
|
||||||
|
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||||
|
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
|
||||||
|
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||||
|
bic r3, r3, #1 /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
|
||||||
|
str r3, [r2] /* Disable MPU. */
|
||||||
|
|
||||||
ldr r2, =0xe000ed9c /* Region Base Address register. */
|
ldr r2, =0xe000ed9c /* Region Base Address register. */
|
||||||
ldmia r1!, {r4-r11} /* Read 4 sets of MPU registers. */
|
ldmia r1!, {r4-r11} /* Read 4 sets of MPU registers. */
|
||||||
stmia r2!, {r4-r11} /* Write 4 sets of MPU registers. */
|
stmia r2!, {r4-r11} /* Write 4 sets of MPU registers. */
|
||||||
|
|
||||||
|
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
|
||||||
|
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||||
|
orr r3, r3, #1 /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
|
||||||
|
str r3, [r2] /* Enable MPU. */
|
||||||
|
dsb /* Force memory writes before continuing. */
|
||||||
|
|
||||||
ldmia r0!, {r3-r11, r14} /* Pop the registers that are not automatically saved on exception entry. */
|
ldmia r0!, {r3-r11, r14} /* Pop the registers that are not automatically saved on exception entry. */
|
||||||
msr control, r3
|
msr control, r3
|
||||||
|
|
||||||
|
@ -548,7 +598,7 @@ uint32_t ulDummy;
|
||||||
* Setup the systick timer to generate the tick interrupts at the required
|
* Setup the systick timer to generate the tick interrupts at the required
|
||||||
* frequency.
|
* frequency.
|
||||||
*/
|
*/
|
||||||
static void prvSetupTimerInterrupt( void )
|
__weak void vSetupTimerInterrupt( void )
|
||||||
{
|
{
|
||||||
/* Reset the SysTick. */
|
/* Reset the SysTick. */
|
||||||
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||||
|
@ -608,8 +658,8 @@ extern uint32_t __privileged_data_end__;
|
||||||
( portMPU_REGION_ENABLE );
|
( portMPU_REGION_ENABLE );
|
||||||
|
|
||||||
/* Setup the first 16K for privileged only access (even though less
|
/* Setup the first 16K for privileged only access (even though less
|
||||||
than 10K is actually being used). This is where the kernel code is
|
* than 10K is actually being used). This is where the kernel code is
|
||||||
placed. */
|
* placed. */
|
||||||
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 ) |
|
||||||
( portPRIVILEGED_FLASH_REGION );
|
( portPRIVILEGED_FLASH_REGION );
|
||||||
|
@ -620,7 +670,7 @@ extern uint32_t __privileged_data_end__;
|
||||||
( 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
|
||||||
is placed. */
|
* is placed. */
|
||||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
( portPRIVILEGED_RAM_REGION );
|
( portPRIVILEGED_RAM_REGION );
|
||||||
|
@ -631,7 +681,7 @@ extern uint32_t __privileged_data_end__;
|
||||||
( portMPU_REGION_ENABLE );
|
( portMPU_REGION_ENABLE );
|
||||||
|
|
||||||
/* By default allow everything to access the general peripherals. The
|
/* By default allow everything to access the general peripherals. The
|
||||||
system peripherals and registers are protected. */
|
* system peripherals and registers are protected. */
|
||||||
portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) |
|
portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) |
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
( portGENERAL_PERIPHERALS_REGION );
|
( portGENERAL_PERIPHERALS_REGION );
|
||||||
|
@ -654,7 +704,7 @@ static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes )
|
||||||
uint32_t ulRegionSize, ulReturnValue = 4;
|
uint32_t ulRegionSize, ulReturnValue = 4;
|
||||||
|
|
||||||
/* 32 is the smallest region size, 31 is the largest valid value for
|
/* 32 is the smallest region size, 31 is the largest valid value for
|
||||||
ulReturnValue. */
|
* ulReturnValue. */
|
||||||
for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) )
|
for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) )
|
||||||
{
|
{
|
||||||
if( ulActualSizeInBytes <= ulRegionSize )
|
if( ulActualSizeInBytes <= ulRegionSize )
|
||||||
|
@ -668,7 +718,7 @@ uint32_t ulRegionSize, ulReturnValue = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shift the code by one before returning so it can be written directly
|
/* Shift the code by one before returning so it can be written directly
|
||||||
into the the correct bit position of the attribute register. */
|
* into the the correct bit position of the attribute register. */
|
||||||
return ( ulReturnValue << 1UL );
|
return ( ulReturnValue << 1UL );
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
@ -723,7 +773,7 @@ uint32_t ul;
|
||||||
( portMPU_REGION_ENABLE );
|
( portMPU_REGION_ENABLE );
|
||||||
|
|
||||||
/* Re-instate the privileged only RAM region as xRegion[ 0 ] will have
|
/* Re-instate the privileged only RAM region as xRegion[ 0 ] will have
|
||||||
just removed the privileged only parameters. */
|
* just removed the privileged only parameters. */
|
||||||
xMPUSettings->xRegion[ 1 ].ulRegionBaseAddress =
|
xMPUSettings->xRegion[ 1 ].ulRegionBaseAddress =
|
||||||
( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
|
@ -745,9 +795,9 @@ uint32_t ul;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* This function is called automatically when the task is created - in
|
/* This function is called automatically when the task is created - in
|
||||||
which case the stack region parameters will be valid. At all other
|
* which case the stack region parameters will be valid. At all other
|
||||||
times the stack parameters will not be valid and it is assumed that the
|
* times the stack parameters will not be valid and it is assumed that the
|
||||||
stack region has already been configured. */
|
* stack region has already been configured. */
|
||||||
if( ulStackDepth > 0 )
|
if( ulStackDepth > 0 )
|
||||||
{
|
{
|
||||||
/* Define the region that allows access to the stack. */
|
/* Define the region that allows access to the stack. */
|
||||||
|
@ -770,8 +820,8 @@ uint32_t ul;
|
||||||
if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL )
|
if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL )
|
||||||
{
|
{
|
||||||
/* Translate the generic region definition contained in
|
/* Translate the generic region definition contained in
|
||||||
xRegions into the CM3 specific MPU settings that are then
|
* xRegions into the CM3 specific MPU settings that are then
|
||||||
stored in xMPUSettings. */
|
* stored in xMPUSettings. */
|
||||||
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress =
|
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress =
|
||||||
( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) |
|
( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) |
|
||||||
( portMPU_REGION_VALID ) |
|
( portMPU_REGION_VALID ) |
|
||||||
|
@ -821,47 +871,46 @@ __asm uint32_t prvPortGetIPSR( void )
|
||||||
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||||
|
|
||||||
/* The following assertion will fail if a service routine (ISR) for
|
/* The following assertion will fail if a service routine (ISR) for
|
||||||
an interrupt that has been assigned a priority above
|
* an interrupt that has been assigned a priority above
|
||||||
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||||
function. ISR safe FreeRTOS API functions must *only* be called
|
* function. ISR safe FreeRTOS API functions must *only* be called
|
||||||
from interrupts that have been assigned a priority at or below
|
* from interrupts that have been assigned a priority at or below
|
||||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
Numerically low interrupt priority numbers represent logically high
|
* Numerically low interrupt priority numbers represent logically high
|
||||||
interrupt priorities, therefore the priority of the interrupt must
|
* interrupt priorities, therefore the priority of the interrupt must
|
||||||
be set to a value equal to or numerically *higher* than
|
* be set to a value equal to or numerically *higher* than
|
||||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
Interrupts that use the FreeRTOS API must not be left at their
|
* Interrupts that use the FreeRTOS API must not be left at their
|
||||||
default priority of zero as that is the highest possible priority,
|
* default priority of zero as that is the highest possible priority,
|
||||||
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
* which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||||
and therefore also guaranteed to be invalid.
|
* and therefore also guaranteed to be invalid.
|
||||||
|
|
||||||
FreeRTOS maintains separate thread and ISR API functions to ensure
|
* FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||||
interrupt entry is as fast and simple as possible.
|
* interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
The following links provide detailed information:
|
* The following links provide detailed information:
|
||||||
http://www.freertos.org/RTOS-Cortex-M3-M4.html
|
* http://www.freertos.org/RTOS-Cortex-M3-M4.html
|
||||||
http://www.freertos.org/FAQHelp.html */
|
* http://www.freertos.org/FAQHelp.html */
|
||||||
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
||||||
that define each interrupt's priority to be split between bits that
|
* that define each interrupt's priority to be split between bits that
|
||||||
define the interrupt's pre-emption priority bits and bits that define
|
* define the interrupt's pre-emption priority bits and bits that define
|
||||||
the interrupt's sub-priority. For simplicity all bits must be defined
|
* the interrupt's sub-priority. For simplicity all bits must be defined
|
||||||
to be pre-emption priority bits. The following assertion will fail if
|
* to be pre-emption priority bits. The following assertion will fail if
|
||||||
this is not the case (if some bits represent a sub-priority).
|
* this is not the case (if some bits represent a sub-priority).
|
||||||
|
|
||||||
If the application only uses CMSIS libraries for interrupt
|
* If the application only uses CMSIS libraries for interrupt
|
||||||
configuration then the correct setting can be achieved on all Cortex-M
|
* configuration then the correct setting can be achieved on all Cortex-M
|
||||||
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
* devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||||
scheduler. Note however that some vendor specific peripheral libraries
|
* scheduler. Note however that some vendor specific peripheral libraries
|
||||||
assume a non-zero priority group setting, in which cases using a value
|
* assume a non-zero priority group setting, in which cases using a value
|
||||||
of zero will result in unpredicable behaviour. */
|
* of zero will result in unpredicable behaviour. */
|
||||||
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* configASSERT_DEFINED */
|
#endif /* configASSERT_DEFINED */
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,7 @@ typedef unsigned long UBaseType_t;
|
||||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
|
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
|
||||||
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
|
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
|
||||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
|
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
|
||||||
|
#define portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ( 0x02UL << 24UL )
|
||||||
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
|
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
|
||||||
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
|
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
|
||||||
|
|
||||||
|
@ -301,6 +302,12 @@ BaseType_t xReturn;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY
|
||||||
|
#warning "configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY is not defined. We recommend defining it to 1 in FreeRTOSConfig.h for better security."
|
||||||
|
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 0
|
||||||
|
#endif
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -679,7 +679,7 @@ void xPortSysTickHandler( void )
|
||||||
*/
|
*/
|
||||||
#if( configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 )
|
#if( configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 )
|
||||||
|
|
||||||
void vPortSetupTimerInterrupt( void )
|
__weak void vPortSetupTimerInterrupt( void )
|
||||||
{
|
{
|
||||||
/* Calculate the constants required to configure the tick interrupt. */
|
/* Calculate the constants required to configure the tick interrupt. */
|
||||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||||
|
|
150
portable/ThirdParty/CDK/T-HEAD_CK802/port.c
vendored
Normal file
150
portable/ThirdParty/CDK/T-HEAD_CK802/port.c
vendored
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. 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.
|
||||||
|
*
|
||||||
|
* 1 tab == 4 spaces!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Kernel includes. */
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
extern void vPortStartTask(void);
|
||||||
|
|
||||||
|
/* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This
|
||||||
|
will be set to 0 prior to the first task being started. */
|
||||||
|
portLONG ulCriticalNesting = 0x9999UL;
|
||||||
|
|
||||||
|
/* Used to record one tack want to swtich task after enter critical area, we need know it
|
||||||
|
* and implement task switch after exit critical area */
|
||||||
|
portLONG pendsvflag = 0;
|
||||||
|
|
||||||
|
StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||||
|
{
|
||||||
|
StackType_t *stk = NULL;
|
||||||
|
|
||||||
|
stk = pxTopOfStack;
|
||||||
|
|
||||||
|
*(--stk) = (uint32_t)pxCode; /* Entry Point */
|
||||||
|
*(--stk) = (uint32_t)0xE0000140L; /* PSR */
|
||||||
|
*(--stk) = (uint32_t)0xFFFFFFFEL; /* R15 (LR) (init value will cause fault if ever used) */
|
||||||
|
*(--stk) = (uint32_t)0x13131313L; /* R13 */
|
||||||
|
*(--stk) = (uint32_t)0x12121212L; /* R12 */
|
||||||
|
*(--stk) = (uint32_t)0x11111111L; /* R11 */
|
||||||
|
*(--stk) = (uint32_t)0x10101010L; /* R10 */
|
||||||
|
*(--stk) = (uint32_t)0x09090909L; /* R9 */
|
||||||
|
*(--stk) = (uint32_t)0x08080808L; /* R8 */
|
||||||
|
*(--stk) = (uint32_t)0x07070707L; /* R7 */
|
||||||
|
*(--stk) = (uint32_t)0x06060606L; /* R6 */
|
||||||
|
*(--stk) = (uint32_t)0x05050505L; /* R5 */
|
||||||
|
*(--stk) = (uint32_t)0x04040404L; /* R4 */
|
||||||
|
*(--stk) = (uint32_t)0x03030303L; /* R3 */
|
||||||
|
*(--stk) = (uint32_t)0x02020202L; /* R2 */
|
||||||
|
*(--stk) = (uint32_t)0x01010101L; /* R1 */
|
||||||
|
*(--stk) = (uint32_t)pvParameters; /* R0 : argument */
|
||||||
|
|
||||||
|
return stk;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseType_t xPortStartScheduler( void )
|
||||||
|
{
|
||||||
|
ulCriticalNesting = 0UL;
|
||||||
|
|
||||||
|
vPortStartTask();
|
||||||
|
|
||||||
|
return pdFALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void vPortEndScheduler( void )
|
||||||
|
{
|
||||||
|
/* Not implemented as there is nothing to return to. */
|
||||||
|
}
|
||||||
|
|
||||||
|
void vPortEnterCritical( void )
|
||||||
|
{
|
||||||
|
portDISABLE_INTERRUPTS();
|
||||||
|
ulCriticalNesting ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vPortExitCritical( void )
|
||||||
|
{
|
||||||
|
if (ulCriticalNesting == 0) {
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ulCriticalNesting --;
|
||||||
|
if (ulCriticalNesting == 0)
|
||||||
|
{
|
||||||
|
portENABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
if (pendsvflag)
|
||||||
|
{
|
||||||
|
pendsvflag = 0;
|
||||||
|
portYIELD();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if configUSE_PREEMPTION == 0
|
||||||
|
void xPortSysTickHandler( void )
|
||||||
|
{
|
||||||
|
portLONG ulDummy;
|
||||||
|
|
||||||
|
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
|
xTaskIncrementTick();
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
void xPortSysTickHandler( void )
|
||||||
|
{
|
||||||
|
portLONG ulDummy;
|
||||||
|
|
||||||
|
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
|
{
|
||||||
|
if (xTaskIncrementTick() != pdFALSE)
|
||||||
|
{
|
||||||
|
portYIELD_FROM_ISR(pdTRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void vPortYieldHandler( void )
|
||||||
|
{
|
||||||
|
uint32_t ulSavedInterruptMask;
|
||||||
|
|
||||||
|
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
|
|
||||||
|
vTaskSwitchContext();
|
||||||
|
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName )
|
||||||
|
{
|
||||||
|
for(;;);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void vApplicationMallocFailedHook( void )
|
||||||
|
{
|
||||||
|
for(;;);
|
||||||
|
}
|
126
portable/ThirdParty/CDK/T-HEAD_CK802/portasm.S
vendored
Normal file
126
portable/ThirdParty/CDK/T-HEAD_CK802/portasm.S
vendored
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. 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.
|
||||||
|
*
|
||||||
|
* 1 tab == 4 spaces!
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#include <csi_config.h>
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Functions: vPortStartTask
|
||||||
|
*
|
||||||
|
********************************************************************/
|
||||||
|
.global vPortStartTask
|
||||||
|
.type vPortStartTask, %function
|
||||||
|
vPortStartTask:
|
||||||
|
psrclr ie
|
||||||
|
lrw r4, pxCurrentTCB
|
||||||
|
ld.w r4, (r4) // the current task stack pointer is the first member
|
||||||
|
ld.w sp, (r4)
|
||||||
|
|
||||||
|
ldw r0, (sp, 64)
|
||||||
|
mtcr r0, epc
|
||||||
|
ldw r0, (sp, 60)
|
||||||
|
mtcr r0, epsr
|
||||||
|
ldw r15, (sp, 56)
|
||||||
|
ldm r0-r13, (sp)
|
||||||
|
addi sp, 68
|
||||||
|
rte
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Functions: vPortYield
|
||||||
|
*
|
||||||
|
********************************************************************/
|
||||||
|
.global vPortYield
|
||||||
|
.type vPortYield, %function
|
||||||
|
vPortYield:
|
||||||
|
psrclr ee
|
||||||
|
subi sp, 68
|
||||||
|
stm r0-r13, (sp)
|
||||||
|
stw r15, (sp, 56)
|
||||||
|
mfcr r0, psr
|
||||||
|
bseti r0, 8
|
||||||
|
stw r0, (sp, 60)
|
||||||
|
stw r15, (sp, 64)
|
||||||
|
|
||||||
|
lrw r2, pxCurrentTCB
|
||||||
|
ld.w r3, (r2)
|
||||||
|
st.w sp, (r3)
|
||||||
|
|
||||||
|
jbsr vTaskSwitchContext
|
||||||
|
lrw r4, pxCurrentTCB
|
||||||
|
ld.w r4, (r4)
|
||||||
|
ld.w sp, (r4)
|
||||||
|
|
||||||
|
ldw r0, (sp, 64)
|
||||||
|
mtcr r0, epc
|
||||||
|
ldw r0, (sp, 60)
|
||||||
|
mtcr r0, epsr
|
||||||
|
ldw r15, (sp, 56)
|
||||||
|
ldm r0-r13, (sp)
|
||||||
|
addi sp, 68
|
||||||
|
|
||||||
|
rte
|
||||||
|
|
||||||
|
/********************************************************************
|
||||||
|
* Functions: NOVIC_IRQ_Default_Handler
|
||||||
|
*
|
||||||
|
********************************************************************/
|
||||||
|
.global NOVIC_IRQ_Default_Handler
|
||||||
|
.type NOVIC_IRQ_Default_Handler, %function
|
||||||
|
NOVIC_IRQ_Default_Handler:
|
||||||
|
psrset ee
|
||||||
|
subi sp, 68
|
||||||
|
stm r0-r13, (sp)
|
||||||
|
stw r15, (sp, 56)
|
||||||
|
mfcr r0, epsr
|
||||||
|
stw r0, (sp, 60)
|
||||||
|
mfcr r0, epc
|
||||||
|
stw r0, (sp, 64)
|
||||||
|
|
||||||
|
lrw r7, pxCurrentTCB
|
||||||
|
ldw r7, (r7)
|
||||||
|
stw sp, (r7)
|
||||||
|
|
||||||
|
lrw sp, g_top_irqstack
|
||||||
|
|
||||||
|
lrw r1, g_irqvector
|
||||||
|
mfcr r0, psr
|
||||||
|
lsri r0, 16
|
||||||
|
sextb r0
|
||||||
|
subi r0, 32
|
||||||
|
lsli r0, 2
|
||||||
|
add r1, r0
|
||||||
|
ldw r1, (r1)
|
||||||
|
lsri r0, 2
|
||||||
|
jsr r1
|
||||||
|
|
||||||
|
lrw r7, pxCurrentTCB
|
||||||
|
ldw r7, (r7)
|
||||||
|
ldw sp, (r7)
|
||||||
|
|
||||||
|
ldw r0, (sp, 64)
|
||||||
|
mtcr r0, epc
|
||||||
|
ldw r0, (sp, 60)
|
||||||
|
mtcr r0, epsr
|
||||||
|
ldm r0-r13, (sp)
|
||||||
|
ldw r15, (sp, 56)
|
||||||
|
addi sp, 68
|
||||||
|
rte
|
159
portable/ThirdParty/CDK/T-HEAD_CK802/portmacro.h
vendored
Normal file
159
portable/ThirdParty/CDK/T-HEAD_CK802/portmacro.h
vendored
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2017 C-SKY Microsystems Co., Ltd. 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.
|
||||||
|
*
|
||||||
|
* 1 tab == 4 spaces!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PORTMACRO_H
|
||||||
|
#define PORTMACRO_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <csi_core.h>
|
||||||
|
|
||||||
|
extern void vPortYield(void);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
class vPortYield;
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Port specific definitions.
|
||||||
|
*
|
||||||
|
* The settings in this file configure FreeRTOS correctly for the
|
||||||
|
* given hardware and compiler.
|
||||||
|
*
|
||||||
|
* These settings should not be altered.
|
||||||
|
*-----------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Type definitions. */
|
||||||
|
#define portCHAR char
|
||||||
|
#define portFLOAT float
|
||||||
|
#define portDOUBLE double
|
||||||
|
#define portLONG long
|
||||||
|
#define portSHORT short
|
||||||
|
#define portSTACK_TYPE uint32_t
|
||||||
|
#define portBASE_TYPE long
|
||||||
|
|
||||||
|
typedef portSTACK_TYPE StackType_t;
|
||||||
|
typedef long BaseType_t;
|
||||||
|
typedef unsigned long UBaseType_t;
|
||||||
|
typedef void (*portvectorfunc)(void);
|
||||||
|
|
||||||
|
#if( configUSE_16_BIT_TICKS == 1 )
|
||||||
|
typedef uint16_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||||
|
#else
|
||||||
|
typedef uint32_t TickType_t;
|
||||||
|
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Hardware specifics. */
|
||||||
|
#define portBYTE_ALIGNMENT 8
|
||||||
|
#define portSTACK_GROWTH -1
|
||||||
|
#define portMS_PERIOD_TICK 10
|
||||||
|
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||||
|
|
||||||
|
|
||||||
|
static inline void vPortEnableInterrupt( void )
|
||||||
|
{
|
||||||
|
__enable_irq();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void vPortDisableInterrupt( void )
|
||||||
|
{
|
||||||
|
__disable_irq();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline portLONG GetCurrentPSR (void)
|
||||||
|
{
|
||||||
|
return __get_PSR();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline portLONG SaveLocalPSR (void)
|
||||||
|
{
|
||||||
|
portLONG flags = __get_PSR();
|
||||||
|
__disable_irq();
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void RestoreLocalPSR (portLONG newMask)
|
||||||
|
{
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"mtcr %0, psr \n"
|
||||||
|
:
|
||||||
|
:"r" (newMask)
|
||||||
|
:"memory"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void vPortEnterCritical( void );
|
||||||
|
extern void vPortExitCritical( void );
|
||||||
|
extern __attribute__((naked)) void cpu_yeild(void);
|
||||||
|
|
||||||
|
#define portDISABLE_INTERRUPTS() vPortDisableInterrupt()
|
||||||
|
#define portENABLE_INTERRUPTS() vPortEnableInterrupt()
|
||||||
|
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||||
|
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||||
|
#define portSET_INTERRUPT_MASK_FROM_ISR() SaveLocalPSR()
|
||||||
|
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(a) RestoreLocalPSR(a)
|
||||||
|
|
||||||
|
#define portNOP() asm("nop")
|
||||||
|
|
||||||
|
extern portLONG ulCriticalNesting;
|
||||||
|
extern portLONG pendsvflag;
|
||||||
|
|
||||||
|
#define portYIELD() if (ulCriticalNesting == 0) \
|
||||||
|
{ \
|
||||||
|
vPortYield(); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
pendsvflag = 1; \
|
||||||
|
} \
|
||||||
|
portNOP();portNOP()
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||||
|
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) __attribute__((noreturn))
|
||||||
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define portEND_SWITCHING_ISR( xSwitchRequired ) do { \
|
||||||
|
if( xSwitchRequired != pdFALSE ) \
|
||||||
|
{ \
|
||||||
|
portYIELD(); \
|
||||||
|
} \
|
||||||
|
}while(0)
|
||||||
|
|
||||||
|
#define portYIELD_FROM_ISR( a ) vTaskSwitchContext()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* PORTMACRO_H */
|
||||||
|
|
6
portable/ThirdParty/GCC/RISC-V/README-for-info-on-official-MIT-license-port.txt
vendored
Normal file
6
portable/ThirdParty/GCC/RISC-V/README-for-info-on-official-MIT-license-port.txt
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
The official and MIT licensed FreeRTOS ports for RISC-V are located in the following directories:
|
||||||
|
\FreeRTOS\Source\portable\GCC\RISC-V
|
||||||
|
\FreeRTOS\Source\portable\IAR\RISC-V
|
||||||
|
|
||||||
|
Also so https://www.freertos.org/Using-FreeRTOS-on-RISC-V.html
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue