mirror of
https://github.com/ADElectronics/RTL00_WEB_WS2812.git
synced 2025-07-31 20:31:07 +00:00
1st
This commit is contained in:
parent
7f07f696e1
commit
c6c5eeed6f
1170 changed files with 608790 additions and 1 deletions
1402
Firmware/RTLGDB/USDK/component/os/freertos/cmsis_os.c
Normal file
1402
Firmware/RTLGDB/USDK/component/os/freertos/cmsis_os.c
Normal file
File diff suppressed because it is too large
Load diff
819
Firmware/RTLGDB/USDK/component/os/freertos/cmsis_os.h
Normal file
819
Firmware/RTLGDB/USDK/component/os/freertos/cmsis_os.h
Normal file
|
|
@ -0,0 +1,819 @@
|
|||
/* ----------------------------------------------------------------------
|
||||
* $Date: 5. February 2013
|
||||
* $Revision: V1.02
|
||||
*
|
||||
* Project: CMSIS-RTOS API
|
||||
* Title: cmsis_os.h template header file
|
||||
*
|
||||
* Version 0.02
|
||||
* Initial Proposal Phase
|
||||
* Version 0.03
|
||||
* osKernelStart added, optional feature: main started as thread
|
||||
* osSemaphores have standard behavior
|
||||
* osTimerCreate does not start the timer, added osTimerStart
|
||||
* osThreadPass is renamed to osThreadYield
|
||||
* Version 1.01
|
||||
* Support for C++ interface
|
||||
* - const attribute removed from the osXxxxDef_t typedef's
|
||||
* - const attribute added to the osXxxxDef macros
|
||||
* Added: osTimerDelete, osMutexDelete, osSemaphoreDelete
|
||||
* Added: osKernelInitialize
|
||||
* Version 1.02
|
||||
* Control functions for short timeouts in microsecond resolution:
|
||||
* Added: osKernelSysTick, osKernelSysTickFrequency, osKernelSysTickMicroSec
|
||||
* Removed: osSignalGet
|
||||
*----------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2013 ARM LIMITED
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* - Neither the name of ARM nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "timers.h"
|
||||
#include "queue.h"
|
||||
#include "semphr.h"
|
||||
|
||||
|
||||
#define FREERTOS_VERSION 0x00080001 // bits[31:16] main version, bits[15:0] sub-version
|
||||
|
||||
#if FREERTOS_VERSION >= 0x00080000
|
||||
#define configSignalManagementSupport 1
|
||||
#else
|
||||
#define configSignalManagementSupport 0
|
||||
#endif
|
||||
|
||||
#if configSignalManagementSupport
|
||||
#include "event_groups.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
\page cmsis_os_h Header File Template: cmsis_os.h
|
||||
|
||||
The file \b cmsis_os.h is a template header file for a CMSIS-RTOS compliant Real-Time Operating System (RTOS).
|
||||
Each RTOS that is compliant with CMSIS-RTOS shall provide a specific \b cmsis_os.h header file that represents
|
||||
its implementation.
|
||||
|
||||
The file cmsis_os.h contains:
|
||||
- CMSIS-RTOS API function definitions
|
||||
- struct definitions for parameters and return types
|
||||
- status and priority values used by CMSIS-RTOS API functions
|
||||
- macros for defining threads and other kernel objects
|
||||
|
||||
|
||||
<b>Name conventions and header file modifications</b>
|
||||
|
||||
All definitions are prefixed with \b os to give an unique name space for CMSIS-RTOS functions.
|
||||
Definitions that are prefixed \b os_ are not used in the application code but local to this header file.
|
||||
All definitions and functions that belong to a module are grouped and have a common prefix, i.e. \b osThread.
|
||||
|
||||
Definitions that are marked with <b>CAN BE CHANGED</b> can be adapted towards the needs of the actual CMSIS-RTOS implementation.
|
||||
These definitions can be specific to the underlying RTOS kernel.
|
||||
|
||||
Definitions that are marked with <b>MUST REMAIN UNCHANGED</b> cannot be altered. Otherwise the CMSIS-RTOS implementation is no longer
|
||||
compliant to the standard. Note that some functions are optional and need not to be provided by every CMSIS-RTOS implementation.
|
||||
|
||||
|
||||
<b>Function calls from interrupt service routines</b>
|
||||
|
||||
The following CMSIS-RTOS functions can be called from threads and interrupt service routines (ISR):
|
||||
- \ref osSignalSet
|
||||
- \ref osSemaphoreRelease
|
||||
- \ref osPoolAlloc, \ref osPoolCAlloc, \ref osPoolFree
|
||||
- \ref osMessagePut, \ref osMessageGet
|
||||
- \ref osMailAlloc, \ref osMailCAlloc, \ref osMailGet, \ref osMailPut, \ref osMailFree
|
||||
|
||||
Functions that cannot be called from an ISR are verifying the interrupt status and return in case that they are called
|
||||
from an ISR context the status code \b osErrorISR. In some implementations this condition might be caught using the HARD FAULT vector.
|
||||
|
||||
Some CMSIS-RTOS implementations support CMSIS-RTOS function calls from multiple ISR at the same time.
|
||||
If this is impossible, the CMSIS-RTOS rejects calls by nested ISR functions with the status code \b osErrorISRRecursive.
|
||||
|
||||
|
||||
<b>Define and reference object definitions</b>
|
||||
|
||||
With <b>\#define osObjectsExternal</b> objects are defined as external symbols. This allows to create a consistent header file
|
||||
that is used throughout a project as shown below:
|
||||
|
||||
<i>Header File</i>
|
||||
\code
|
||||
#include <cmsis_os.h> // CMSIS RTOS header file
|
||||
|
||||
// Thread definition
|
||||
extern void thread_sample (void const *argument); // function prototype
|
||||
osThreadDef (thread_sample, osPriorityBelowNormal, 1, 100);
|
||||
|
||||
// Pool definition
|
||||
osPoolDef(MyPool, 10, long);
|
||||
\endcode
|
||||
|
||||
|
||||
This header file defines all objects when included in a C/C++ source file. When <b>\#define osObjectsExternal</b> is
|
||||
present before the header file, the objects are defined as external symbols. A single consistent header file can therefore be
|
||||
used throughout the whole project.
|
||||
|
||||
<i>Example</i>
|
||||
\code
|
||||
#include "osObjects.h" // Definition of the CMSIS-RTOS objects
|
||||
\endcode
|
||||
|
||||
\code
|
||||
#define osObjectExternal // Objects will be defined as external symbols
|
||||
#include "osObjects.h" // Reference to the CMSIS-RTOS objects
|
||||
\endcode
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _CMSIS_OS_H
|
||||
#define _CMSIS_OS_H
|
||||
|
||||
/// \note MUST REMAIN UNCHANGED: \b osCMSIS identifies the CMSIS-RTOS API version.
|
||||
#define osCMSIS 0x10002 ///< API version (main [31:16] .sub [15:0])
|
||||
|
||||
/// \note CAN BE CHANGED: \b osCMSIS_KERNEL identifies the underlying RTOS kernel and version number.
|
||||
#define osCMSIS_KERNEL 0x10000 ///< RTOS identification and version (main [31:16] .sub [15:0])
|
||||
|
||||
/// \note MUST REMAIN UNCHANGED: \b osKernelSystemId shall be consistent in every CMSIS-RTOS.
|
||||
#define osKernelSystemId "KERNEL V1.00" ///< RTOS identification string
|
||||
|
||||
/// \note MUST REMAIN UNCHANGED: \b osFeature_xxx shall be consistent in every CMSIS-RTOS.
|
||||
#define osFeature_MainThread 1 ///< main thread 1=main can be thread, 0=not available
|
||||
#define osFeature_Pool 1 ///< Memory Pools: 1=available, 0=not available
|
||||
#define osFeature_MailQ 1 ///< Mail Queues: 1=available, 0=not available
|
||||
#define osFeature_MessageQ 1 ///< Message Queues: 1=available, 0=not available
|
||||
#define osFeature_Signals 8 ///< maximum number of Signal Flags available per thread
|
||||
#define osFeature_Semaphore 30 ///< maximum count for \ref osSemaphoreCreate function
|
||||
#define osFeature_Wait 1 ///< osWait function: 1=available, 0=not available
|
||||
#define osFeature_SysTick 1 ///< osKernelSysTick functions: 1=available, 0=not available
|
||||
|
||||
//#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
// ==== Enumeration, structures, defines ====
|
||||
|
||||
/// Priority used for thread control.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osPriority shall be consistent in every CMSIS-RTOS.
|
||||
typedef enum {
|
||||
osPriorityIdle = -3, ///< priority: idle (lowest)
|
||||
osPriorityLow = -2, ///< priority: low
|
||||
osPriorityBelowNormal = -1, ///< priority: below normal
|
||||
osPriorityNormal = 0, ///< priority: normal (default)
|
||||
osPriorityAboveNormal = +1, ///< priority: above normal
|
||||
osPriorityHigh = +2, ///< priority: high
|
||||
osPriorityRealtime = +3, ///< priority: realtime (highest)
|
||||
osPriorityError = 0x84 ///< system cannot determine priority or thread has illegal priority
|
||||
} osPriority;
|
||||
|
||||
/// Timeout value.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osWaitForever shall be consistent in every CMSIS-RTOS.
|
||||
#define osWaitForever 0xFFFFFFFF ///< wait forever timeout value
|
||||
|
||||
/// Status code values returned by CMSIS-RTOS functions.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osStatus shall be consistent in every CMSIS-RTOS.
|
||||
typedef enum {
|
||||
osOK = 0, ///< function completed; no error or event occurred.
|
||||
osEventSignal = 0x08, ///< function completed; signal event occurred.
|
||||
osEventMessage = 0x10, ///< function completed; message event occurred.
|
||||
osEventMail = 0x20, ///< function completed; mail event occurred.
|
||||
osEventTimeout = 0x40, ///< function completed; timeout occurred.
|
||||
osErrorParameter = 0x80, ///< parameter error: a mandatory parameter was missing or specified an incorrect object.
|
||||
osErrorResource = 0x81, ///< resource not available: a specified resource was not available.
|
||||
osErrorTimeoutResource = 0xC1, ///< resource not available within given time: a specified resource was not available within the timeout period.
|
||||
osErrorISR = 0x82, ///< not allowed in ISR context: the function cannot be called from interrupt service routines.
|
||||
osErrorISRRecursive = 0x83, ///< function called multiple times from ISR with same object.
|
||||
osErrorPriority = 0x84, ///< system cannot determine priority or thread has illegal priority.
|
||||
osErrorNoMemory = 0x85, ///< system is out of memory: it was impossible to allocate or reserve memory for the operation.
|
||||
osErrorValue = 0x86, ///< value of a parameter is out of range.
|
||||
osErrorOS = 0xFF, ///< unspecified RTOS error: run-time error but no other error message fits.
|
||||
os_status_reserved = 0x7FFFFFFF ///< prevent from enum down-size compiler optimization.
|
||||
} osStatus;
|
||||
|
||||
|
||||
/// Timer type value for the timer definition.
|
||||
/// \note MUST REMAIN UNCHANGED: \b os_timer_type shall be consistent in every CMSIS-RTOS.
|
||||
typedef enum {
|
||||
osTimerOnce = 0, ///< one-shot timer
|
||||
osTimerPeriodic = 1 ///< repeating timer
|
||||
} os_timer_type;
|
||||
|
||||
/// Entry point of a thread.
|
||||
/// \note MUST REMAIN UNCHANGED: \b os_pthread shall be consistent in every CMSIS-RTOS.
|
||||
typedef void (*os_pthread) (void const *argument);
|
||||
|
||||
/// Entry point of a timer call back function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b os_ptimer shall be consistent in every CMSIS-RTOS.
|
||||
typedef void (*os_ptimer) (void const *argument);
|
||||
|
||||
// >>> the following data type definitions may shall adapted towards a specific RTOS
|
||||
|
||||
/// Thread ID identifies the thread (pointer to a thread control block).
|
||||
/// \note CAN BE CHANGED: \b os_thread_cb is implementation specific in every CMSIS-RTOS.
|
||||
typedef xTaskHandle osThreadId;
|
||||
|
||||
/// Timer ID identifies the timer (pointer to a timer control block).
|
||||
/// \note CAN BE CHANGED: \b os_timer_cb is implementation specific in every CMSIS-RTOS.
|
||||
typedef xTimerHandle osTimerId;
|
||||
|
||||
/// Mutex ID identifies the mutex (pointer to a mutex control block).
|
||||
/// \note CAN BE CHANGED: \b os_mutex_cb is implementation specific in every CMSIS-RTOS.
|
||||
typedef xSemaphoreHandle osMutexId;
|
||||
|
||||
/// Semaphore ID identifies the semaphore (pointer to a semaphore control block).
|
||||
/// \note CAN BE CHANGED: \b os_semaphore_cb is implementation specific in every CMSIS-RTOS.
|
||||
typedef xSemaphoreHandle osSemaphoreId;
|
||||
|
||||
/// Pool ID identifies the memory pool (pointer to a memory pool control block).
|
||||
/// \note CAN BE CHANGED: \b os_pool_cb is implementation specific in every CMSIS-RTOS.
|
||||
typedef struct os_pool_cb *osPoolId;
|
||||
|
||||
/// Message ID identifies the message queue (pointer to a message queue control block).
|
||||
/// \note CAN BE CHANGED: \b os_messageQ_cb is implementation specific in every CMSIS-RTOS.
|
||||
typedef xQueueHandle osMessageQId;
|
||||
|
||||
/// Mail ID identifies the mail queue (pointer to a mail queue control block).
|
||||
/// \note CAN BE CHANGED: \b os_mailQ_cb is implementation specific in every CMSIS-RTOS.
|
||||
typedef struct os_mailQ_cb *osMailQId;
|
||||
|
||||
|
||||
/// Thread Definition structure contains startup information of a thread.
|
||||
/// \note CAN BE CHANGED: \b os_thread_def is implementation specific in every CMSIS-RTOS.
|
||||
typedef struct os_thread_def {
|
||||
os_pthread pthread; ///< start address of thread function
|
||||
osPriority tpriority; ///< initial thread priority
|
||||
uint32_t instances; ///< maximum number of instances of that thread function
|
||||
uint32_t stacksize; ///< stack size requirements in bytes; 0 is default stack size
|
||||
char * name;
|
||||
} osThreadDef_t;
|
||||
|
||||
/// Timer Definition structure contains timer parameters.
|
||||
/// \note CAN BE CHANGED: \b os_timer_def is implementation specific in every CMSIS-RTOS.
|
||||
struct os_timer_custom {
|
||||
void *argument;
|
||||
};
|
||||
|
||||
typedef struct os_timer_def {
|
||||
os_ptimer ptimer; ///< start address of a timer function
|
||||
struct os_timer_custom *custom;
|
||||
} osTimerDef_t;
|
||||
|
||||
/// Mutex Definition structure contains setup information for a mutex.
|
||||
/// \note CAN BE CHANGED: \b os_mutex_def is implementation specific in every CMSIS-RTOS.
|
||||
typedef struct os_mutex_def {
|
||||
uint32_t dummy; ///< dummy value.
|
||||
} osMutexDef_t;
|
||||
|
||||
/// Semaphore Definition structure contains setup information for a semaphore.
|
||||
/// \note CAN BE CHANGED: \b os_semaphore_def is implementation specific in every CMSIS-RTOS.
|
||||
typedef struct os_semaphore_def {
|
||||
uint32_t dummy; ///< dummy value.
|
||||
} osSemaphoreDef_t;
|
||||
|
||||
/// Definition structure for memory block allocation
|
||||
/// \note CAN BE CHANGED: \b os_pool_def is implementation specific in every CMSIS-RTOS.
|
||||
typedef struct os_pool_def {
|
||||
uint32_t pool_sz; ///< number of items (elements) in the pool
|
||||
uint32_t item_sz; ///< size of an item
|
||||
void *pool; ///< pointer to memory for pool
|
||||
} osPoolDef_t;
|
||||
|
||||
/// Definition structure for message queue.
|
||||
/// \note CAN BE CHANGED: \b os_messageQ_def is implementation specific in every CMSIS-RTOS.
|
||||
typedef struct os_messageQ_def {
|
||||
uint32_t queue_sz; ///< number of elements in the queue
|
||||
uint32_t item_sz; ///< size of an item
|
||||
void *pool; ///< memory array for messages
|
||||
} osMessageQDef_t;
|
||||
|
||||
/// Definition structure for mail queue
|
||||
/// \note CAN BE CHANGED: \b os_mailQ_def is implementation specific in every CMSIS-RTOS.
|
||||
typedef struct os_mailQ_def {
|
||||
uint32_t queue_sz; ///< number of elements in the queue
|
||||
uint32_t item_sz; ///< size of an item
|
||||
struct os_mailQ_cb **cb;
|
||||
} osMailQDef_t;
|
||||
|
||||
/// Event structure contains detailed information about an event.
|
||||
/// \note MUST REMAIN UNCHANGED: \b os_event shall be consistent in every CMSIS-RTOS.
|
||||
/// However the struct may be extended at the end.
|
||||
typedef struct {
|
||||
osStatus status; ///< status code: event or error information
|
||||
union {
|
||||
uint32_t v; ///< message as 32-bit value
|
||||
void *p; ///< message or mail as void pointer
|
||||
int32_t signals; ///< signal flags
|
||||
} value; ///< event value
|
||||
union {
|
||||
osMailQId mail_id; ///< mail id obtained by \ref osMailCreate
|
||||
osMessageQId message_id; ///< message id obtained by \ref osMessageCreate
|
||||
} def; ///< event definition
|
||||
} osEvent;
|
||||
|
||||
|
||||
// ==== Kernel Control Functions ====
|
||||
|
||||
/// Initialize the RTOS Kernel for creating objects.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osKernelInitialize shall be consistent in every CMSIS-RTOS.
|
||||
osStatus osKernelInitialize (void);
|
||||
|
||||
/// Start the RTOS Kernel.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osKernelStart shall be consistent in every CMSIS-RTOS.
|
||||
osStatus osKernelStart (void);
|
||||
|
||||
/// Check if the RTOS kernel is already started.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osKernelRunning shall be consistent in every CMSIS-RTOS.
|
||||
/// \return 0 RTOS is not started, 1 RTOS is started.
|
||||
int32_t osKernelRunning(void);
|
||||
|
||||
#if (defined (osFeature_SysTick) && (osFeature_SysTick != 0)) // System Timer available
|
||||
|
||||
/// Get the RTOS kernel system timer counter
|
||||
/// \note MUST REMAIN UNCHANGED: \b osKernelSysTick shall be consistent in every CMSIS-RTOS.
|
||||
/// \return RTOS kernel system timer as 32-bit value
|
||||
uint32_t osKernelSysTick (void);
|
||||
|
||||
/// The RTOS kernel system timer frequency in Hz
|
||||
/// \note Reflects the system timer setting and is typically defined in a configuration file.
|
||||
#define osKernelSysTickFrequency configTICK_RATE_HZ
|
||||
|
||||
/// Convert a microseconds value to a RTOS kernel system timer value.
|
||||
/// \param microsec time value in microseconds.
|
||||
/// \return time value normalized to the \ref osKernelSysTickFrequency
|
||||
#define osKernelSysTickMicroSec(microsec) (((uint64_t)microsec * (osKernelSysTickFrequency)) / 1000000)
|
||||
|
||||
#endif // System Timer available
|
||||
|
||||
// ==== Thread Management ====
|
||||
|
||||
/// Create a Thread Definition with function, priority, and stack requirements.
|
||||
/// \param name name of the thread function.
|
||||
/// \param priority initial priority of the thread function.
|
||||
/// \param instances number of possible thread instances.
|
||||
/// \param stacksz stack size (in bytes) requirements for the thread function.
|
||||
/// \note CAN BE CHANGED: The parameters to \b osThreadDef shall be consistent but the
|
||||
/// macro body is implementation specific in every CMSIS-RTOS.
|
||||
#if defined (osObjectsExternal) // object is external
|
||||
#define osThreadDef(name, priority, instances, stacksz) \
|
||||
extern const osThreadDef_t os_thread_def_##name
|
||||
#else // define the object
|
||||
#define osThreadDef(name, priority, instances, stacksz) \
|
||||
const osThreadDef_t os_thread_def_##name = \
|
||||
{ (name), (priority), (instances), (stacksz), #name }
|
||||
#endif
|
||||
|
||||
/// Access a Thread definition.
|
||||
/// \param name name of the thread definition object.
|
||||
/// \note CAN BE CHANGED: The parameter to \b osThread shall be consistent but the
|
||||
/// macro body is implementation specific in every CMSIS-RTOS.
|
||||
#define osThread(name) \
|
||||
&os_thread_def_##name
|
||||
|
||||
/// Create a thread and add it to Active Threads and set it to state READY.
|
||||
/// \param[in] thread_def thread definition referenced with \ref osThread.
|
||||
/// \param[in] argument pointer that is passed to the thread function as start argument.
|
||||
/// \return thread ID for reference by other functions or NULL in case of error.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osThreadCreate shall be consistent in every CMSIS-RTOS.
|
||||
osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument);
|
||||
|
||||
/// Return the thread ID of the current running thread.
|
||||
/// \return thread ID for reference by other functions or NULL in case of error.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osThreadGetId shall be consistent in every CMSIS-RTOS.
|
||||
osThreadId osThreadGetId (void);
|
||||
|
||||
/// Terminate execution of a thread and remove it from Active Threads.
|
||||
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osThreadTerminate shall be consistent in every CMSIS-RTOS.
|
||||
osStatus osThreadTerminate (osThreadId thread_id);
|
||||
|
||||
/// Pass control to next thread that is in state \b READY.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osThreadYield shall be consistent in every CMSIS-RTOS.
|
||||
osStatus osThreadYield (void);
|
||||
|
||||
/// Change priority of an active thread.
|
||||
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
|
||||
/// \param[in] priority new priority value for the thread function.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osThreadSetPriority shall be consistent in every CMSIS-RTOS.
|
||||
osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority);
|
||||
|
||||
/// Get current priority of an active thread.
|
||||
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
|
||||
/// \return current priority value of the thread function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osThreadGetPriority shall be consistent in every CMSIS-RTOS.
|
||||
osPriority osThreadGetPriority (osThreadId thread_id);
|
||||
|
||||
|
||||
// ==== Generic Wait Functions ====
|
||||
|
||||
/// Wait for Timeout (Time Delay).
|
||||
/// \param[in] millisec time delay value
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus osDelay (uint32_t millisec);
|
||||
|
||||
#if (defined (osFeature_Wait) && (osFeature_Wait != 0)) // Generic Wait available
|
||||
|
||||
/// Wait for Signal, Message, Mail, or Timeout.
|
||||
/// \param[in] millisec timeout value or 0 in case of no time-out
|
||||
/// \return event that contains signal, message, or mail information or error code.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osWait shall be consistent in every CMSIS-RTOS.
|
||||
osEvent osWait (uint32_t millisec);
|
||||
|
||||
#endif // Generic Wait available
|
||||
|
||||
|
||||
// ==== Timer Management Functions ====
|
||||
/// Define a Timer object.
|
||||
/// \param name name of the timer object.
|
||||
/// \param function name of the timer call back function.
|
||||
/// \note CAN BE CHANGED: The parameter to \b osTimerDef shall be consistent but the
|
||||
/// macro body is implementation specific in every CMSIS-RTOS.
|
||||
#if defined (osObjectsExternal) // object is external
|
||||
#define osTimerDef(name, function) \
|
||||
extern const osTimerDef_t os_timer_def_##name; \
|
||||
extern struct os_timer_custom os_timer_custome_##name
|
||||
#else // define the object
|
||||
#define osTimerDef(name, function) \
|
||||
struct os_timer_custom os_timer_custom_##name; \
|
||||
const osTimerDef_t os_timer_def_##name = \
|
||||
{ (function), (&os_timer_custom_##name) }
|
||||
#endif
|
||||
|
||||
/// Access a Timer definition.
|
||||
/// \param name name of the timer object.
|
||||
/// \note CAN BE CHANGED: The parameter to \b osTimer shall be consistent but the
|
||||
/// macro body is implementation specific in every CMSIS-RTOS.
|
||||
#define osTimer(name) \
|
||||
&os_timer_def_##name
|
||||
|
||||
/// Create a timer.
|
||||
/// \param[in] timer_def timer object referenced with \ref osTimer.
|
||||
/// \param[in] type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior.
|
||||
/// \param[in] argument argument to the timer call back function.
|
||||
/// \return timer ID for reference by other functions or NULL in case of error.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osTimerCreate shall be consistent in every CMSIS-RTOS.
|
||||
osTimerId osTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void *argument);
|
||||
|
||||
/// Start or restart a timer.
|
||||
/// \param[in] timer_id timer ID obtained by \ref osTimerCreate.
|
||||
/// \param[in] millisec time delay value of the timer.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osTimerStart shall be consistent in every CMSIS-RTOS.
|
||||
osStatus osTimerStart (osTimerId timer_id, uint32_t millisec);
|
||||
|
||||
/// Stop the timer.
|
||||
/// \param[in] timer_id timer ID obtained by \ref osTimerCreate.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osTimerStop shall be consistent in every CMSIS-RTOS.
|
||||
osStatus osTimerStop (osTimerId timer_id);
|
||||
|
||||
/// Delete a timer that was created by \ref osTimerCreate.
|
||||
/// \param[in] timer_id timer ID obtained by \ref osTimerCreate.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osTimerDelete shall be consistent in every CMSIS-RTOS.
|
||||
osStatus osTimerDelete (osTimerId timer_id);
|
||||
|
||||
|
||||
// ==== Signal Management ====
|
||||
|
||||
/// Set the specified Signal Flags of an active thread.
|
||||
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
|
||||
/// \param[in] signals specifies the signal flags of the thread that should be set.
|
||||
/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osSignalSet shall be consistent in every CMSIS-RTOS.
|
||||
int32_t osSignalSet (osThreadId thread_id, int32_t signals);
|
||||
|
||||
/// Clear the specified Signal Flags of an active thread.
|
||||
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
|
||||
/// \param[in] signals specifies the signal flags of the thread that shall be cleared.
|
||||
/// \return previous signal flags of the specified thread or 0x80000000 in case of incorrect parameters.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osSignalClear shall be consistent in every CMSIS-RTOS.
|
||||
int32_t osSignalClear (osThreadId thread_id, int32_t signals);
|
||||
|
||||
/// Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread.
|
||||
/// \param[in] signals wait until all specified signal flags set or 0 for any single signal flag.
|
||||
/// \param[in] millisec timeout value or 0 in case of no time-out.
|
||||
/// \return event flag information or error code.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osSignalWait shall be consistent in every CMSIS-RTOS.
|
||||
osEvent osSignalWait (int32_t signals, uint32_t millisec);
|
||||
|
||||
|
||||
// ==== Mutex Management ====
|
||||
|
||||
/// Define a Mutex.
|
||||
/// \param name name of the mutex object.
|
||||
/// \note CAN BE CHANGED: The parameter to \b osMutexDef shall be consistent but the
|
||||
/// macro body is implementation specific in every CMSIS-RTOS.
|
||||
#if defined (osObjectsExternal) // object is external
|
||||
#define osMutexDef(name) \
|
||||
extern const osMutexDef_t os_mutex_def_##name
|
||||
#else // define the object
|
||||
#define osMutexDef(name) \
|
||||
const osMutexDef_t os_mutex_def_##name = { 0 }
|
||||
#endif
|
||||
|
||||
/// Access a Mutex definition.
|
||||
/// \param name name of the mutex object.
|
||||
/// \note CAN BE CHANGED: The parameter to \b osMutex shall be consistent but the
|
||||
/// macro body is implementation specific in every CMSIS-RTOS.
|
||||
#define osMutex(name) \
|
||||
&os_mutex_def_##name
|
||||
|
||||
/// Create and Initialize a Mutex object.
|
||||
/// \param[in] mutex_def mutex definition referenced with \ref osMutex.
|
||||
/// \return mutex ID for reference by other functions or NULL in case of error.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osMutexCreate shall be consistent in every CMSIS-RTOS.
|
||||
osMutexId osMutexCreate (const osMutexDef_t *mutex_def);
|
||||
|
||||
/// Wait until a Mutex becomes available.
|
||||
/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate.
|
||||
/// \param[in] millisec timeout value or 0 in case of no time-out.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osMutexWait shall be consistent in every CMSIS-RTOS.
|
||||
osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec);
|
||||
|
||||
/// Release a Mutex that was obtained by \ref osMutexWait.
|
||||
/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osMutexRelease shall be consistent in every CMSIS-RTOS.
|
||||
osStatus osMutexRelease (osMutexId mutex_id);
|
||||
|
||||
/// Delete a Mutex that was created by \ref osMutexCreate.
|
||||
/// \param[in] mutex_id mutex ID obtained by \ref osMutexCreate.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osMutexDelete shall be consistent in every CMSIS-RTOS.
|
||||
osStatus osMutexDelete (osMutexId mutex_id);
|
||||
|
||||
|
||||
// ==== Semaphore Management Functions ====
|
||||
|
||||
#if (defined (osFeature_Semaphore) && (osFeature_Semaphore != 0)) // Semaphore available
|
||||
|
||||
/// Define a Semaphore object.
|
||||
/// \param name name of the semaphore object.
|
||||
/// \note CAN BE CHANGED: The parameter to \b osSemaphoreDef shall be consistent but the
|
||||
/// macro body is implementation specific in every CMSIS-RTOS.
|
||||
#if defined (osObjectsExternal) // object is external
|
||||
#define osSemaphoreDef(name) \
|
||||
extern const osSemaphoreDef_t os_semaphore_def_##name
|
||||
#else // define the object
|
||||
#define osSemaphoreDef(name) \
|
||||
const osSemaphoreDef_t os_semaphore_def_##name = { 0 }
|
||||
#endif
|
||||
|
||||
/// Access a Semaphore definition.
|
||||
/// \param name name of the semaphore object.
|
||||
/// \note CAN BE CHANGED: The parameter to \b osSemaphore shall be consistent but the
|
||||
/// macro body is implementation specific in every CMSIS-RTOS.
|
||||
#define osSemaphore(name) \
|
||||
&os_semaphore_def_##name
|
||||
|
||||
/// Create and Initialize a Semaphore object used for managing resources.
|
||||
/// \param[in] semaphore_def semaphore definition referenced with \ref osSemaphore.
|
||||
/// \param[in] count number of available resources.
|
||||
/// \return semaphore ID for reference by other functions or NULL in case of error.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osSemaphoreCreate shall be consistent in every CMSIS-RTOS.
|
||||
osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count);
|
||||
|
||||
/// Wait until a Semaphore token becomes available.
|
||||
/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate.
|
||||
/// \param[in] millisec timeout value or 0 in case of no time-out.
|
||||
/// \return number of available tokens, or -1 in case of incorrect parameters.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS.
|
||||
int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec);
|
||||
|
||||
/// Release a Semaphore token.
|
||||
/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS.
|
||||
osStatus osSemaphoreRelease (osSemaphoreId semaphore_id);
|
||||
|
||||
/// Delete a Semaphore that was created by \ref osSemaphoreCreate.
|
||||
/// \param[in] semaphore_id semaphore object referenced with \ref osSemaphoreCreate.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osSemaphoreDelete shall be consistent in every CMSIS-RTOS.
|
||||
osStatus osSemaphoreDelete (osSemaphoreId semaphore_id);
|
||||
|
||||
#endif // Semaphore available
|
||||
|
||||
|
||||
// ==== Memory Pool Management Functions ====
|
||||
|
||||
#if (defined (osFeature_Pool) && (osFeature_Pool != 0)) // Memory Pool Management available
|
||||
|
||||
/// \brief Define a Memory Pool.
|
||||
/// \param name name of the memory pool.
|
||||
/// \param no maximum number of blocks (objects) in the memory pool.
|
||||
/// \param type data type of a single block (object).
|
||||
/// \note CAN BE CHANGED: The parameter to \b osPoolDef shall be consistent but the
|
||||
/// macro body is implementation specific in every CMSIS-RTOS.
|
||||
#if defined (osObjectsExternal) // object is external
|
||||
#define osPoolDef(name, no, type) \
|
||||
extern const osPoolDef_t os_pool_def_##name
|
||||
#else // define the object
|
||||
#define osPoolDef(name, no, type) \
|
||||
const osPoolDef_t os_pool_def_##name = \
|
||||
{ (no), sizeof(type), NULL }
|
||||
#endif
|
||||
|
||||
/// \brief Access a Memory Pool definition.
|
||||
/// \param name name of the memory pool
|
||||
/// \note CAN BE CHANGED: The parameter to \b osPool shall be consistent but the
|
||||
/// macro body is implementation specific in every CMSIS-RTOS.
|
||||
#define osPool(name) \
|
||||
&os_pool_def_##name
|
||||
|
||||
/// Create and Initialize a memory pool.
|
||||
/// \param[in] pool_def memory pool definition referenced with \ref osPool.
|
||||
/// \return memory pool ID for reference by other functions or NULL in case of error.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osPoolCreate shall be consistent in every CMSIS-RTOS.
|
||||
osPoolId osPoolCreate (const osPoolDef_t *pool_def);
|
||||
|
||||
/// Allocate a memory block from a memory pool.
|
||||
/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate.
|
||||
/// \return address of the allocated memory block or NULL in case of no memory available.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osPoolAlloc shall be consistent in every CMSIS-RTOS.
|
||||
void *osPoolAlloc (osPoolId pool_id);
|
||||
|
||||
/// Allocate a memory block from a memory pool and set memory block to zero.
|
||||
/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate.
|
||||
/// \return address of the allocated memory block or NULL in case of no memory available.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osPoolCAlloc shall be consistent in every CMSIS-RTOS.
|
||||
void *osPoolCAlloc (osPoolId pool_id);
|
||||
|
||||
/// Return an allocated memory block back to a specific memory pool.
|
||||
/// \param[in] pool_id memory pool ID obtain referenced with \ref osPoolCreate.
|
||||
/// \param[in] block address of the allocated memory block that is returned to the memory pool.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osPoolFree shall be consistent in every CMSIS-RTOS.
|
||||
osStatus osPoolFree (osPoolId pool_id, void *block);
|
||||
|
||||
#endif // Memory Pool Management available
|
||||
|
||||
|
||||
// ==== Message Queue Management Functions ====
|
||||
|
||||
#if (defined (osFeature_MessageQ) && (osFeature_MessageQ != 0)) // Message Queues available
|
||||
|
||||
/// \brief Create a Message Queue Definition.
|
||||
/// \param name name of the queue.
|
||||
/// \param queue_sz maximum number of messages in the queue.
|
||||
/// \param type data type of a single message element (for debugger).
|
||||
/// \note CAN BE CHANGED: The parameter to \b osMessageQDef shall be consistent but the
|
||||
/// macro body is implementation specific in every CMSIS-RTOS.
|
||||
#if defined (osObjectsExternal) // object is external
|
||||
#define osMessageQDef(name, queue_sz, type) \
|
||||
extern const osMessageQDef_t os_messageQ_def_##name
|
||||
#else // define the object
|
||||
#define osMessageQDef(name, queue_sz, type) \
|
||||
const osMessageQDef_t os_messageQ_def_##name = \
|
||||
{ (queue_sz), sizeof (type) }
|
||||
#endif
|
||||
|
||||
/// \brief Access a Message Queue Definition.
|
||||
/// \param name name of the queue
|
||||
/// \note CAN BE CHANGED: The parameter to \b osMessageQ shall be consistent but the
|
||||
/// macro body is implementation specific in every CMSIS-RTOS.
|
||||
#define osMessageQ(name) \
|
||||
&os_messageQ_def_##name
|
||||
|
||||
/// Create and Initialize a Message Queue.
|
||||
/// \param[in] queue_def queue definition referenced with \ref osMessageQ.
|
||||
/// \param[in] thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
|
||||
/// \return message queue ID for reference by other functions or NULL in case of error.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osMessageCreate shall be consistent in every CMSIS-RTOS.
|
||||
osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id);
|
||||
|
||||
/// Put a Message to a Queue.
|
||||
/// \param[in] queue_id message queue ID obtained with \ref osMessageCreate.
|
||||
/// \param[in] info message information.
|
||||
/// \param[in] millisec timeout value or 0 in case of no time-out.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osMessagePut shall be consistent in every CMSIS-RTOS.
|
||||
osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec);
|
||||
|
||||
/// Get a Message or Wait for a Message from a Queue.
|
||||
/// \param[in] queue_id message queue ID obtained with \ref osMessageCreate.
|
||||
/// \param[in] millisec timeout value or 0 in case of no time-out.
|
||||
/// \return event information that includes status code.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osMessageGet shall be consistent in every CMSIS-RTOS.
|
||||
osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec);
|
||||
|
||||
#endif // Message Queues available
|
||||
|
||||
|
||||
// ==== Mail Queue Management Functions ====
|
||||
|
||||
#if (defined (osFeature_MailQ) && (osFeature_MailQ != 0)) // Mail Queues available
|
||||
|
||||
/// \brief Create a Mail Queue Definition.
|
||||
/// \param name name of the queue
|
||||
/// \param queue_sz maximum number of messages in queue
|
||||
/// \param type data type of a single message element
|
||||
/// \note CAN BE CHANGED: The parameter to \b osMailQDef shall be consistent but the
|
||||
/// macro body is implementation specific in every CMSIS-RTOS.
|
||||
#if defined (osObjectsExternal) // object is external
|
||||
#define osMailQDef(name, queue_sz, type) \
|
||||
extern struct os_mailQ_cb *os_mailQ_cb_##name; \
|
||||
extern const osMailQDef_t os_mailQ_def_##name;
|
||||
#else // define the object
|
||||
#define osMailQDef(name, queue_sz, type) \
|
||||
struct os_mailQ_cb *os_mailQ_cb_##name; \
|
||||
const osMailQDef_t os_mailQ_def_##name = \
|
||||
{ (queue_sz), sizeof (type), (&os_mailQ_cb_##name) }
|
||||
#endif
|
||||
|
||||
/// \brief Access a Mail Queue Definition.
|
||||
/// \param name name of the queue
|
||||
/// \note CAN BE CHANGED: The parameter to \b osMailQ shall be consistent but the
|
||||
/// macro body is implementation specific in every CMSIS-RTOS.
|
||||
#define osMailQ(name) \
|
||||
&os_mailQ_def_##name
|
||||
|
||||
/// Create and Initialize mail queue.
|
||||
/// \param[in] queue_def reference to the mail queue definition obtain with \ref osMailQ
|
||||
/// \param[in] thread_id thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
|
||||
/// \return mail queue ID for reference by other functions or NULL in case of error.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osMailCreate shall be consistent in every CMSIS-RTOS.
|
||||
osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id);
|
||||
|
||||
/// Allocate a memory block from a mail.
|
||||
/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
|
||||
/// \param[in] millisec timeout value or 0 in case of no time-out
|
||||
/// \return pointer to memory block that can be filled with mail or NULL in case of error.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osMailAlloc shall be consistent in every CMSIS-RTOS.
|
||||
void *osMailAlloc (osMailQId queue_id, uint32_t millisec);
|
||||
|
||||
/// Allocate a memory block from a mail and set memory block to zero.
|
||||
/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
|
||||
/// \param[in] millisec timeout value or 0 in case of no time-out
|
||||
/// \return pointer to memory block that can be filled with mail or NULL in case of error.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osMailCAlloc shall be consistent in every CMSIS-RTOS.
|
||||
void *osMailCAlloc (osMailQId queue_id, uint32_t millisec);
|
||||
|
||||
/// Put a mail to a queue.
|
||||
/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
|
||||
/// \param[in] mail memory block previously allocated with \ref osMailAlloc or \ref osMailCAlloc.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osMailPut shall be consistent in every CMSIS-RTOS.
|
||||
osStatus osMailPut (osMailQId queue_id, void *mail);
|
||||
|
||||
/// Get a mail from a queue.
|
||||
/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
|
||||
/// \param[in] millisec timeout value or 0 in case of no time-out
|
||||
/// \return event that contains mail information or error code.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osMailGet shall be consistent in every CMSIS-RTOS.
|
||||
osEvent osMailGet (osMailQId queue_id, uint32_t millisec);
|
||||
|
||||
/// Free a memory block from a mail.
|
||||
/// \param[in] queue_id mail queue ID obtained with \ref osMailCreate.
|
||||
/// \param[in] mail pointer to the memory block that was obtained with \ref osMailGet.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
/// \note MUST REMAIN UNCHANGED: \b osMailFree shall be consistent in every CMSIS-RTOS.
|
||||
osStatus osMailFree (osMailQId queue_id, void *mail);
|
||||
|
||||
#endif // Mail Queues available
|
||||
|
||||
#undef malloc
|
||||
#define malloc(size) pvPortMalloc(size)
|
||||
#undef free
|
||||
#define free(pbuf) vPortFree(pbuf)
|
||||
|
||||
extern void *calloc_freertos(size_t nelements, size_t elementSize);
|
||||
#define calloc(nelements, elementSize) calloc_freertos(nelements, elementSize)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _CMSIS_OS_H
|
||||
|
|
@ -0,0 +1,395 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "croutine.h"
|
||||
|
||||
/* Remove the whole file is co-routines are not being used. */
|
||||
#if( configUSE_CO_ROUTINES != 0 )
|
||||
|
||||
/*
|
||||
* Some kernel aware debuggers require data to be viewed to be global, rather
|
||||
* than file scope.
|
||||
*/
|
||||
#ifdef portREMOVE_STATIC_QUALIFIER
|
||||
#define static
|
||||
#endif
|
||||
|
||||
|
||||
/* Lists for ready and blocked co-routines. --------------------*/
|
||||
static List_t pxReadyCoRoutineLists[ configMAX_CO_ROUTINE_PRIORITIES ]; /*< Prioritised ready co-routines. */
|
||||
static List_t xDelayedCoRoutineList1; /*< Delayed co-routines. */
|
||||
static List_t xDelayedCoRoutineList2; /*< Delayed co-routines (two lists are used - one for delays that have overflowed the current tick count. */
|
||||
static List_t * pxDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used. */
|
||||
static List_t * pxOverflowDelayedCoRoutineList; /*< Points to the delayed co-routine list currently being used to hold co-routines that have overflowed the current tick count. */
|
||||
static List_t xPendingReadyCoRoutineList; /*< Holds co-routines that have been readied by an external event. They cannot be added directly to the ready lists as the ready lists cannot be accessed by interrupts. */
|
||||
|
||||
/* Other file private variables. --------------------------------*/
|
||||
CRCB_t * pxCurrentCoRoutine = NULL;
|
||||
static UBaseType_t uxTopCoRoutineReadyPriority = 0;
|
||||
static TickType_t xCoRoutineTickCount = 0, xLastTickCount = 0, xPassedTicks = 0;
|
||||
|
||||
/* The initial state of the co-routine when it is created. */
|
||||
#define corINITIAL_STATE ( 0 )
|
||||
|
||||
/*
|
||||
* Place the co-routine represented by pxCRCB into the appropriate ready queue
|
||||
* for the priority. It is inserted at the end of the list.
|
||||
*
|
||||
* This macro accesses the co-routine ready lists and therefore must not be
|
||||
* used from within an ISR.
|
||||
*/
|
||||
#define prvAddCoRoutineToReadyQueue( pxCRCB ) \
|
||||
{ \
|
||||
if( pxCRCB->uxPriority > uxTopCoRoutineReadyPriority ) \
|
||||
{ \
|
||||
uxTopCoRoutineReadyPriority = pxCRCB->uxPriority; \
|
||||
} \
|
||||
vListInsertEnd( ( List_t * ) &( pxReadyCoRoutineLists[ pxCRCB->uxPriority ] ), &( pxCRCB->xGenericListItem ) ); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility to ready all the lists used by the scheduler. This is called
|
||||
* automatically upon the creation of the first co-routine.
|
||||
*/
|
||||
static void prvInitialiseCoRoutineLists( void );
|
||||
|
||||
/*
|
||||
* Co-routines that are readied by an interrupt cannot be placed directly into
|
||||
* the ready lists (there is no mutual exclusion). Instead they are placed in
|
||||
* in the pending ready list in order that they can later be moved to the ready
|
||||
* list by the co-routine scheduler.
|
||||
*/
|
||||
static void prvCheckPendingReadyList( void );
|
||||
|
||||
/*
|
||||
* Macro that looks at the list of co-routines that are currently delayed to
|
||||
* see if any require waking.
|
||||
*
|
||||
* Co-routines are stored in the queue in the order of their wake time -
|
||||
* meaning once one co-routine has been found whose timer has not expired
|
||||
* we need not look any further down the list.
|
||||
*/
|
||||
static void prvCheckDelayedList( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
CRCB_t *pxCoRoutine;
|
||||
|
||||
/* Allocate the memory that will store the co-routine control block. */
|
||||
pxCoRoutine = ( CRCB_t * ) pvPortMalloc( sizeof( CRCB_t ) );
|
||||
if( pxCoRoutine )
|
||||
{
|
||||
/* If pxCurrentCoRoutine is NULL then this is the first co-routine to
|
||||
be created and the co-routine data structures need initialising. */
|
||||
if( pxCurrentCoRoutine == NULL )
|
||||
{
|
||||
pxCurrentCoRoutine = pxCoRoutine;
|
||||
prvInitialiseCoRoutineLists();
|
||||
}
|
||||
|
||||
/* Check the priority is within limits. */
|
||||
if( uxPriority >= configMAX_CO_ROUTINE_PRIORITIES )
|
||||
{
|
||||
uxPriority = configMAX_CO_ROUTINE_PRIORITIES - 1;
|
||||
}
|
||||
|
||||
/* Fill out the co-routine control block from the function parameters. */
|
||||
pxCoRoutine->uxState = corINITIAL_STATE;
|
||||
pxCoRoutine->uxPriority = uxPriority;
|
||||
pxCoRoutine->uxIndex = uxIndex;
|
||||
pxCoRoutine->pxCoRoutineFunction = pxCoRoutineCode;
|
||||
|
||||
/* Initialise all the other co-routine control block parameters. */
|
||||
vListInitialiseItem( &( pxCoRoutine->xGenericListItem ) );
|
||||
vListInitialiseItem( &( pxCoRoutine->xEventListItem ) );
|
||||
|
||||
/* Set the co-routine control block as a link back from the ListItem_t.
|
||||
This is so we can get back to the containing CRCB from a generic item
|
||||
in a list. */
|
||||
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xGenericListItem ), pxCoRoutine );
|
||||
listSET_LIST_ITEM_OWNER( &( pxCoRoutine->xEventListItem ), pxCoRoutine );
|
||||
|
||||
/* Event lists are always in priority order. */
|
||||
listSET_LIST_ITEM_VALUE( &( pxCoRoutine->xEventListItem ), ( ( TickType_t ) configMAX_CO_ROUTINE_PRIORITIES - ( TickType_t ) uxPriority ) );
|
||||
|
||||
/* Now the co-routine has been initialised it can be added to the ready
|
||||
list at the correct priority. */
|
||||
prvAddCoRoutineToReadyQueue( pxCoRoutine );
|
||||
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList )
|
||||
{
|
||||
TickType_t xTimeToWake;
|
||||
|
||||
/* Calculate the time to wake - this may overflow but this is
|
||||
not a problem. */
|
||||
xTimeToWake = xCoRoutineTickCount + xTicksToDelay;
|
||||
|
||||
/* We must remove ourselves from the ready list before adding
|
||||
ourselves to the blocked list as the same list item is used for
|
||||
both lists. */
|
||||
( void ) uxListRemove( ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||
|
||||
/* The list item will be inserted in wake time order. */
|
||||
listSET_LIST_ITEM_VALUE( &( pxCurrentCoRoutine->xGenericListItem ), xTimeToWake );
|
||||
|
||||
if( xTimeToWake < xCoRoutineTickCount )
|
||||
{
|
||||
/* Wake time has overflowed. Place this item in the
|
||||
overflow list. */
|
||||
vListInsert( ( List_t * ) pxOverflowDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The wake time has not overflowed, so we can use the
|
||||
current block list. */
|
||||
vListInsert( ( List_t * ) pxDelayedCoRoutineList, ( ListItem_t * ) &( pxCurrentCoRoutine->xGenericListItem ) );
|
||||
}
|
||||
|
||||
if( pxEventList )
|
||||
{
|
||||
/* Also add the co-routine to an event list. If this is done then the
|
||||
function must be called with interrupts disabled. */
|
||||
vListInsert( pxEventList, &( pxCurrentCoRoutine->xEventListItem ) );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvCheckPendingReadyList( void )
|
||||
{
|
||||
/* Are there any co-routines waiting to get moved to the ready list? These
|
||||
are co-routines that have been readied by an ISR. The ISR cannot access
|
||||
the ready lists itself. */
|
||||
while( listLIST_IS_EMPTY( &xPendingReadyCoRoutineList ) == pdFALSE )
|
||||
{
|
||||
CRCB_t *pxUnblockedCRCB;
|
||||
|
||||
/* The pending ready list can be accessed by an ISR. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( (&xPendingReadyCoRoutineList) );
|
||||
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
( void ) uxListRemove( &( pxUnblockedCRCB->xGenericListItem ) );
|
||||
prvAddCoRoutineToReadyQueue( pxUnblockedCRCB );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvCheckDelayedList( void )
|
||||
{
|
||||
CRCB_t *pxCRCB;
|
||||
|
||||
xPassedTicks = xTaskGetTickCount() - xLastTickCount;
|
||||
while( xPassedTicks )
|
||||
{
|
||||
xCoRoutineTickCount++;
|
||||
xPassedTicks--;
|
||||
|
||||
/* If the tick count has overflowed we need to swap the ready lists. */
|
||||
if( xCoRoutineTickCount == 0 )
|
||||
{
|
||||
List_t * pxTemp;
|
||||
|
||||
/* Tick count has overflowed so we need to swap the delay lists. If there are
|
||||
any items in pxDelayedCoRoutineList here then there is an error! */
|
||||
pxTemp = pxDelayedCoRoutineList;
|
||||
pxDelayedCoRoutineList = pxOverflowDelayedCoRoutineList;
|
||||
pxOverflowDelayedCoRoutineList = pxTemp;
|
||||
}
|
||||
|
||||
/* See if this tick has made a timeout expire. */
|
||||
while( listLIST_IS_EMPTY( pxDelayedCoRoutineList ) == pdFALSE )
|
||||
{
|
||||
pxCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedCoRoutineList );
|
||||
|
||||
if( xCoRoutineTickCount < listGET_LIST_ITEM_VALUE( &( pxCRCB->xGenericListItem ) ) )
|
||||
{
|
||||
/* Timeout not yet expired. */
|
||||
break;
|
||||
}
|
||||
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
/* The event could have occurred just before this critical
|
||||
section. If this is the case then the generic list item will
|
||||
have been moved to the pending ready list and the following
|
||||
line is still valid. Also the pvContainer parameter will have
|
||||
been set to NULL so the following lines are also valid. */
|
||||
( void ) uxListRemove( &( pxCRCB->xGenericListItem ) );
|
||||
|
||||
/* Is the co-routine waiting on an event also? */
|
||||
if( pxCRCB->xEventListItem.pvContainer )
|
||||
{
|
||||
( void ) uxListRemove( &( pxCRCB->xEventListItem ) );
|
||||
}
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
prvAddCoRoutineToReadyQueue( pxCRCB );
|
||||
}
|
||||
}
|
||||
|
||||
xLastTickCount = xCoRoutineTickCount;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vCoRoutineSchedule( void )
|
||||
{
|
||||
/* See if any co-routines readied by events need moving to the ready lists. */
|
||||
prvCheckPendingReadyList();
|
||||
|
||||
/* See if any delayed co-routines have timed out. */
|
||||
prvCheckDelayedList();
|
||||
|
||||
/* Find the highest priority queue that contains ready co-routines. */
|
||||
while( listLIST_IS_EMPTY( &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) ) )
|
||||
{
|
||||
if( uxTopCoRoutineReadyPriority == 0 )
|
||||
{
|
||||
/* No more co-routines to check. */
|
||||
return;
|
||||
}
|
||||
--uxTopCoRoutineReadyPriority;
|
||||
}
|
||||
|
||||
/* listGET_OWNER_OF_NEXT_ENTRY walks through the list, so the co-routines
|
||||
of the same priority get an equal share of the processor time. */
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentCoRoutine, &( pxReadyCoRoutineLists[ uxTopCoRoutineReadyPriority ] ) );
|
||||
|
||||
/* Call the co-routine. */
|
||||
( pxCurrentCoRoutine->pxCoRoutineFunction )( pxCurrentCoRoutine, pxCurrentCoRoutine->uxIndex );
|
||||
|
||||
return;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInitialiseCoRoutineLists( void )
|
||||
{
|
||||
UBaseType_t uxPriority;
|
||||
|
||||
for( uxPriority = 0; uxPriority < configMAX_CO_ROUTINE_PRIORITIES; uxPriority++ )
|
||||
{
|
||||
vListInitialise( ( List_t * ) &( pxReadyCoRoutineLists[ uxPriority ] ) );
|
||||
}
|
||||
|
||||
vListInitialise( ( List_t * ) &xDelayedCoRoutineList1 );
|
||||
vListInitialise( ( List_t * ) &xDelayedCoRoutineList2 );
|
||||
vListInitialise( ( List_t * ) &xPendingReadyCoRoutineList );
|
||||
|
||||
/* Start with pxDelayedCoRoutineList using list1 and the
|
||||
pxOverflowDelayedCoRoutineList using list2. */
|
||||
pxDelayedCoRoutineList = &xDelayedCoRoutineList1;
|
||||
pxOverflowDelayedCoRoutineList = &xDelayedCoRoutineList2;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList )
|
||||
{
|
||||
CRCB_t *pxUnblockedCRCB;
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* This function is called from within an interrupt. It can only access
|
||||
event lists and the pending ready list. This function assumes that a
|
||||
check has already been made to ensure pxEventList is not empty. */
|
||||
pxUnblockedCRCB = ( CRCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );
|
||||
( void ) uxListRemove( &( pxUnblockedCRCB->xEventListItem ) );
|
||||
vListInsertEnd( ( List_t * ) &( xPendingReadyCoRoutineList ), &( pxUnblockedCRCB->xEventListItem ) );
|
||||
|
||||
if( pxUnblockedCRCB->uxPriority >= pxCurrentCoRoutine->uxPriority )
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif /* configUSE_CO_ROUTINES == 0 */
|
||||
|
||||
|
|
@ -0,0 +1,752 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* 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
|
||||
task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "timers.h"
|
||||
#include "event_groups.h"
|
||||
|
||||
/* Lint e961 and e750 are suppressed as a MISRA exception justified because the
|
||||
MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
|
||||
header files above, but not in this file, in order to generate the correct
|
||||
privileged Vs unprivileged linkage and placement. */
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
|
||||
|
||||
/* The following bit fields convey control information in a task's event list
|
||||
item value. It is important they don't clash with the
|
||||
taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */
|
||||
#if configUSE_16_BIT_TICKS == 1
|
||||
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
|
||||
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U
|
||||
#define eventWAIT_FOR_ALL_BITS 0x0400U
|
||||
#define eventEVENT_BITS_CONTROL_BYTES 0xff00U
|
||||
#else
|
||||
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
|
||||
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL
|
||||
#define eventWAIT_FOR_ALL_BITS 0x04000000UL
|
||||
#define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL
|
||||
#endif
|
||||
|
||||
typedef struct xEventGroupDefinition
|
||||
{
|
||||
EventBits_t uxEventBits;
|
||||
List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
|
||||
|
||||
#if( configUSE_TRACE_FACILITY == 1 )
|
||||
UBaseType_t uxEventGroupNumber;
|
||||
#endif
|
||||
|
||||
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
|
||||
uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
|
||||
#endif
|
||||
} EventGroup_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Test the bits set in uxCurrentEventBits to see if the wait condition is met.
|
||||
* The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is
|
||||
* pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor
|
||||
* are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the
|
||||
* wait condition is met if any of the bits set in uxBitsToWait for are also set
|
||||
* in uxCurrentEventBits.
|
||||
*/
|
||||
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
|
||||
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer )
|
||||
{
|
||||
EventGroup_t *pxEventBits;
|
||||
|
||||
/* A StaticEventGroup_t object must be provided. */
|
||||
configASSERT( pxEventGroupBuffer );
|
||||
|
||||
/* The user has provided a statically allocated event group - use it. */
|
||||
pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; /*lint !e740 EventGroup_t and StaticEventGroup_t are guaranteed to have the same size and alignment requirement - checked by configASSERT(). */
|
||||
|
||||
if( pxEventBits != NULL )
|
||||
{
|
||||
pxEventBits->uxEventBits = 0;
|
||||
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
|
||||
|
||||
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
{
|
||||
/* Both static and dynamic allocation can be used, so note that
|
||||
this event group was created statically in case the event group
|
||||
is later deleted. */
|
||||
pxEventBits->ucStaticallyAllocated = pdTRUE;
|
||||
}
|
||||
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||
|
||||
traceEVENT_GROUP_CREATE( pxEventBits );
|
||||
}
|
||||
else
|
||||
{
|
||||
traceEVENT_GROUP_CREATE_FAILED();
|
||||
}
|
||||
|
||||
return ( EventGroupHandle_t ) pxEventBits;
|
||||
}
|
||||
|
||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
|
||||
EventGroupHandle_t xEventGroupCreate( void )
|
||||
{
|
||||
EventGroup_t *pxEventBits;
|
||||
|
||||
/* Allocate the event group. */
|
||||
pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
|
||||
|
||||
if( pxEventBits != NULL )
|
||||
{
|
||||
pxEventBits->uxEventBits = 0;
|
||||
vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );
|
||||
|
||||
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
{
|
||||
/* Both static and dynamic allocation can be used, so note this
|
||||
event group was allocated statically in case the event group is
|
||||
later deleted. */
|
||||
pxEventBits->ucStaticallyAllocated = pdFALSE;
|
||||
}
|
||||
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||||
|
||||
traceEVENT_GROUP_CREATE( pxEventBits );
|
||||
}
|
||||
else
|
||||
{
|
||||
traceEVENT_GROUP_CREATE_FAILED();
|
||||
}
|
||||
|
||||
return ( EventGroupHandle_t ) pxEventBits;
|
||||
}
|
||||
|
||||
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait )
|
||||
{
|
||||
EventBits_t uxOriginalBitValue, uxReturn;
|
||||
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
|
||||
BaseType_t xAlreadyYielded;
|
||||
BaseType_t xTimeoutOccurred = pdFALSE;
|
||||
|
||||
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||
configASSERT( uxBitsToWaitFor != 0 );
|
||||
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
|
||||
{
|
||||
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
uxOriginalBitValue = pxEventBits->uxEventBits;
|
||||
|
||||
( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );
|
||||
|
||||
if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor )
|
||||
{
|
||||
/* All the rendezvous bits are now set - no need to block. */
|
||||
uxReturn = ( uxOriginalBitValue | uxBitsToSet );
|
||||
|
||||
/* Rendezvous always clear the bits. They will have been cleared
|
||||
already unless this is the only task in the rendezvous. */
|
||||
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||
|
||||
xTicksToWait = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( xTicksToWait != ( TickType_t ) 0 )
|
||||
{
|
||||
traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor );
|
||||
|
||||
/* Store the bits that the calling task is waiting for in the
|
||||
task's event list item so the kernel knows when a match is
|
||||
found. Then enter the blocked state. */
|
||||
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait );
|
||||
|
||||
/* This assignment is obsolete as uxReturn will get set after
|
||||
the task unblocks, but some compilers mistakenly generate a
|
||||
warning about uxReturn being returned without being set if the
|
||||
assignment is omitted. */
|
||||
uxReturn = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The rendezvous bits were not set, but no block time was
|
||||
specified - just return the current event bit value. */
|
||||
uxReturn = pxEventBits->uxEventBits;
|
||||
}
|
||||
}
|
||||
}
|
||||
xAlreadyYielded = xTaskResumeAll();
|
||||
|
||||
if( xTicksToWait != ( TickType_t ) 0 )
|
||||
{
|
||||
if( xAlreadyYielded == pdFALSE )
|
||||
{
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The task blocked to wait for its required bits to be set - at this
|
||||
point either the required bits were set or the block time expired. If
|
||||
the required bits were set they will have been stored in the task's
|
||||
event list item, and they should now be retrieved then cleared. */
|
||||
uxReturn = uxTaskResetEventItemValue();
|
||||
|
||||
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
|
||||
{
|
||||
/* The task timed out, just return the current event bit value. */
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
uxReturn = pxEventBits->uxEventBits;
|
||||
|
||||
/* Although the task got here because it timed out before the
|
||||
bits it was waiting for were set, it is possible that since it
|
||||
unblocked another task has set the bits. If this is the case
|
||||
then it needs to clear the bits before exiting. */
|
||||
if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )
|
||||
{
|
||||
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
xTimeoutOccurred = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The task unblocked because the bits were set. */
|
||||
}
|
||||
|
||||
/* Control bits might be set as the task had blocked should not be
|
||||
returned. */
|
||||
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
|
||||
}
|
||||
|
||||
traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
|
||||
{
|
||||
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
|
||||
EventBits_t uxReturn, uxControlBits = 0;
|
||||
BaseType_t xWaitConditionMet, xAlreadyYielded;
|
||||
BaseType_t xTimeoutOccurred = pdFALSE;
|
||||
|
||||
/* Check the user is not attempting to wait on the bits used by the kernel
|
||||
itself, and that at least one bit is being requested. */
|
||||
configASSERT( xEventGroup );
|
||||
configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||
configASSERT( uxBitsToWaitFor != 0 );
|
||||
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
|
||||
{
|
||||
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;
|
||||
|
||||
/* Check to see if the wait condition is already met or not. */
|
||||
xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );
|
||||
|
||||
if( xWaitConditionMet != pdFALSE )
|
||||
{
|
||||
/* The wait condition has already been met so there is no need to
|
||||
block. */
|
||||
uxReturn = uxCurrentEventBits;
|
||||
xTicksToWait = ( TickType_t ) 0;
|
||||
|
||||
/* Clear the wait bits if requested to do so. */
|
||||
if( xClearOnExit != pdFALSE )
|
||||
{
|
||||
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else if( xTicksToWait == ( TickType_t ) 0 )
|
||||
{
|
||||
/* The wait condition has not been met, but no block time was
|
||||
specified, so just return the current value. */
|
||||
uxReturn = uxCurrentEventBits;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The task is going to block to wait for its required bits to be
|
||||
set. uxControlBits are used to remember the specified behaviour of
|
||||
this call to xEventGroupWaitBits() - for use when the event bits
|
||||
unblock the task. */
|
||||
if( xClearOnExit != pdFALSE )
|
||||
{
|
||||
uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( xWaitForAllBits != pdFALSE )
|
||||
{
|
||||
uxControlBits |= eventWAIT_FOR_ALL_BITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Store the bits that the calling task is waiting for in the
|
||||
task's event list item so the kernel knows when a match is
|
||||
found. Then enter the blocked state. */
|
||||
vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );
|
||||
|
||||
/* This is obsolete as it will get set after the task unblocks, but
|
||||
some compilers mistakenly generate a warning about the variable
|
||||
being returned without being set if it is not done. */
|
||||
uxReturn = 0;
|
||||
|
||||
traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
|
||||
}
|
||||
}
|
||||
xAlreadyYielded = xTaskResumeAll();
|
||||
|
||||
if( xTicksToWait != ( TickType_t ) 0 )
|
||||
{
|
||||
if( xAlreadyYielded == pdFALSE )
|
||||
{
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The task blocked to wait for its required bits to be set - at this
|
||||
point either the required bits were set or the block time expired. If
|
||||
the required bits were set they will have been stored in the task's
|
||||
event list item, and they should now be retrieved then cleared. */
|
||||
uxReturn = uxTaskResetEventItemValue();
|
||||
|
||||
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
|
||||
{
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
/* The task timed out, just return the current event bit value. */
|
||||
uxReturn = pxEventBits->uxEventBits;
|
||||
|
||||
/* It is possible that the event bits were updated between this
|
||||
task leaving the Blocked state and running again. */
|
||||
if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
|
||||
{
|
||||
if( xClearOnExit != pdFALSE )
|
||||
{
|
||||
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
/* Prevent compiler warnings when trace macros are not used. */
|
||||
xTimeoutOccurred = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The task unblocked because the bits were set. */
|
||||
}
|
||||
|
||||
/* The task blocked so control bits may have been set. */
|
||||
uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
|
||||
}
|
||||
traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
|
||||
{
|
||||
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
|
||||
EventBits_t uxReturn;
|
||||
|
||||
/* Check the user is not attempting to clear the bits used by the kernel
|
||||
itself. */
|
||||
configASSERT( xEventGroup );
|
||||
configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );
|
||||
|
||||
/* The value returned is the event group value prior to the bits being
|
||||
cleared. */
|
||||
uxReturn = pxEventBits->uxEventBits;
|
||||
|
||||
/* Clear the bits. */
|
||||
pxEventBits->uxEventBits &= ~uxBitsToClear;
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
|
||||
|
||||
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
|
||||
traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );
|
||||
xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL );
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )
|
||||
{
|
||||
UBaseType_t uxSavedInterruptStatus;
|
||||
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
|
||||
EventBits_t uxReturn;
|
||||
|
||||
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
uxReturn = pxEventBits->uxEventBits;
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
|
||||
|
||||
return uxReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
|
||||
{
|
||||
ListItem_t *pxListItem, *pxNext;
|
||||
ListItem_t const *pxListEnd;
|
||||
List_t *pxList;
|
||||
EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
|
||||
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
|
||||
BaseType_t xMatchFound = pdFALSE;
|
||||
|
||||
/* Check the user is not attempting to set the bits used by the kernel
|
||||
itself. */
|
||||
configASSERT( xEventGroup );
|
||||
configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
|
||||
|
||||
pxList = &( pxEventBits->xTasksWaitingForBits );
|
||||
pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
|
||||
|
||||
pxListItem = listGET_HEAD_ENTRY( pxList );
|
||||
|
||||
/* Set the bits. */
|
||||
pxEventBits->uxEventBits |= uxBitsToSet;
|
||||
|
||||
/* See if the new bit value should unblock any tasks. */
|
||||
while( pxListItem != pxListEnd )
|
||||
{
|
||||
pxNext = listGET_NEXT( pxListItem );
|
||||
uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
|
||||
xMatchFound = pdFALSE;
|
||||
|
||||
/* Split the bits waited for from the control bits. */
|
||||
uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
|
||||
uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;
|
||||
|
||||
if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
|
||||
{
|
||||
/* Just looking for single bit being set. */
|
||||
if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
|
||||
{
|
||||
xMatchFound = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
|
||||
{
|
||||
/* All bits are set. */
|
||||
xMatchFound = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Need all bits to be set, but not all the bits were set. */
|
||||
}
|
||||
|
||||
if( xMatchFound != pdFALSE )
|
||||
{
|
||||
/* The bits match. Should the bits be cleared on exit? */
|
||||
if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
|
||||
{
|
||||
uxBitsToClear |= uxBitsWaitedFor;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Store the actual event flag value in the task's event list
|
||||
item before removing the task from the event list. The
|
||||
eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
|
||||
that is was unblocked due to its required bits matching, rather
|
||||
than because it timed out. */
|
||||
( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
|
||||
}
|
||||
|
||||
/* Move onto the next list item. Note pxListItem->pxNext is not
|
||||
used here as the list item may have been removed from the event list
|
||||
and inserted into the ready/pending reading list. */
|
||||
pxListItem = pxNext;
|
||||
}
|
||||
|
||||
/* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
|
||||
bit was set in the control word. */
|
||||
pxEventBits->uxEventBits &= ~uxBitsToClear;
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
|
||||
return pxEventBits->uxEventBits;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
|
||||
{
|
||||
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
|
||||
const List_t *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
traceEVENT_GROUP_DELETE( xEventGroup );
|
||||
|
||||
while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 )
|
||||
{
|
||||
/* Unblock the task, returning 0 as the event list is being deleted
|
||||
and cannot therefore have any bits set. */
|
||||
configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) );
|
||||
( void ) xTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET );
|
||||
}
|
||||
|
||||
#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) )
|
||||
{
|
||||
/* The event group can only have been allocated dynamically - free
|
||||
it again. */
|
||||
vPortFree( pxEventBits );
|
||||
}
|
||||
#elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
|
||||
{
|
||||
/* The event group could have been allocated statically or
|
||||
dynamically, so check before attempting to free the memory. */
|
||||
if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE )
|
||||
{
|
||||
vPortFree( pxEventBits );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||||
}
|
||||
( void ) xTaskResumeAll();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* For internal use only - execute a 'set bits' command that was pended from
|
||||
an interrupt. */
|
||||
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet )
|
||||
{
|
||||
( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* For internal use only - execute a 'clear bits' command that was pended from
|
||||
an interrupt. */
|
||||
void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear )
|
||||
{
|
||||
( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits )
|
||||
{
|
||||
BaseType_t xWaitConditionMet = pdFALSE;
|
||||
|
||||
if( xWaitForAllBits == pdFALSE )
|
||||
{
|
||||
/* Task only has to wait for one bit within uxBitsToWaitFor to be
|
||||
set. Is one already set? */
|
||||
if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 )
|
||||
{
|
||||
xWaitConditionMet = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Task has to wait for all the bits in uxBitsToWaitFor to be set.
|
||||
Are they set already? */
|
||||
if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor )
|
||||
{
|
||||
xWaitConditionMet = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
|
||||
return xWaitConditionMet;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )
|
||||
|
||||
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
|
||||
traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet );
|
||||
xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken );
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if (configUSE_TRACE_FACILITY == 1)
|
||||
|
||||
UBaseType_t uxEventGroupGetNumber( void* xEventGroup )
|
||||
{
|
||||
UBaseType_t xReturn;
|
||||
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
|
||||
|
||||
if( xEventGroup == NULL )
|
||||
{
|
||||
xReturn = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pxEventBits->uxEventGroupNumber;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef STACK_MACROS_H
|
||||
#define STACK_MACROS_H
|
||||
|
||||
/*
|
||||
* Call the stack overflow hook function if the stack of the task being swapped
|
||||
* out is currently overflowed, or looks like it might have overflowed in the
|
||||
* past.
|
||||
*
|
||||
* Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check
|
||||
* the current stack state only - comparing the current top of stack value to
|
||||
* the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1
|
||||
* will also cause the last few stack bytes to be checked to ensure the value
|
||||
* to which the bytes were set when the task was created have not been
|
||||
* overwritten. Note this second test does not guarantee that an overflowed
|
||||
* stack will always be recognised.
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) )
|
||||
|
||||
/* Only the current stack state is to be checked. */
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
{ \
|
||||
/* Is the currently saved stack pointer within the stack limit? */ \
|
||||
if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack ) \
|
||||
{ \
|
||||
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) )
|
||||
|
||||
/* Only the current stack state is to be checked. */
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
{ \
|
||||
\
|
||||
/* Is the currently saved stack pointer within the stack limit? */ \
|
||||
if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack ) \
|
||||
{ \
|
||||
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) )
|
||||
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
{ \
|
||||
const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \
|
||||
const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5; \
|
||||
\
|
||||
if( ( pulStack[ 0 ] != ulCheckValue ) || \
|
||||
( pulStack[ 1 ] != ulCheckValue ) || \
|
||||
( pulStack[ 2 ] != ulCheckValue ) || \
|
||||
( pulStack[ 3 ] != ulCheckValue ) ) \
|
||||
{ \
|
||||
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) )
|
||||
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW() \
|
||||
{ \
|
||||
int8_t *pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \
|
||||
static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \
|
||||
tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \
|
||||
\
|
||||
\
|
||||
pcEndOfStack -= sizeof( ucExpectedStackBytes ); \
|
||||
\
|
||||
/* Has the extremity of the task stack ever been written over? */ \
|
||||
if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \
|
||||
{ \
|
||||
vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pxCurrentTCB->pcTaskName ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Remove stack overflow macro if not being used. */
|
||||
#ifndef taskCHECK_FOR_STACK_OVERFLOW
|
||||
#define taskCHECK_FOR_STACK_OVERFLOW()
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif /* STACK_MACROS_H */
|
||||
|
||||
|
|
@ -0,0 +1,762 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef CO_ROUTINE_H
|
||||
#define CO_ROUTINE_H
|
||||
|
||||
#ifndef INC_FREERTOS_H
|
||||
#error "include FreeRTOS.h must appear in source files before include croutine.h"
|
||||
#endif
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Used to hide the implementation of the co-routine control block. The
|
||||
control block structure however has to be included in the header due to
|
||||
the macro implementation of the co-routine functionality. */
|
||||
typedef void * CoRoutineHandle_t;
|
||||
|
||||
/* Defines the prototype to which co-routine functions must conform. */
|
||||
typedef void (*crCOROUTINE_CODE)( CoRoutineHandle_t, UBaseType_t );
|
||||
|
||||
typedef struct corCoRoutineControlBlock
|
||||
{
|
||||
crCOROUTINE_CODE pxCoRoutineFunction;
|
||||
ListItem_t xGenericListItem; /*< List item used to place the CRCB in ready and blocked queues. */
|
||||
ListItem_t xEventListItem; /*< List item used to place the CRCB in event lists. */
|
||||
UBaseType_t uxPriority; /*< The priority of the co-routine in relation to other co-routines. */
|
||||
UBaseType_t uxIndex; /*< Used to distinguish between co-routines when multiple co-routines use the same co-routine function. */
|
||||
uint16_t uxState; /*< Used internally by the co-routine implementation. */
|
||||
} CRCB_t; /* Co-routine control block. Note must be identical in size down to uxPriority with TCB_t. */
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
*<pre>
|
||||
BaseType_t xCoRoutineCreate(
|
||||
crCOROUTINE_CODE pxCoRoutineCode,
|
||||
UBaseType_t uxPriority,
|
||||
UBaseType_t uxIndex
|
||||
);</pre>
|
||||
*
|
||||
* Create a new co-routine and add it to the list of co-routines that are
|
||||
* ready to run.
|
||||
*
|
||||
* @param pxCoRoutineCode Pointer to the co-routine function. Co-routine
|
||||
* functions require special syntax - see the co-routine section of the WEB
|
||||
* documentation for more information.
|
||||
*
|
||||
* @param uxPriority The priority with respect to other co-routines at which
|
||||
* the co-routine will run.
|
||||
*
|
||||
* @param uxIndex Used to distinguish between different co-routines that
|
||||
* execute the same function. See the example below and the co-routine section
|
||||
* of the WEB documentation for further information.
|
||||
*
|
||||
* @return pdPASS if the co-routine was successfully created and added to a ready
|
||||
* list, otherwise an error code defined with ProjDefs.h.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// Co-routine to be created.
|
||||
void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
{
|
||||
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
// This may not be necessary for const variables.
|
||||
static const char cLedToFlash[ 2 ] = { 5, 6 };
|
||||
static const TickType_t uxFlashRates[ 2 ] = { 200, 400 };
|
||||
|
||||
// Must start every co-routine with a call to crSTART();
|
||||
crSTART( xHandle );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// This co-routine just delays for a fixed period, then toggles
|
||||
// an LED. Two co-routines are created using this function, so
|
||||
// the uxIndex parameter is used to tell the co-routine which
|
||||
// LED to flash and how int32_t to delay. This assumes xQueue has
|
||||
// already been created.
|
||||
vParTestToggleLED( cLedToFlash[ uxIndex ] );
|
||||
crDELAY( xHandle, uxFlashRates[ uxIndex ] );
|
||||
}
|
||||
|
||||
// Must end every co-routine with a call to crEND();
|
||||
crEND();
|
||||
}
|
||||
|
||||
// Function that creates two co-routines.
|
||||
void vOtherFunction( void )
|
||||
{
|
||||
uint8_t ucParameterToPass;
|
||||
TaskHandle_t xHandle;
|
||||
|
||||
// Create two co-routines at priority 0. The first is given index 0
|
||||
// so (from the code above) toggles LED 5 every 200 ticks. The second
|
||||
// is given index 1 so toggles LED 6 every 400 ticks.
|
||||
for( uxIndex = 0; uxIndex < 2; uxIndex++ )
|
||||
{
|
||||
xCoRoutineCreate( vFlashCoRoutine, 0, uxIndex );
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xCoRoutineCreate xCoRoutineCreate
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
BaseType_t xCoRoutineCreate( crCOROUTINE_CODE pxCoRoutineCode, UBaseType_t uxPriority, UBaseType_t uxIndex );
|
||||
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
*<pre>
|
||||
void vCoRoutineSchedule( void );</pre>
|
||||
*
|
||||
* Run a co-routine.
|
||||
*
|
||||
* vCoRoutineSchedule() executes the highest priority co-routine that is able
|
||||
* to run. The co-routine will execute until it either blocks, yields or is
|
||||
* preempted by a task. Co-routines execute cooperatively so one
|
||||
* co-routine cannot be preempted by another, but can be preempted by a task.
|
||||
*
|
||||
* If an application comprises of both tasks and co-routines then
|
||||
* vCoRoutineSchedule should be called from the idle task (in an idle task
|
||||
* hook).
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// This idle task hook will schedule a co-routine each time it is called.
|
||||
// The rest of the idle task will execute between co-routine calls.
|
||||
void vApplicationIdleHook( void )
|
||||
{
|
||||
vCoRoutineSchedule();
|
||||
}
|
||||
|
||||
// Alternatively, if you do not require any other part of the idle task to
|
||||
// execute, the idle task hook can call vCoRoutineScheduler() within an
|
||||
// infinite loop.
|
||||
void vApplicationIdleHook( void )
|
||||
{
|
||||
for( ;; )
|
||||
{
|
||||
vCoRoutineSchedule();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup vCoRoutineSchedule vCoRoutineSchedule
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
void vCoRoutineSchedule( void );
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* <pre>
|
||||
crSTART( CoRoutineHandle_t xHandle );</pre>
|
||||
*
|
||||
* This macro MUST always be called at the start of a co-routine function.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// Co-routine to be created.
|
||||
void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
{
|
||||
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
static int32_t ulAVariable;
|
||||
|
||||
// Must start every co-routine with a call to crSTART();
|
||||
crSTART( xHandle );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// Co-routine functionality goes here.
|
||||
}
|
||||
|
||||
// Must end every co-routine with a call to crEND();
|
||||
crEND();
|
||||
}</pre>
|
||||
* \defgroup crSTART crSTART
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crSTART( pxCRCB ) switch( ( ( CRCB_t * )( pxCRCB ) )->uxState ) { case 0:
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* <pre>
|
||||
crEND();</pre>
|
||||
*
|
||||
* This macro MUST always be called at the end of a co-routine function.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// Co-routine to be created.
|
||||
void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
{
|
||||
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
static int32_t ulAVariable;
|
||||
|
||||
// Must start every co-routine with a call to crSTART();
|
||||
crSTART( xHandle );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// Co-routine functionality goes here.
|
||||
}
|
||||
|
||||
// Must end every co-routine with a call to crEND();
|
||||
crEND();
|
||||
}</pre>
|
||||
* \defgroup crSTART crSTART
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crEND() }
|
||||
|
||||
/*
|
||||
* These macros are intended for internal use by the co-routine implementation
|
||||
* only. The macros should not be used directly by application writers.
|
||||
*/
|
||||
#define crSET_STATE0( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = (__LINE__ * 2); return; case (__LINE__ * 2):
|
||||
#define crSET_STATE1( xHandle ) ( ( CRCB_t * )( xHandle ) )->uxState = ((__LINE__ * 2)+1); return; case ((__LINE__ * 2)+1):
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
*<pre>
|
||||
crDELAY( CoRoutineHandle_t xHandle, TickType_t xTicksToDelay );</pre>
|
||||
*
|
||||
* Delay a co-routine for a fixed period of time.
|
||||
*
|
||||
* crDELAY can only be called from the co-routine function itself - not
|
||||
* from within a function called by the co-routine function. This is because
|
||||
* co-routines do not maintain their own stack.
|
||||
*
|
||||
* @param xHandle The handle of the co-routine to delay. This is the xHandle
|
||||
* parameter of the co-routine function.
|
||||
*
|
||||
* @param xTickToDelay The number of ticks that the co-routine should delay
|
||||
* for. The actual amount of time this equates to is defined by
|
||||
* configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant portTICK_PERIOD_MS
|
||||
* can be used to convert ticks to milliseconds.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// Co-routine to be created.
|
||||
void vACoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
{
|
||||
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
// This may not be necessary for const variables.
|
||||
// We are to delay for 200ms.
|
||||
static const xTickType xDelayTime = 200 / portTICK_PERIOD_MS;
|
||||
|
||||
// Must start every co-routine with a call to crSTART();
|
||||
crSTART( xHandle );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// Delay for 200ms.
|
||||
crDELAY( xHandle, xDelayTime );
|
||||
|
||||
// Do something here.
|
||||
}
|
||||
|
||||
// Must end every co-routine with a call to crEND();
|
||||
crEND();
|
||||
}</pre>
|
||||
* \defgroup crDELAY crDELAY
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crDELAY( xHandle, xTicksToDelay ) \
|
||||
if( ( xTicksToDelay ) > 0 ) \
|
||||
{ \
|
||||
vCoRoutineAddToDelayedList( ( xTicksToDelay ), NULL ); \
|
||||
} \
|
||||
crSET_STATE0( ( xHandle ) );
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
crQUEUE_SEND(
|
||||
CoRoutineHandle_t xHandle,
|
||||
QueueHandle_t pxQueue,
|
||||
void *pvItemToQueue,
|
||||
TickType_t xTicksToWait,
|
||||
BaseType_t *pxResult
|
||||
)</pre>
|
||||
*
|
||||
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
|
||||
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
|
||||
*
|
||||
* crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
|
||||
* xQueueSend() and xQueueReceive() can only be used from tasks.
|
||||
*
|
||||
* crQUEUE_SEND can only be called from the co-routine function itself - not
|
||||
* from within a function called by the co-routine function. This is because
|
||||
* co-routines do not maintain their own stack.
|
||||
*
|
||||
* See the co-routine section of the WEB documentation for information on
|
||||
* passing data between tasks and co-routines and between ISR's and
|
||||
* co-routines.
|
||||
*
|
||||
* @param xHandle The handle of the calling co-routine. This is the xHandle
|
||||
* parameter of the co-routine function.
|
||||
*
|
||||
* @param pxQueue The handle of the queue on which the data will be posted.
|
||||
* The handle is obtained as the return value when the queue is created using
|
||||
* the xQueueCreate() API function.
|
||||
*
|
||||
* @param pvItemToQueue A pointer to the data being posted onto the queue.
|
||||
* The number of bytes of each queued item is specified when the queue is
|
||||
* created. This number of bytes is copied from pvItemToQueue into the queue
|
||||
* itself.
|
||||
*
|
||||
* @param xTickToDelay The number of ticks that the co-routine should block
|
||||
* to wait for space to become available on the queue, should space not be
|
||||
* available immediately. The actual amount of time this equates to is defined
|
||||
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
|
||||
* portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see example
|
||||
* below).
|
||||
*
|
||||
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if
|
||||
* data was successfully posted onto the queue, otherwise it will be set to an
|
||||
* error defined within ProjDefs.h.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// Co-routine function that blocks for a fixed period then posts a number onto
|
||||
// a queue.
|
||||
static void prvCoRoutineFlashTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
{
|
||||
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
static BaseType_t xNumberToPost = 0;
|
||||
static BaseType_t xResult;
|
||||
|
||||
// Co-routines must begin with a call to crSTART().
|
||||
crSTART( xHandle );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// This assumes the queue has already been created.
|
||||
crQUEUE_SEND( xHandle, xCoRoutineQueue, &xNumberToPost, NO_DELAY, &xResult );
|
||||
|
||||
if( xResult != pdPASS )
|
||||
{
|
||||
// The message was not posted!
|
||||
}
|
||||
|
||||
// Increment the number to be posted onto the queue.
|
||||
xNumberToPost++;
|
||||
|
||||
// Delay for 100 ticks.
|
||||
crDELAY( xHandle, 100 );
|
||||
}
|
||||
|
||||
// Co-routines must end with a call to crEND().
|
||||
crEND();
|
||||
}</pre>
|
||||
* \defgroup crQUEUE_SEND crQUEUE_SEND
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crQUEUE_SEND( xHandle, pxQueue, pvItemToQueue, xTicksToWait, pxResult ) \
|
||||
{ \
|
||||
*( pxResult ) = xQueueCRSend( ( pxQueue) , ( pvItemToQueue) , ( xTicksToWait ) ); \
|
||||
if( *( pxResult ) == errQUEUE_BLOCKED ) \
|
||||
{ \
|
||||
crSET_STATE0( ( xHandle ) ); \
|
||||
*pxResult = xQueueCRSend( ( pxQueue ), ( pvItemToQueue ), 0 ); \
|
||||
} \
|
||||
if( *pxResult == errQUEUE_YIELD ) \
|
||||
{ \
|
||||
crSET_STATE1( ( xHandle ) ); \
|
||||
*pxResult = pdPASS; \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* <pre>
|
||||
crQUEUE_RECEIVE(
|
||||
CoRoutineHandle_t xHandle,
|
||||
QueueHandle_t pxQueue,
|
||||
void *pvBuffer,
|
||||
TickType_t xTicksToWait,
|
||||
BaseType_t *pxResult
|
||||
)</pre>
|
||||
*
|
||||
* The macro's crQUEUE_SEND() and crQUEUE_RECEIVE() are the co-routine
|
||||
* equivalent to the xQueueSend() and xQueueReceive() functions used by tasks.
|
||||
*
|
||||
* crQUEUE_SEND and crQUEUE_RECEIVE can only be used from a co-routine whereas
|
||||
* xQueueSend() and xQueueReceive() can only be used from tasks.
|
||||
*
|
||||
* crQUEUE_RECEIVE can only be called from the co-routine function itself - not
|
||||
* from within a function called by the co-routine function. This is because
|
||||
* co-routines do not maintain their own stack.
|
||||
*
|
||||
* See the co-routine section of the WEB documentation for information on
|
||||
* passing data between tasks and co-routines and between ISR's and
|
||||
* co-routines.
|
||||
*
|
||||
* @param xHandle The handle of the calling co-routine. This is the xHandle
|
||||
* parameter of the co-routine function.
|
||||
*
|
||||
* @param pxQueue The handle of the queue from which the data will be received.
|
||||
* The handle is obtained as the return value when the queue is created using
|
||||
* the xQueueCreate() API function.
|
||||
*
|
||||
* @param pvBuffer The buffer into which the received item is to be copied.
|
||||
* The number of bytes of each queued item is specified when the queue is
|
||||
* created. This number of bytes is copied into pvBuffer.
|
||||
*
|
||||
* @param xTickToDelay The number of ticks that the co-routine should block
|
||||
* to wait for data to become available from the queue, should data not be
|
||||
* available immediately. The actual amount of time this equates to is defined
|
||||
* by configTICK_RATE_HZ (set in FreeRTOSConfig.h). The constant
|
||||
* portTICK_PERIOD_MS can be used to convert ticks to milliseconds (see the
|
||||
* crQUEUE_SEND example).
|
||||
*
|
||||
* @param pxResult The variable pointed to by pxResult will be set to pdPASS if
|
||||
* data was successfully retrieved from the queue, otherwise it will be set to
|
||||
* an error code as defined within ProjDefs.h.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// A co-routine receives the number of an LED to flash from a queue. It
|
||||
// blocks on the queue until the number is received.
|
||||
static void prvCoRoutineFlashWorkTask( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
{
|
||||
// Variables in co-routines must be declared static if they must maintain value across a blocking call.
|
||||
static BaseType_t xResult;
|
||||
static UBaseType_t uxLEDToFlash;
|
||||
|
||||
// All co-routines must start with a call to crSTART().
|
||||
crSTART( xHandle );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// Wait for data to become available on the queue.
|
||||
crQUEUE_RECEIVE( xHandle, xCoRoutineQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
|
||||
|
||||
if( xResult == pdPASS )
|
||||
{
|
||||
// We received the LED to flash - flash it!
|
||||
vParTestToggleLED( uxLEDToFlash );
|
||||
}
|
||||
}
|
||||
|
||||
crEND();
|
||||
}</pre>
|
||||
* \defgroup crQUEUE_RECEIVE crQUEUE_RECEIVE
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crQUEUE_RECEIVE( xHandle, pxQueue, pvBuffer, xTicksToWait, pxResult ) \
|
||||
{ \
|
||||
*( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), ( xTicksToWait ) ); \
|
||||
if( *( pxResult ) == errQUEUE_BLOCKED ) \
|
||||
{ \
|
||||
crSET_STATE0( ( xHandle ) ); \
|
||||
*( pxResult ) = xQueueCRReceive( ( pxQueue) , ( pvBuffer ), 0 ); \
|
||||
} \
|
||||
if( *( pxResult ) == errQUEUE_YIELD ) \
|
||||
{ \
|
||||
crSET_STATE1( ( xHandle ) ); \
|
||||
*( pxResult ) = pdPASS; \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* <pre>
|
||||
crQUEUE_SEND_FROM_ISR(
|
||||
QueueHandle_t pxQueue,
|
||||
void *pvItemToQueue,
|
||||
BaseType_t xCoRoutinePreviouslyWoken
|
||||
)</pre>
|
||||
*
|
||||
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
|
||||
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
|
||||
* functions used by tasks.
|
||||
*
|
||||
* crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
|
||||
* pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
|
||||
* xQueueReceiveFromISR() can only be used to pass data between a task and and
|
||||
* ISR.
|
||||
*
|
||||
* crQUEUE_SEND_FROM_ISR can only be called from an ISR to send data to a queue
|
||||
* that is being used from within a co-routine.
|
||||
*
|
||||
* See the co-routine section of the WEB documentation for information on
|
||||
* passing data between tasks and co-routines and between ISR's and
|
||||
* co-routines.
|
||||
*
|
||||
* @param xQueue The handle to the queue on which the item is to be posted.
|
||||
*
|
||||
* @param pvItemToQueue A pointer to the item that is to be placed on the
|
||||
* queue. The size of the items the queue will hold was defined when the
|
||||
* queue was created, so this many bytes will be copied from pvItemToQueue
|
||||
* into the queue storage area.
|
||||
*
|
||||
* @param xCoRoutinePreviouslyWoken This is included so an ISR can post onto
|
||||
* the same queue multiple times from a single interrupt. The first call
|
||||
* should always pass in pdFALSE. Subsequent calls should pass in
|
||||
* the value returned from the previous call.
|
||||
*
|
||||
* @return pdTRUE if a co-routine was woken by posting onto the queue. This is
|
||||
* used by the ISR to determine if a context switch may be required following
|
||||
* the ISR.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// A co-routine that blocks on a queue waiting for characters to be received.
|
||||
static void vReceivingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
{
|
||||
char cRxedChar;
|
||||
BaseType_t xResult;
|
||||
|
||||
// All co-routines must start with a call to crSTART().
|
||||
crSTART( xHandle );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// Wait for data to become available on the queue. This assumes the
|
||||
// queue xCommsRxQueue has already been created!
|
||||
crQUEUE_RECEIVE( xHandle, xCommsRxQueue, &uxLEDToFlash, portMAX_DELAY, &xResult );
|
||||
|
||||
// Was a character received?
|
||||
if( xResult == pdPASS )
|
||||
{
|
||||
// Process the character here.
|
||||
}
|
||||
}
|
||||
|
||||
// All co-routines must end with a call to crEND().
|
||||
crEND();
|
||||
}
|
||||
|
||||
// An ISR that uses a queue to send characters received on a serial port to
|
||||
// a co-routine.
|
||||
void vUART_ISR( void )
|
||||
{
|
||||
char cRxedChar;
|
||||
BaseType_t xCRWokenByPost = pdFALSE;
|
||||
|
||||
// We loop around reading characters until there are none left in the UART.
|
||||
while( UART_RX_REG_NOT_EMPTY() )
|
||||
{
|
||||
// Obtain the character from the UART.
|
||||
cRxedChar = UART_RX_REG;
|
||||
|
||||
// Post the character onto a queue. xCRWokenByPost will be pdFALSE
|
||||
// the first time around the loop. If the post causes a co-routine
|
||||
// to be woken (unblocked) then xCRWokenByPost will be set to pdTRUE.
|
||||
// In this manner we can ensure that if more than one co-routine is
|
||||
// blocked on the queue only one is woken by this ISR no matter how
|
||||
// many characters are posted to the queue.
|
||||
xCRWokenByPost = crQUEUE_SEND_FROM_ISR( xCommsRxQueue, &cRxedChar, xCRWokenByPost );
|
||||
}
|
||||
}</pre>
|
||||
* \defgroup crQUEUE_SEND_FROM_ISR crQUEUE_SEND_FROM_ISR
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crQUEUE_SEND_FROM_ISR( pxQueue, pvItemToQueue, xCoRoutinePreviouslyWoken ) xQueueCRSendFromISR( ( pxQueue ), ( pvItemToQueue ), ( xCoRoutinePreviouslyWoken ) )
|
||||
|
||||
|
||||
/**
|
||||
* croutine. h
|
||||
* <pre>
|
||||
crQUEUE_SEND_FROM_ISR(
|
||||
QueueHandle_t pxQueue,
|
||||
void *pvBuffer,
|
||||
BaseType_t * pxCoRoutineWoken
|
||||
)</pre>
|
||||
*
|
||||
* The macro's crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() are the
|
||||
* co-routine equivalent to the xQueueSendFromISR() and xQueueReceiveFromISR()
|
||||
* functions used by tasks.
|
||||
*
|
||||
* crQUEUE_SEND_FROM_ISR() and crQUEUE_RECEIVE_FROM_ISR() can only be used to
|
||||
* pass data between a co-routine and and ISR, whereas xQueueSendFromISR() and
|
||||
* xQueueReceiveFromISR() can only be used to pass data between a task and and
|
||||
* ISR.
|
||||
*
|
||||
* crQUEUE_RECEIVE_FROM_ISR can only be called from an ISR to receive data
|
||||
* from a queue that is being used from within a co-routine (a co-routine
|
||||
* posted to the queue).
|
||||
*
|
||||
* See the co-routine section of the WEB documentation for information on
|
||||
* passing data between tasks and co-routines and between ISR's and
|
||||
* co-routines.
|
||||
*
|
||||
* @param xQueue The handle to the queue on which the item is to be posted.
|
||||
*
|
||||
* @param pvBuffer A pointer to a buffer into which the received item will be
|
||||
* placed. The size of the items the queue will hold was defined when the
|
||||
* queue was created, so this many bytes will be copied from the queue into
|
||||
* pvBuffer.
|
||||
*
|
||||
* @param pxCoRoutineWoken A co-routine may be blocked waiting for space to become
|
||||
* available on the queue. If crQUEUE_RECEIVE_FROM_ISR causes such a
|
||||
* co-routine to unblock *pxCoRoutineWoken will get set to pdTRUE, otherwise
|
||||
* *pxCoRoutineWoken will remain unchanged.
|
||||
*
|
||||
* @return pdTRUE an item was successfully received from the queue, otherwise
|
||||
* pdFALSE.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// A co-routine that posts a character to a queue then blocks for a fixed
|
||||
// period. The character is incremented each time.
|
||||
static void vSendingCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
|
||||
{
|
||||
// cChar holds its value while this co-routine is blocked and must therefore
|
||||
// be declared static.
|
||||
static char cCharToTx = 'a';
|
||||
BaseType_t xResult;
|
||||
|
||||
// All co-routines must start with a call to crSTART().
|
||||
crSTART( xHandle );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// Send the next character to the queue.
|
||||
crQUEUE_SEND( xHandle, xCoRoutineQueue, &cCharToTx, NO_DELAY, &xResult );
|
||||
|
||||
if( xResult == pdPASS )
|
||||
{
|
||||
// The character was successfully posted to the queue.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Could not post the character to the queue.
|
||||
}
|
||||
|
||||
// Enable the UART Tx interrupt to cause an interrupt in this
|
||||
// hypothetical UART. The interrupt will obtain the character
|
||||
// from the queue and send it.
|
||||
ENABLE_RX_INTERRUPT();
|
||||
|
||||
// Increment to the next character then block for a fixed period.
|
||||
// cCharToTx will maintain its value across the delay as it is
|
||||
// declared static.
|
||||
cCharToTx++;
|
||||
if( cCharToTx > 'x' )
|
||||
{
|
||||
cCharToTx = 'a';
|
||||
}
|
||||
crDELAY( 100 );
|
||||
}
|
||||
|
||||
// All co-routines must end with a call to crEND().
|
||||
crEND();
|
||||
}
|
||||
|
||||
// An ISR that uses a queue to receive characters to send on a UART.
|
||||
void vUART_ISR( void )
|
||||
{
|
||||
char cCharToTx;
|
||||
BaseType_t xCRWokenByPost = pdFALSE;
|
||||
|
||||
while( UART_TX_REG_EMPTY() )
|
||||
{
|
||||
// Are there any characters in the queue waiting to be sent?
|
||||
// xCRWokenByPost will automatically be set to pdTRUE if a co-routine
|
||||
// is woken by the post - ensuring that only a single co-routine is
|
||||
// woken no matter how many times we go around this loop.
|
||||
if( crQUEUE_RECEIVE_FROM_ISR( pxQueue, &cCharToTx, &xCRWokenByPost ) )
|
||||
{
|
||||
SEND_CHARACTER( cCharToTx );
|
||||
}
|
||||
}
|
||||
}</pre>
|
||||
* \defgroup crQUEUE_RECEIVE_FROM_ISR crQUEUE_RECEIVE_FROM_ISR
|
||||
* \ingroup Tasks
|
||||
*/
|
||||
#define crQUEUE_RECEIVE_FROM_ISR( pxQueue, pvBuffer, pxCoRoutineWoken ) xQueueCRReceiveFromISR( ( pxQueue ), ( pvBuffer ), ( pxCoRoutineWoken ) )
|
||||
|
||||
/*
|
||||
* This function is intended for internal use by the co-routine macros only.
|
||||
* The macro nature of the co-routine implementation requires that the
|
||||
* prototype appears here. The function should not be used by application
|
||||
* writers.
|
||||
*
|
||||
* Removes the current co-routine from its ready list and places it in the
|
||||
* appropriate delayed list.
|
||||
*/
|
||||
void vCoRoutineAddToDelayedList( TickType_t xTicksToDelay, List_t *pxEventList );
|
||||
|
||||
/*
|
||||
* This function is intended for internal use by the queue implementation only.
|
||||
* The function should not be used by application writers.
|
||||
*
|
||||
* Removes the highest priority co-routine from the event list and places it in
|
||||
* the pending ready list.
|
||||
*/
|
||||
BaseType_t xCoRoutineRemoveFromEventList( const List_t *pxEventList );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CO_ROUTINE_H */
|
||||
|
|
@ -0,0 +1,321 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef DEPRECATED_DEFINITIONS_H
|
||||
#define DEPRECATED_DEFINITIONS_H
|
||||
|
||||
|
||||
/* Each FreeRTOS port has a unique portmacro.h header file. Originally a
|
||||
pre-processor definition was used to ensure the pre-processor found the correct
|
||||
portmacro.h file for the port being used. That scheme was deprecated in favour
|
||||
of setting the compiler's include path such that it found the correct
|
||||
portmacro.h file - removing the need for the constant and allowing the
|
||||
portmacro.h file to be located anywhere in relation to the port being used. The
|
||||
definitions below remain in the code for backward compatibility only. New
|
||||
projects should not use them. */
|
||||
|
||||
#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT
|
||||
#include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h"
|
||||
typedef void ( __interrupt __far *pxISR )();
|
||||
#endif
|
||||
|
||||
#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT
|
||||
#include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h"
|
||||
typedef void ( __interrupt __far *pxISR )();
|
||||
#endif
|
||||
|
||||
#ifdef GCC_MEGA_AVR
|
||||
#include "../portable/GCC/ATMega323/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef IAR_MEGA_AVR
|
||||
#include "../portable/IAR/ATMega323/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef MPLAB_PIC24_PORT
|
||||
#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef MPLAB_DSPIC_PORT
|
||||
#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef MPLAB_PIC18F_PORT
|
||||
#include "../../Source/portable/MPLAB/PIC18F/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef MPLAB_PIC32MX_PORT
|
||||
#include "../../Source/portable/MPLAB/PIC32MX/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef _FEDPICC
|
||||
#include "libFreeRTOS/Include/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef SDCC_CYGNAL
|
||||
#include "../../Source/portable/SDCC/Cygnal/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_ARM7
|
||||
#include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_ARM7_ECLIPSE
|
||||
#include "portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef ROWLEY_LPC23xx
|
||||
#include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef IAR_MSP430
|
||||
#include "..\..\Source\portable\IAR\MSP430\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_MSP430
|
||||
#include "../../Source/portable/GCC/MSP430F449/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef ROWLEY_MSP430
|
||||
#include "../../Source/portable/Rowley/MSP430F449/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef ARM7_LPC21xx_KEIL_RVDS
|
||||
#include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef SAM7_GCC
|
||||
#include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef SAM7_IAR
|
||||
#include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef SAM9XE_IAR
|
||||
#include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef LPC2000_IAR
|
||||
#include "..\..\Source\portable\IAR\LPC2000\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef STR71X_IAR
|
||||
#include "..\..\Source\portable\IAR\STR71x\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef STR75X_IAR
|
||||
#include "..\..\Source\portable\IAR\STR75x\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef STR75X_GCC
|
||||
#include "..\..\Source\portable\GCC\STR75x\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef STR91X_IAR
|
||||
#include "..\..\Source\portable\IAR\STR91x\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_H8S
|
||||
#include "../../Source/portable/GCC/H8S2329/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_AT91FR40008
|
||||
#include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef RVDS_ARMCM3_LM3S102
|
||||
#include "../../Source/portable/RVDS/ARM_CM3/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_ARMCM3_LM3S102
|
||||
#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_ARMCM3
|
||||
#include "../../Source/portable/GCC/ARM_CM3/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef IAR_ARM_CM3
|
||||
#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef IAR_ARMCM3_LM
|
||||
#include "../../Source/portable/IAR/ARM_CM3/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef HCS12_CODE_WARRIOR
|
||||
#include "../../Source/portable/CodeWarrior/HCS12/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef MICROBLAZE_GCC
|
||||
#include "../../Source/portable/GCC/MicroBlaze/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef TERN_EE
|
||||
#include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_HCS12
|
||||
#include "../../Source/portable/GCC/HCS12/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_MCF5235
|
||||
#include "../../Source/portable/GCC/MCF5235/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef COLDFIRE_V2_GCC
|
||||
#include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef COLDFIRE_V2_CODEWARRIOR
|
||||
#include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_PPC405
|
||||
#include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef GCC_PPC440
|
||||
#include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef _16FX_SOFTUNE
|
||||
#include "..\..\Source\portable\Softune\MB96340\portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef BCC_INDUSTRIAL_PC_PORT
|
||||
/* A short file name has to be used in place of the normal
|
||||
FreeRTOSConfig.h when using the Borland compiler. */
|
||||
#include "frconfig.h"
|
||||
#include "..\portable\BCC\16BitDOS\PC\prtmacro.h"
|
||||
typedef void ( __interrupt __far *pxISR )();
|
||||
#endif
|
||||
|
||||
#ifdef BCC_FLASH_LITE_186_PORT
|
||||
/* A short file name has to be used in place of the normal
|
||||
FreeRTOSConfig.h when using the Borland compiler. */
|
||||
#include "frconfig.h"
|
||||
#include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h"
|
||||
typedef void ( __interrupt __far *pxISR )();
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifdef __AVR32_AVR32A__
|
||||
#include "portmacro.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __ICCAVR32__
|
||||
#ifdef __CORE__
|
||||
#if __CORE__ == __AVR32A__
|
||||
#include "portmacro.h"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __91467D
|
||||
#include "portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef __96340
|
||||
#include "portmacro.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __IAR_V850ES_Fx3__
|
||||
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef __IAR_V850ES_Jx3__
|
||||
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef __IAR_V850ES_Jx3_L__
|
||||
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef __IAR_V850ES_Jx2__
|
||||
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef __IAR_V850ES_Hx2__
|
||||
#include "../../Source/portable/IAR/V850ES/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef __IAR_78K0R_Kx3__
|
||||
#include "../../Source/portable/IAR/78K0R/portmacro.h"
|
||||
#endif
|
||||
|
||||
#ifdef __IAR_78K0R_Kx3L__
|
||||
#include "../../Source/portable/IAR/78K0R/portmacro.h"
|
||||
#endif
|
||||
|
||||
#endif /* DEPRECATED_DEFINITIONS_H */
|
||||
|
||||
|
|
@ -0,0 +1,797 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef EVENT_GROUPS_H
|
||||
#define EVENT_GROUPS_H
|
||||
|
||||
#ifndef INC_FREERTOS_H
|
||||
#error "include FreeRTOS.h" must appear in source files before "include event_groups.h"
|
||||
#endif
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "timers.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* An event group is a collection of bits to which an application can assign a
|
||||
* meaning. For example, an application may create an event group to convey
|
||||
* the status of various CAN bus related events in which bit 0 might mean "A CAN
|
||||
* message has been received and is ready for processing", bit 1 might mean "The
|
||||
* application has queued a message that is ready for sending onto the CAN
|
||||
* network", and bit 2 might mean "It is time to send a SYNC message onto the
|
||||
* CAN network" etc. A task can then test the bit values to see which events
|
||||
* are active, and optionally enter the Blocked state to wait for a specified
|
||||
* bit or a group of specified bits to be active. To continue the CAN bus
|
||||
* example, a CAN controlling task can enter the Blocked state (and therefore
|
||||
* not consume any processing time) until either bit 0, bit 1 or bit 2 are
|
||||
* active, at which time the bit that was actually active would inform the task
|
||||
* which action it had to take (process a received message, send a message, or
|
||||
* send a SYNC).
|
||||
*
|
||||
* The event groups implementation contains intelligence to avoid race
|
||||
* conditions that would otherwise occur were an application to use a simple
|
||||
* variable for the same purpose. This is particularly important with respect
|
||||
* to when a bit within an event group is to be cleared, and when bits have to
|
||||
* be set and then tested atomically - as is the case where event groups are
|
||||
* used to create a synchronisation point between multiple tasks (a
|
||||
* 'rendezvous').
|
||||
*
|
||||
* \defgroup EventGroup
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*
|
||||
* Type by which event groups are referenced. For example, a call to
|
||||
* xEventGroupCreate() returns an EventGroupHandle_t variable that can then
|
||||
* be used as a parameter to other event group functions.
|
||||
*
|
||||
* \defgroup EventGroupHandle_t EventGroupHandle_t
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
typedef void * EventGroupHandle_t;
|
||||
|
||||
/*
|
||||
* The type that holds event bits always matches TickType_t - therefore the
|
||||
* number of bits it holds is set by configUSE_16_BIT_TICKS (16 bits if set to 1,
|
||||
* 32 bits if set to 0.
|
||||
*
|
||||
* \defgroup EventBits_t EventBits_t
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
typedef TickType_t EventBits_t;
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
EventGroupHandle_t xEventGroupCreate( void );
|
||||
</pre>
|
||||
*
|
||||
* Create a new event group.
|
||||
*
|
||||
* Internally, within the FreeRTOS implementation, event groups use a [small]
|
||||
* block of memory, in which the event group's structure is stored. If an event
|
||||
* groups is created using xEventGropuCreate() then the required memory is
|
||||
* automatically dynamically allocated inside the xEventGroupCreate() function.
|
||||
* (see http://www.freertos.org/a00111.html). If an event group is created
|
||||
* using xEventGropuCreateStatic() then the application writer must instead
|
||||
* provide the memory that will get used by the event group.
|
||||
* xEventGroupCreateStatic() therefore allows an event group to be created
|
||||
* without using any dynamic memory allocation.
|
||||
*
|
||||
* Although event groups are not related to ticks, for internal implementation
|
||||
* reasons the number of bits available for use in an event group is dependent
|
||||
* on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If
|
||||
* configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit
|
||||
* 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has
|
||||
* 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store
|
||||
* event bits within an event group.
|
||||
*
|
||||
* @return If the event group was created then a handle to the event group is
|
||||
* returned. If there was insufficient FreeRTOS heap available to create the
|
||||
* event group then NULL is returned. See http://www.freertos.org/a00111.html
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// Declare a variable to hold the created event group.
|
||||
EventGroupHandle_t xCreatedEventGroup;
|
||||
|
||||
// Attempt to create the event group.
|
||||
xCreatedEventGroup = xEventGroupCreate();
|
||||
|
||||
// Was the event group created successfully?
|
||||
if( xCreatedEventGroup == NULL )
|
||||
{
|
||||
// The event group was not created because there was insufficient
|
||||
// FreeRTOS heap available.
|
||||
}
|
||||
else
|
||||
{
|
||||
// The event group was created.
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xEventGroupCreate xEventGroupCreate
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
|
||||
EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer );
|
||||
</pre>
|
||||
*
|
||||
* Create a new event group.
|
||||
*
|
||||
* Internally, within the FreeRTOS implementation, event groups use a [small]
|
||||
* block of memory, in which the event group's structure is stored. If an event
|
||||
* groups is created using xEventGropuCreate() then the required memory is
|
||||
* automatically dynamically allocated inside the xEventGroupCreate() function.
|
||||
* (see http://www.freertos.org/a00111.html). If an event group is created
|
||||
* using xEventGropuCreateStatic() then the application writer must instead
|
||||
* provide the memory that will get used by the event group.
|
||||
* xEventGroupCreateStatic() therefore allows an event group to be created
|
||||
* without using any dynamic memory allocation.
|
||||
*
|
||||
* Although event groups are not related to ticks, for internal implementation
|
||||
* reasons the number of bits available for use in an event group is dependent
|
||||
* on the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If
|
||||
* configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit
|
||||
* 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has
|
||||
* 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store
|
||||
* event bits within an event group.
|
||||
*
|
||||
* @param pxEventGroupBuffer pxEventGroupBuffer must point to a variable of type
|
||||
* StaticEventGroup_t, which will be then be used to hold the event group's data
|
||||
* structures, removing the need for the memory to be allocated dynamically.
|
||||
*
|
||||
* @return If the event group was created then a handle to the event group is
|
||||
* returned. If pxEventGroupBuffer was NULL then NULL is returned.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// StaticEventGroup_t is a publicly accessible structure that has the same
|
||||
// size and alignment requirements as the real event group structure. It is
|
||||
// provided as a mechanism for applications to know the size of the event
|
||||
// group (which is dependent on the architecture and configuration file
|
||||
// settings) without breaking the strict data hiding policy by exposing the
|
||||
// real event group internals. This StaticEventGroup_t variable is passed
|
||||
// into the xSemaphoreCreateEventGroupStatic() function and is used to store
|
||||
// the event group's data structures
|
||||
StaticEventGroup_t xEventGroupBuffer;
|
||||
|
||||
// Create the event group without dynamically allocating any memory.
|
||||
xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );
|
||||
</pre>
|
||||
*/
|
||||
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
|
||||
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToWaitFor,
|
||||
const BaseType_t xClearOnExit,
|
||||
const BaseType_t xWaitForAllBits,
|
||||
const TickType_t xTicksToWait );
|
||||
</pre>
|
||||
*
|
||||
* [Potentially] block to wait for one or more bits to be set within a
|
||||
* previously created event group.
|
||||
*
|
||||
* This function cannot be called from an interrupt.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are being tested. The
|
||||
* event group must have previously been created using a call to
|
||||
* xEventGroupCreate().
|
||||
*
|
||||
* @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
|
||||
* inside the event group. For example, to wait for bit 0 and/or bit 2 set
|
||||
* uxBitsToWaitFor to 0x05. To wait for bits 0 and/or bit 1 and/or bit 2 set
|
||||
* uxBitsToWaitFor to 0x07. Etc.
|
||||
*
|
||||
* @param xClearOnExit If xClearOnExit is set to pdTRUE then any bits within
|
||||
* uxBitsToWaitFor that are set within the event group will be cleared before
|
||||
* xEventGroupWaitBits() returns if the wait condition was met (if the function
|
||||
* returns for a reason other than a timeout). If xClearOnExit is set to
|
||||
* pdFALSE then the bits set in the event group are not altered when the call to
|
||||
* xEventGroupWaitBits() returns.
|
||||
*
|
||||
* @param xWaitForAllBits If xWaitForAllBits is set to pdTRUE then
|
||||
* xEventGroupWaitBits() will return when either all the bits in uxBitsToWaitFor
|
||||
* are set or the specified block time expires. If xWaitForAllBits is set to
|
||||
* pdFALSE then xEventGroupWaitBits() will return when any one of the bits set
|
||||
* in uxBitsToWaitFor is set or the specified block time expires. The block
|
||||
* time is specified by the xTicksToWait parameter.
|
||||
*
|
||||
* @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
|
||||
* for one/all (depending on the xWaitForAllBits value) of the bits specified by
|
||||
* uxBitsToWaitFor to become set.
|
||||
*
|
||||
* @return The value of the event group at the time either the bits being waited
|
||||
* for became set, or the block time expired. Test the return value to know
|
||||
* which bits were set. If xEventGroupWaitBits() returned because its timeout
|
||||
* expired then not all the bits being waited for will be set. If
|
||||
* xEventGroupWaitBits() returned because the bits it was waiting for were set
|
||||
* then the returned value is the event group value before any bits were
|
||||
* automatically cleared in the case that xClearOnExit parameter was set to
|
||||
* pdTRUE.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
#define BIT_0 ( 1 << 0 )
|
||||
#define BIT_4 ( 1 << 4 )
|
||||
|
||||
void aFunction( EventGroupHandle_t xEventGroup )
|
||||
{
|
||||
EventBits_t uxBits;
|
||||
const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
|
||||
|
||||
// Wait a maximum of 100ms for either bit 0 or bit 4 to be set within
|
||||
// the event group. Clear the bits before exiting.
|
||||
uxBits = xEventGroupWaitBits(
|
||||
xEventGroup, // The event group being tested.
|
||||
BIT_0 | BIT_4, // The bits within the event group to wait for.
|
||||
pdTRUE, // BIT_0 and BIT_4 should be cleared before returning.
|
||||
pdFALSE, // Don't wait for both bits, either bit will do.
|
||||
xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.
|
||||
|
||||
if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
|
||||
{
|
||||
// xEventGroupWaitBits() returned because both bits were set.
|
||||
}
|
||||
else if( ( uxBits & BIT_0 ) != 0 )
|
||||
{
|
||||
// xEventGroupWaitBits() returned because just BIT_0 was set.
|
||||
}
|
||||
else if( ( uxBits & BIT_4 ) != 0 )
|
||||
{
|
||||
// xEventGroupWaitBits() returned because just BIT_4 was set.
|
||||
}
|
||||
else
|
||||
{
|
||||
// xEventGroupWaitBits() returned because xTicksToWait ticks passed
|
||||
// without either BIT_0 or BIT_4 becoming set.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xEventGroupWaitBits xEventGroupWaitBits
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
|
||||
</pre>
|
||||
*
|
||||
* Clear bits within an event group. This function cannot be called from an
|
||||
* interrupt.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are to be cleared.
|
||||
*
|
||||
* @param uxBitsToClear A bitwise value that indicates the bit or bits to clear
|
||||
* in the event group. For example, to clear bit 3 only, set uxBitsToClear to
|
||||
* 0x08. To clear bit 3 and bit 0 set uxBitsToClear to 0x09.
|
||||
*
|
||||
* @return The value of the event group before the specified bits were cleared.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
#define BIT_0 ( 1 << 0 )
|
||||
#define BIT_4 ( 1 << 4 )
|
||||
|
||||
void aFunction( EventGroupHandle_t xEventGroup )
|
||||
{
|
||||
EventBits_t uxBits;
|
||||
|
||||
// Clear bit 0 and bit 4 in xEventGroup.
|
||||
uxBits = xEventGroupClearBits(
|
||||
xEventGroup, // The event group being updated.
|
||||
BIT_0 | BIT_4 );// The bits being cleared.
|
||||
|
||||
if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
|
||||
{
|
||||
// Both bit 0 and bit 4 were set before xEventGroupClearBits() was
|
||||
// called. Both will now be clear (not set).
|
||||
}
|
||||
else if( ( uxBits & BIT_0 ) != 0 )
|
||||
{
|
||||
// Bit 0 was set before xEventGroupClearBits() was called. It will
|
||||
// now be clear.
|
||||
}
|
||||
else if( ( uxBits & BIT_4 ) != 0 )
|
||||
{
|
||||
// Bit 4 was set before xEventGroupClearBits() was called. It will
|
||||
// now be clear.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Neither bit 0 nor bit 4 were set in the first place.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xEventGroupClearBits xEventGroupClearBits
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
|
||||
</pre>
|
||||
*
|
||||
* A version of xEventGroupClearBits() that can be called from an interrupt.
|
||||
*
|
||||
* Setting bits in an event group is not a deterministic operation because there
|
||||
* are an unknown number of tasks that may be waiting for the bit or bits being
|
||||
* set. FreeRTOS does not allow nondeterministic operations to be performed
|
||||
* while interrupts are disabled, so protects event groups that are accessed
|
||||
* from tasks by suspending the scheduler rather than disabling interrupts. As
|
||||
* a result event groups cannot be accessed directly from an interrupt service
|
||||
* routine. Therefore xEventGroupClearBitsFromISR() sends a message to the
|
||||
* timer task to have the clear operation performed in the context of the timer
|
||||
* task.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are to be cleared.
|
||||
*
|
||||
* @param uxBitsToClear A bitwise value that indicates the bit or bits to clear.
|
||||
* For example, to clear bit 3 only, set uxBitsToClear to 0x08. To clear bit 3
|
||||
* and bit 0 set uxBitsToClear to 0x09.
|
||||
*
|
||||
* @return If the request to execute the function was posted successfully then
|
||||
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
|
||||
* if the timer service queue was full.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
#define BIT_0 ( 1 << 0 )
|
||||
#define BIT_4 ( 1 << 4 )
|
||||
|
||||
// An event group which it is assumed has already been created by a call to
|
||||
// xEventGroupCreate().
|
||||
EventGroupHandle_t xEventGroup;
|
||||
|
||||
void anInterruptHandler( void )
|
||||
{
|
||||
// Clear bit 0 and bit 4 in xEventGroup.
|
||||
xResult = xEventGroupClearBitsFromISR(
|
||||
xEventGroup, // The event group being updated.
|
||||
BIT_0 | BIT_4 ); // The bits being set.
|
||||
|
||||
if( xResult == pdPASS )
|
||||
{
|
||||
// The message was posted successfully.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
#if( configUSE_TRACE_FACILITY == 1 )
|
||||
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;
|
||||
#else
|
||||
#define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
|
||||
</pre>
|
||||
*
|
||||
* Set bits within an event group.
|
||||
* This function cannot be called from an interrupt. xEventGroupSetBitsFromISR()
|
||||
* is a version that can be called from an interrupt.
|
||||
*
|
||||
* Setting bits in an event group will automatically unblock tasks that are
|
||||
* blocked waiting for the bits.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are to be set.
|
||||
*
|
||||
* @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
|
||||
* For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
|
||||
* and bit 0 set uxBitsToSet to 0x09.
|
||||
*
|
||||
* @return The value of the event group at the time the call to
|
||||
* xEventGroupSetBits() returns. There are two reasons why the returned value
|
||||
* might have the bits specified by the uxBitsToSet parameter cleared. First,
|
||||
* if setting a bit results in a task that was waiting for the bit leaving the
|
||||
* blocked state then it is possible the bit will be cleared automatically
|
||||
* (see the xClearBitOnExit parameter of xEventGroupWaitBits()). Second, any
|
||||
* unblocked (or otherwise Ready state) task that has a priority above that of
|
||||
* the task that called xEventGroupSetBits() will execute and may change the
|
||||
* event group value before the call to xEventGroupSetBits() returns.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
#define BIT_0 ( 1 << 0 )
|
||||
#define BIT_4 ( 1 << 4 )
|
||||
|
||||
void aFunction( EventGroupHandle_t xEventGroup )
|
||||
{
|
||||
EventBits_t uxBits;
|
||||
|
||||
// Set bit 0 and bit 4 in xEventGroup.
|
||||
uxBits = xEventGroupSetBits(
|
||||
xEventGroup, // The event group being updated.
|
||||
BIT_0 | BIT_4 );// The bits being set.
|
||||
|
||||
if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
|
||||
{
|
||||
// Both bit 0 and bit 4 remained set when the function returned.
|
||||
}
|
||||
else if( ( uxBits & BIT_0 ) != 0 )
|
||||
{
|
||||
// Bit 0 remained set when the function returned, but bit 4 was
|
||||
// cleared. It might be that bit 4 was cleared automatically as a
|
||||
// task that was waiting for bit 4 was removed from the Blocked
|
||||
// state.
|
||||
}
|
||||
else if( ( uxBits & BIT_4 ) != 0 )
|
||||
{
|
||||
// Bit 4 remained set when the function returned, but bit 0 was
|
||||
// cleared. It might be that bit 0 was cleared automatically as a
|
||||
// task that was waiting for bit 0 was removed from the Blocked
|
||||
// state.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Neither bit 0 nor bit 4 remained set. It might be that a task
|
||||
// was waiting for both of the bits to be set, and the bits were
|
||||
// cleared as the task left the Blocked state.
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xEventGroupSetBits xEventGroupSetBits
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken );
|
||||
</pre>
|
||||
*
|
||||
* A version of xEventGroupSetBits() that can be called from an interrupt.
|
||||
*
|
||||
* Setting bits in an event group is not a deterministic operation because there
|
||||
* are an unknown number of tasks that may be waiting for the bit or bits being
|
||||
* set. FreeRTOS does not allow nondeterministic operations to be performed in
|
||||
* interrupts or from critical sections. Therefore xEventGroupSetBitsFromISR()
|
||||
* sends a message to the timer task to have the set operation performed in the
|
||||
* context of the timer task - where a scheduler lock is used in place of a
|
||||
* critical section.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are to be set.
|
||||
*
|
||||
* @param uxBitsToSet A bitwise value that indicates the bit or bits to set.
|
||||
* For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3
|
||||
* and bit 0 set uxBitsToSet to 0x09.
|
||||
*
|
||||
* @param pxHigherPriorityTaskWoken As mentioned above, calling this function
|
||||
* will result in a message being sent to the timer daemon task. If the
|
||||
* priority of the timer daemon task is higher than the priority of the
|
||||
* currently running task (the task the interrupt interrupted) then
|
||||
* *pxHigherPriorityTaskWoken will be set to pdTRUE by
|
||||
* xEventGroupSetBitsFromISR(), indicating that a context switch should be
|
||||
* requested before the interrupt exits. For that reason
|
||||
* *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the
|
||||
* example code below.
|
||||
*
|
||||
* @return If the request to execute the function was posted successfully then
|
||||
* pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned
|
||||
* if the timer service queue was full.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
#define BIT_0 ( 1 << 0 )
|
||||
#define BIT_4 ( 1 << 4 )
|
||||
|
||||
// An event group which it is assumed has already been created by a call to
|
||||
// xEventGroupCreate().
|
||||
EventGroupHandle_t xEventGroup;
|
||||
|
||||
void anInterruptHandler( void )
|
||||
{
|
||||
BaseType_t xHigherPriorityTaskWoken, xResult;
|
||||
|
||||
// xHigherPriorityTaskWoken must be initialised to pdFALSE.
|
||||
xHigherPriorityTaskWoken = pdFALSE;
|
||||
|
||||
// Set bit 0 and bit 4 in xEventGroup.
|
||||
xResult = xEventGroupSetBitsFromISR(
|
||||
xEventGroup, // The event group being updated.
|
||||
BIT_0 | BIT_4 // The bits being set.
|
||||
&xHigherPriorityTaskWoken );
|
||||
|
||||
// Was the message posted successfully?
|
||||
if( xResult == pdPASS )
|
||||
{
|
||||
// If xHigherPriorityTaskWoken is now set to pdTRUE then a context
|
||||
// switch should be requested. The macro used is port specific and
|
||||
// will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() -
|
||||
// refer to the documentation page for the port being used.
|
||||
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
* \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
#if( configUSE_TRACE_FACILITY == 1 )
|
||||
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||
#else
|
||||
#define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
|
||||
const EventBits_t uxBitsToSet,
|
||||
const EventBits_t uxBitsToWaitFor,
|
||||
TickType_t xTicksToWait );
|
||||
</pre>
|
||||
*
|
||||
* Atomically set bits within an event group, then wait for a combination of
|
||||
* bits to be set within the same event group. This functionality is typically
|
||||
* used to synchronise multiple tasks, where each task has to wait for the other
|
||||
* tasks to reach a synchronisation point before proceeding.
|
||||
*
|
||||
* This function cannot be used from an interrupt.
|
||||
*
|
||||
* The function will return before its block time expires if the bits specified
|
||||
* by the uxBitsToWait parameter are set, or become set within that time. In
|
||||
* this case all the bits specified by uxBitsToWait will be automatically
|
||||
* cleared before the function returns.
|
||||
*
|
||||
* @param xEventGroup The event group in which the bits are being tested. The
|
||||
* event group must have previously been created using a call to
|
||||
* xEventGroupCreate().
|
||||
*
|
||||
* @param uxBitsToSet The bits to set in the event group before determining
|
||||
* if, and possibly waiting for, all the bits specified by the uxBitsToWait
|
||||
* parameter are set.
|
||||
*
|
||||
* @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test
|
||||
* inside the event group. For example, to wait for bit 0 and bit 2 set
|
||||
* uxBitsToWaitFor to 0x05. To wait for bits 0 and bit 1 and bit 2 set
|
||||
* uxBitsToWaitFor to 0x07. Etc.
|
||||
*
|
||||
* @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait
|
||||
* for all of the bits specified by uxBitsToWaitFor to become set.
|
||||
*
|
||||
* @return The value of the event group at the time either the bits being waited
|
||||
* for became set, or the block time expired. Test the return value to know
|
||||
* which bits were set. If xEventGroupSync() returned because its timeout
|
||||
* expired then not all the bits being waited for will be set. If
|
||||
* xEventGroupSync() returned because all the bits it was waiting for were
|
||||
* set then the returned value is the event group value before any bits were
|
||||
* automatically cleared.
|
||||
*
|
||||
* Example usage:
|
||||
<pre>
|
||||
// Bits used by the three tasks.
|
||||
#define TASK_0_BIT ( 1 << 0 )
|
||||
#define TASK_1_BIT ( 1 << 1 )
|
||||
#define TASK_2_BIT ( 1 << 2 )
|
||||
|
||||
#define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT )
|
||||
|
||||
// Use an event group to synchronise three tasks. It is assumed this event
|
||||
// group has already been created elsewhere.
|
||||
EventGroupHandle_t xEventBits;
|
||||
|
||||
void vTask0( void *pvParameters )
|
||||
{
|
||||
EventBits_t uxReturn;
|
||||
TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// Perform task functionality here.
|
||||
|
||||
// Set bit 0 in the event flag to note this task has reached the
|
||||
// sync point. The other two tasks will set the other two bits defined
|
||||
// by ALL_SYNC_BITS. All three tasks have reached the synchronisation
|
||||
// point when all the ALL_SYNC_BITS are set. Wait a maximum of 100ms
|
||||
// for this to happen.
|
||||
uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait );
|
||||
|
||||
if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS )
|
||||
{
|
||||
// All three tasks reached the synchronisation point before the call
|
||||
// to xEventGroupSync() timed out.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vTask1( void *pvParameters )
|
||||
{
|
||||
for( ;; )
|
||||
{
|
||||
// Perform task functionality here.
|
||||
|
||||
// Set bit 1 in the event flag to note this task has reached the
|
||||
// synchronisation point. The other two tasks will set the other two
|
||||
// bits defined by ALL_SYNC_BITS. All three tasks have reached the
|
||||
// synchronisation point when all the ALL_SYNC_BITS are set. Wait
|
||||
// indefinitely for this to happen.
|
||||
xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY );
|
||||
|
||||
// xEventGroupSync() was called with an indefinite block time, so
|
||||
// this task will only reach here if the syncrhonisation was made by all
|
||||
// three tasks, so there is no need to test the return value.
|
||||
}
|
||||
}
|
||||
|
||||
void vTask2( void *pvParameters )
|
||||
{
|
||||
for( ;; )
|
||||
{
|
||||
// Perform task functionality here.
|
||||
|
||||
// Set bit 2 in the event flag to note this task has reached the
|
||||
// synchronisation point. The other two tasks will set the other two
|
||||
// bits defined by ALL_SYNC_BITS. All three tasks have reached the
|
||||
// synchronisation point when all the ALL_SYNC_BITS are set. Wait
|
||||
// indefinitely for this to happen.
|
||||
xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY );
|
||||
|
||||
// xEventGroupSync() was called with an indefinite block time, so
|
||||
// this task will only reach here if the syncrhonisation was made by all
|
||||
// three tasks, so there is no need to test the return value.
|
||||
}
|
||||
}
|
||||
|
||||
</pre>
|
||||
* \defgroup xEventGroupSync xEventGroupSync
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
|
||||
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );
|
||||
</pre>
|
||||
*
|
||||
* Returns the current value of the bits in an event group. This function
|
||||
* cannot be used from an interrupt.
|
||||
*
|
||||
* @param xEventGroup The event group being queried.
|
||||
*
|
||||
* @return The event group bits at the time xEventGroupGetBits() was called.
|
||||
*
|
||||
* \defgroup xEventGroupGetBits xEventGroupGetBits
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 )
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );
|
||||
</pre>
|
||||
*
|
||||
* A version of xEventGroupGetBits() that can be called from an ISR.
|
||||
*
|
||||
* @param xEventGroup The event group being queried.
|
||||
*
|
||||
* @return The event group bits at the time xEventGroupGetBitsFromISR() was called.
|
||||
*
|
||||
* \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR
|
||||
* \ingroup EventGroup
|
||||
*/
|
||||
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* event_groups.h
|
||||
*<pre>
|
||||
void xEventGroupDelete( EventGroupHandle_t xEventGroup );
|
||||
</pre>
|
||||
*
|
||||
* Delete an event group that was previously created by a call to
|
||||
* xEventGroupCreate(). Tasks that are blocked on the event group will be
|
||||
* unblocked and obtain 0 as the event group's value.
|
||||
*
|
||||
* @param xEventGroup The event group being deleted.
|
||||
*/
|
||||
void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/* For internal use only. */
|
||||
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION;
|
||||
void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION;
|
||||
|
||||
|
||||
#if (configUSE_TRACE_FACILITY == 1)
|
||||
UBaseType_t uxEventGroupGetNumber( void* xEventGroup ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EVENT_GROUPS_H */
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,453 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is the list implementation used by the scheduler. While it is tailored
|
||||
* heavily for the schedulers needs, it is also available for use by
|
||||
* application code.
|
||||
*
|
||||
* list_ts can only store pointers to list_item_ts. Each ListItem_t contains a
|
||||
* numeric value (xItemValue). Most of the time the lists are sorted in
|
||||
* descending item value order.
|
||||
*
|
||||
* Lists are created already containing one list item. The value of this
|
||||
* item is the maximum possible that can be stored, it is therefore always at
|
||||
* the end of the list and acts as a marker. The list member pxHead always
|
||||
* points to this marker - even though it is at the tail of the list. This
|
||||
* is because the tail contains a wrap back pointer to the true head of
|
||||
* the list.
|
||||
*
|
||||
* In addition to it's value, each list item contains a pointer to the next
|
||||
* item in the list (pxNext), a pointer to the list it is in (pxContainer)
|
||||
* and a pointer to back to the object that contains it. These later two
|
||||
* pointers are included for efficiency of list manipulation. There is
|
||||
* effectively a two way link between the object containing the list item and
|
||||
* the list item itself.
|
||||
*
|
||||
*
|
||||
* \page ListIntroduction List Implementation
|
||||
* \ingroup FreeRTOSIntro
|
||||
*/
|
||||
|
||||
#ifndef INC_FREERTOS_H
|
||||
#error FreeRTOS.h must be included before list.h
|
||||
#endif
|
||||
|
||||
#ifndef LIST_H
|
||||
#define LIST_H
|
||||
|
||||
/*
|
||||
* The list structure members are modified from within interrupts, and therefore
|
||||
* by rights should be declared volatile. However, they are only modified in a
|
||||
* functionally atomic way (within critical sections of with the scheduler
|
||||
* suspended) and are either passed by reference into a function or indexed via
|
||||
* a volatile variable. Therefore, in all use cases tested so far, the volatile
|
||||
* qualifier can be omitted in order to provide a moderate performance
|
||||
* improvement without adversely affecting functional behaviour. The assembly
|
||||
* instructions generated by the IAR, ARM and GCC compilers when the respective
|
||||
* compiler's options were set for maximum optimisation has been inspected and
|
||||
* deemed to be as intended. That said, as compiler technology advances, and
|
||||
* especially if aggressive cross module optimisation is used (a use case that
|
||||
* has not been exercised to any great extend) then it is feasible that the
|
||||
* volatile qualifier will be needed for correct optimisation. It is expected
|
||||
* that a compiler removing essential code because, without the volatile
|
||||
* qualifier on the list structure members and with aggressive cross module
|
||||
* optimisation, the compiler deemed the code unnecessary will result in
|
||||
* complete and obvious failure of the scheduler. If this is ever experienced
|
||||
* then the volatile qualifier can be inserted in the relevant places within the
|
||||
* list structures by simply defining configLIST_VOLATILE to volatile in
|
||||
* FreeRTOSConfig.h (as per the example at the bottom of this comment block).
|
||||
* If configLIST_VOLATILE is not defined then the preprocessor directives below
|
||||
* will simply #define configLIST_VOLATILE away completely.
|
||||
*
|
||||
* To use volatile list structure members then add the following line to
|
||||
* FreeRTOSConfig.h (without the quotes):
|
||||
* "#define configLIST_VOLATILE volatile"
|
||||
*/
|
||||
#ifndef configLIST_VOLATILE
|
||||
#define configLIST_VOLATILE
|
||||
#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Macros that can be used to place known values within the list structures,
|
||||
then check that the known values do not get corrupted during the execution of
|
||||
the application. These may catch the list data structures being overwritten in
|
||||
memory. They will not catch data errors caused by incorrect configuration or
|
||||
use of FreeRTOS.*/
|
||||
#if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 )
|
||||
/* Define the macros to do nothing. */
|
||||
#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE
|
||||
#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE
|
||||
#define listFIRST_LIST_INTEGRITY_CHECK_VALUE
|
||||
#define listSECOND_LIST_INTEGRITY_CHECK_VALUE
|
||||
#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
|
||||
#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem )
|
||||
#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )
|
||||
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )
|
||||
#define listTEST_LIST_ITEM_INTEGRITY( pxItem )
|
||||
#define listTEST_LIST_INTEGRITY( pxList )
|
||||
#else
|
||||
/* Define macros that add new members into the list structures. */
|
||||
#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1;
|
||||
#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2;
|
||||
#define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1;
|
||||
#define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2;
|
||||
|
||||
/* Define macros that set the new structure members to known values. */
|
||||
#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
|
||||
#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
|
||||
#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE
|
||||
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE
|
||||
|
||||
/* Define macros that will assert if one of the structure members does not
|
||||
contain its expected value. */
|
||||
#define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
|
||||
#define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) )
|
||||
#endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */
|
||||
|
||||
|
||||
/*
|
||||
* Definition of the only type of object that a list can contain.
|
||||
*/
|
||||
struct xLIST_ITEM
|
||||
{
|
||||
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */
|
||||
struct xLIST_ITEM * configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */
|
||||
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */
|
||||
void * pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */
|
||||
void * configLIST_VOLATILE pvContainer; /*< Pointer to the list in which this list item is placed (if any). */
|
||||
listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
};
|
||||
typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */
|
||||
|
||||
struct xMINI_LIST_ITEM
|
||||
{
|
||||
listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
configLIST_VOLATILE TickType_t xItemValue;
|
||||
struct xLIST_ITEM * configLIST_VOLATILE pxNext;
|
||||
struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;
|
||||
};
|
||||
typedef struct xMINI_LIST_ITEM MiniListItem_t;
|
||||
|
||||
/*
|
||||
* Definition of the type of queue used by the scheduler.
|
||||
*/
|
||||
typedef struct xLIST
|
||||
{
|
||||
listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
configLIST_VOLATILE UBaseType_t uxNumberOfItems;
|
||||
ListItem_t * configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */
|
||||
MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */
|
||||
listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
} List_t;
|
||||
|
||||
/*
|
||||
* Access macro to set the owner of a list item. The owner of a list item
|
||||
* is the object (usually a TCB) that contains the list item.
|
||||
*
|
||||
* \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) )
|
||||
|
||||
/*
|
||||
* Access macro to get the owner of a list item. The owner of a list item
|
||||
* is the object (usually a TCB) that contains the list item.
|
||||
*
|
||||
* \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner )
|
||||
|
||||
/*
|
||||
* Access macro to set the value of the list item. In most cases the value is
|
||||
* used to sort the list in descending order.
|
||||
*
|
||||
* \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) )
|
||||
|
||||
/*
|
||||
* Access macro to retrieve the value of the list item. The value can
|
||||
* represent anything - for example the priority of a task, or the time at
|
||||
* which a task should be unblocked.
|
||||
*
|
||||
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue )
|
||||
|
||||
/*
|
||||
* Access macro to retrieve the value of the list item at the head of a given
|
||||
* list.
|
||||
*
|
||||
* \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue )
|
||||
|
||||
/*
|
||||
* Return the list item at the head of the list.
|
||||
*
|
||||
* \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext )
|
||||
|
||||
/*
|
||||
* Return the list item at the head of the list.
|
||||
*
|
||||
* \page listGET_NEXT listGET_NEXT
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext )
|
||||
|
||||
/*
|
||||
* Return the list item that marks the end of the list
|
||||
*
|
||||
* \page listGET_END_MARKER listGET_END_MARKER
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) )
|
||||
|
||||
/*
|
||||
* Access macro to determine if a list contains any items. The macro will
|
||||
* only have the value true if the list is empty.
|
||||
*
|
||||
* \page listLIST_IS_EMPTY listLIST_IS_EMPTY
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listLIST_IS_EMPTY( pxList ) ( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) )
|
||||
|
||||
/*
|
||||
* Access macro to return the number of items in the list.
|
||||
*/
|
||||
#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems )
|
||||
|
||||
/*
|
||||
* Access function to obtain the owner of the next entry in a list.
|
||||
*
|
||||
* The list member pxIndex is used to walk through a list. Calling
|
||||
* listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list
|
||||
* and returns that entry's pxOwner parameter. Using multiple calls to this
|
||||
* function it is therefore possible to move through every item contained in
|
||||
* a list.
|
||||
*
|
||||
* The pxOwner parameter of a list item is a pointer to the object that owns
|
||||
* the list item. In the scheduler this is normally a task control block.
|
||||
* The pxOwner parameter effectively creates a two way link between the list
|
||||
* item and its owner.
|
||||
*
|
||||
* @param pxTCB pxTCB is set to the address of the owner of the next list item.
|
||||
* @param pxList The list from which the next item owner is to be returned.
|
||||
*
|
||||
* \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \
|
||||
{ \
|
||||
List_t * const pxConstList = ( pxList ); \
|
||||
/* Increment the index to the next item and return the item, ensuring */ \
|
||||
/* we don't return the marker used at the end of the list. */ \
|
||||
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
|
||||
if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \
|
||||
{ \
|
||||
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
|
||||
} \
|
||||
( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Access function to obtain the owner of the first entry in a list. Lists
|
||||
* are normally sorted in ascending item value order.
|
||||
*
|
||||
* This function returns the pxOwner member of the first item in the list.
|
||||
* The pxOwner parameter of a list item is a pointer to the object that owns
|
||||
* the list item. In the scheduler this is normally a task control block.
|
||||
* The pxOwner parameter effectively creates a two way link between the list
|
||||
* item and its owner.
|
||||
*
|
||||
* @param pxList The list from which the owner of the head item is to be
|
||||
* returned.
|
||||
*
|
||||
* \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner )
|
||||
|
||||
/*
|
||||
* Check to see if a list item is within a list. The list item maintains a
|
||||
* "container" pointer that points to the list it is in. All this macro does
|
||||
* is check to see if the container and the list match.
|
||||
*
|
||||
* @param pxList The list we want to know if the list item is within.
|
||||
* @param pxListItem The list item we want to know if is in the list.
|
||||
* @return pdTRUE if the list item is in the list, otherwise pdFALSE.
|
||||
*/
|
||||
#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( BaseType_t ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) )
|
||||
|
||||
/*
|
||||
* Return the list a list item is contained within (referenced from).
|
||||
*
|
||||
* @param pxListItem The list item being queried.
|
||||
* @return A pointer to the List_t object that references the pxListItem
|
||||
*/
|
||||
#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pvContainer )
|
||||
|
||||
/*
|
||||
* This provides a crude means of knowing if a list has been initialised, as
|
||||
* pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise()
|
||||
* function.
|
||||
*/
|
||||
#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY )
|
||||
|
||||
/*
|
||||
* Must be called before a list is used! This initialises all the members
|
||||
* of the list structure and inserts the xListEnd item into the list as a
|
||||
* marker to the back of the list.
|
||||
*
|
||||
* @param pxList Pointer to the list being initialised.
|
||||
*
|
||||
* \page vListInitialise vListInitialise
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Must be called before a list item is used. This sets the list container to
|
||||
* null so the item does not think that it is already contained in a list.
|
||||
*
|
||||
* @param pxItem Pointer to the list item being initialised.
|
||||
*
|
||||
* \page vListInitialiseItem vListInitialiseItem
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Insert a list item into a list. The item will be inserted into the list in
|
||||
* a position determined by its item value (descending item value order).
|
||||
*
|
||||
* @param pxList The list into which the item is to be inserted.
|
||||
*
|
||||
* @param pxNewListItem The item that is to be placed in the list.
|
||||
*
|
||||
* \page vListInsert vListInsert
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Insert a list item into a list. The item will be inserted in a position
|
||||
* such that it will be the last item within the list returned by multiple
|
||||
* calls to listGET_OWNER_OF_NEXT_ENTRY.
|
||||
*
|
||||
* The list member pxIndex is used to walk through a list. Calling
|
||||
* listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list.
|
||||
* Placing an item in a list using vListInsertEnd effectively places the item
|
||||
* in the list position pointed to by pxIndex. This means that every other
|
||||
* item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before
|
||||
* the pxIndex parameter again points to the item being inserted.
|
||||
*
|
||||
* @param pxList The list into which the item is to be inserted.
|
||||
*
|
||||
* @param pxNewListItem The list item to be inserted into the list.
|
||||
*
|
||||
* \page vListInsertEnd vListInsertEnd
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Remove an item from a list. The list item has a pointer to the list that
|
||||
* it is in, so only the list item need be passed into the function.
|
||||
*
|
||||
* @param uxListRemove The item to be removed. The item will remove itself from
|
||||
* the list pointed to by it's pxContainer parameter.
|
||||
*
|
||||
* @return The number of items that remain in the list after the list item has
|
||||
* been removed.
|
||||
*
|
||||
* \page uxListRemove uxListRemove
|
||||
* \ingroup LinkedList
|
||||
*/
|
||||
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*
|
||||
* When the MPU is used the standard (non MPU) API functions are mapped to
|
||||
* equivalents that start "MPU_", the prototypes for which are defined in this
|
||||
* header files. This will cause the application code to call the MPU_ version
|
||||
* which wraps the non-MPU version with privilege promoting then demoting code,
|
||||
* so the kernel code always runs will full privileges.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MPU_PROTOTYPES_H
|
||||
#define MPU_PROTOTYPES_H
|
||||
|
||||
/* MPU versions of tasks.h API function. */
|
||||
BaseType_t MPU_xTaskCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask );
|
||||
TaskHandle_t MPU_xTaskCreateStatic( TaskFunction_t pxTaskCode, const char * const pcName, const uint32_t ulStackDepth, void * const pvParameters, UBaseType_t uxPriority, StackType_t * const puxStackBuffer, StaticTask_t * const pxTaskBuffer );
|
||||
BaseType_t MPU_xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask );
|
||||
void MPU_vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions );
|
||||
void MPU_vTaskDelete( TaskHandle_t xTaskToDelete );
|
||||
void MPU_vTaskDelay( const TickType_t xTicksToDelay );
|
||||
void MPU_vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement );
|
||||
BaseType_t MPU_xTaskAbortDelay( TaskHandle_t xTask );
|
||||
UBaseType_t MPU_uxTaskPriorityGet( TaskHandle_t xTask );
|
||||
eTaskState MPU_eTaskGetState( TaskHandle_t xTask );
|
||||
void MPU_vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState );
|
||||
void MPU_vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );
|
||||
void MPU_vTaskSuspend( TaskHandle_t xTaskToSuspend );
|
||||
void MPU_vTaskResume( TaskHandle_t xTaskToResume );
|
||||
void MPU_vTaskStartScheduler( void );
|
||||
void MPU_vTaskSuspendAll( void );
|
||||
BaseType_t MPU_xTaskResumeAll( void );
|
||||
TickType_t MPU_xTaskGetTickCount( void );
|
||||
UBaseType_t MPU_uxTaskGetNumberOfTasks( void );
|
||||
char * MPU_pcTaskGetName( TaskHandle_t xTaskToQuery );
|
||||
TaskHandle_t MPU_xTaskGetHandle( const char *pcNameToQuery );
|
||||
UBaseType_t MPU_uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
|
||||
void MPU_vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction );
|
||||
TaskHookFunction_t MPU_xTaskGetApplicationTaskTag( TaskHandle_t xTask );
|
||||
void MPU_vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue );
|
||||
void * MPU_pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, BaseType_t xIndex );
|
||||
BaseType_t MPU_xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter );
|
||||
TaskHandle_t MPU_xTaskGetIdleTaskHandle( void );
|
||||
UBaseType_t MPU_uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime );
|
||||
void MPU_vTaskList( char * pcWriteBuffer );
|
||||
void MPU_vTaskGetRunTimeStats( char *pcWriteBuffer );
|
||||
BaseType_t MPU_xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue );
|
||||
BaseType_t MPU_xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
|
||||
uint32_t MPU_ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
|
||||
BaseType_t MPU_xTaskNotifyStateClear( TaskHandle_t xTask );
|
||||
BaseType_t MPU_xTaskIncrementTick( void );
|
||||
TaskHandle_t MPU_xTaskGetCurrentTaskHandle( void );
|
||||
void MPU_vTaskSetTimeOutState( TimeOut_t * const pxTimeOut );
|
||||
BaseType_t MPU_xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait );
|
||||
void MPU_vTaskMissedYield( void );
|
||||
BaseType_t MPU_xTaskGetSchedulerState( void );
|
||||
|
||||
/* MPU versions of queue.h API function. */
|
||||
BaseType_t MPU_xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition );
|
||||
BaseType_t MPU_xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek );
|
||||
UBaseType_t MPU_uxQueueMessagesWaiting( const QueueHandle_t xQueue );
|
||||
UBaseType_t MPU_uxQueueSpacesAvailable( const QueueHandle_t xQueue );
|
||||
void MPU_vQueueDelete( QueueHandle_t xQueue );
|
||||
QueueHandle_t MPU_xQueueCreateMutex( const uint8_t ucQueueType );
|
||||
QueueHandle_t MPU_xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue );
|
||||
QueueHandle_t MPU_xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount );
|
||||
QueueHandle_t MPU_xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue );
|
||||
void* MPU_xQueueGetMutexHolder( QueueHandle_t xSemaphore );
|
||||
BaseType_t MPU_xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait );
|
||||
BaseType_t MPU_xQueueGiveMutexRecursive( QueueHandle_t pxMutex );
|
||||
void MPU_vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcName );
|
||||
void MPU_vQueueUnregisterQueue( QueueHandle_t xQueue );
|
||||
const char * MPU_pcQueueGetName( QueueHandle_t xQueue );
|
||||
QueueHandle_t MPU_xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType );
|
||||
QueueHandle_t MPU_xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType );
|
||||
QueueSetHandle_t MPU_xQueueCreateSet( const UBaseType_t uxEventQueueLength );
|
||||
BaseType_t MPU_xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet );
|
||||
BaseType_t MPU_xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet );
|
||||
QueueSetMemberHandle_t MPU_xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait );
|
||||
BaseType_t MPU_xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue );
|
||||
void MPU_vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber );
|
||||
UBaseType_t MPU_uxQueueGetQueueNumber( QueueHandle_t xQueue );
|
||||
uint8_t MPU_ucQueueGetQueueType( QueueHandle_t xQueue );
|
||||
|
||||
/* MPU versions of timers.h API function. */
|
||||
TimerHandle_t MPU_xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction );
|
||||
TimerHandle_t MPU_xTimerCreateStatic( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks, const UBaseType_t uxAutoReload, void * const pvTimerID, TimerCallbackFunction_t pxCallbackFunction, StaticTimer_t *pxTimerBuffer );
|
||||
void * MPU_pvTimerGetTimerID( const TimerHandle_t xTimer );
|
||||
void MPU_vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID );
|
||||
BaseType_t MPU_xTimerIsTimerActive( TimerHandle_t xTimer );
|
||||
TaskHandle_t MPU_xTimerGetTimerDaemonTaskHandle( void );
|
||||
BaseType_t MPU_xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvParameter1, uint32_t ulParameter2, TickType_t xTicksToWait );
|
||||
const char * MPU_pcTimerGetName( TimerHandle_t xTimer );
|
||||
TickType_t MPU_xTimerGetPeriod( TimerHandle_t xTimer );
|
||||
TickType_t MPU_xTimerGetExpiryTime( TimerHandle_t xTimer );
|
||||
BaseType_t MPU_xTimerCreateTimerTask( void );
|
||||
BaseType_t MPU_xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait );
|
||||
|
||||
/* MPU versions of event_group.h API function. */
|
||||
EventGroupHandle_t MPU_xEventGroupCreate( void );
|
||||
EventGroupHandle_t MPU_xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer );
|
||||
EventBits_t MPU_xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait );
|
||||
EventBits_t MPU_xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );
|
||||
EventBits_t MPU_xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );
|
||||
EventBits_t MPU_xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait );
|
||||
void MPU_vEventGroupDelete( EventGroupHandle_t xEventGroup );
|
||||
UBaseType_t MPU_uxEventGroupGetNumber( void* xEventGroup );
|
||||
|
||||
#endif /* MPU_PROTOTYPES_H */
|
||||
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef MPU_WRAPPERS_H
|
||||
#define MPU_WRAPPERS_H
|
||||
|
||||
/* This file redefines API functions to be called through a wrapper macro, but
|
||||
only for ports that are using the MPU. */
|
||||
#ifdef portUSING_MPU_WRAPPERS
|
||||
|
||||
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is
|
||||
included from queue.c or task.c to prevent it from having an effect within
|
||||
those files. */
|
||||
#ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/*
|
||||
* Map standard (non MPU) API functions to equivalents that start
|
||||
* "MPU_". This will cause the application code to call the MPU_
|
||||
* version, which wraps the non-MPU version with privilege promoting
|
||||
* then demoting code, so the kernel code always runs will full
|
||||
* privileges.
|
||||
*/
|
||||
|
||||
/* Map standard tasks.h API functions to the MPU equivalents. */
|
||||
#define xTaskCreate MPU_xTaskCreate
|
||||
#define xTaskCreateStatic MPU_xTaskCreateStatic
|
||||
#define xTaskCreateRestricted MPU_xTaskCreateRestricted
|
||||
#define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions
|
||||
#define vTaskDelete MPU_vTaskDelete
|
||||
#define vTaskDelay MPU_vTaskDelay
|
||||
#define vTaskDelayUntil MPU_vTaskDelayUntil
|
||||
#define xTaskAbortDelay MPU_xTaskAbortDelay
|
||||
#define uxTaskPriorityGet MPU_uxTaskPriorityGet
|
||||
#define eTaskGetState MPU_eTaskGetState
|
||||
#define vTaskGetInfo MPU_vTaskGetInfo
|
||||
#define vTaskPrioritySet MPU_vTaskPrioritySet
|
||||
#define vTaskSuspend MPU_vTaskSuspend
|
||||
#define vTaskResume MPU_vTaskResume
|
||||
#define vTaskSuspendAll MPU_vTaskSuspendAll
|
||||
#define xTaskResumeAll MPU_xTaskResumeAll
|
||||
#define xTaskGetTickCount MPU_xTaskGetTickCount
|
||||
#define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks
|
||||
#define pcTaskGetName MPU_pcTaskGetName
|
||||
#define xTaskGetHandle MPU_xTaskGetHandle
|
||||
#define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark
|
||||
#define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag
|
||||
#define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag
|
||||
#define vTaskSetThreadLocalStoragePointer MPU_vTaskSetThreadLocalStoragePointer
|
||||
#define pvTaskGetThreadLocalStoragePointer MPU_pvTaskGetThreadLocalStoragePointer
|
||||
#define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook
|
||||
#define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle
|
||||
#define uxTaskGetSystemState MPU_uxTaskGetSystemState
|
||||
#define vTaskList MPU_vTaskList
|
||||
#define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats
|
||||
#define xTaskGenericNotify MPU_xTaskGenericNotify
|
||||
#define xTaskNotifyWait MPU_xTaskNotifyWait
|
||||
#define ulTaskNotifyTake MPU_ulTaskNotifyTake
|
||||
#define xTaskNotifyStateClear MPU_xTaskNotifyStateClear
|
||||
|
||||
#define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle
|
||||
#define vTaskSetTimeOutState MPU_vTaskSetTimeOutState
|
||||
#define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut
|
||||
#define xTaskGetSchedulerState MPU_xTaskGetSchedulerState
|
||||
|
||||
/* Map standard queue.h API functions to the MPU equivalents. */
|
||||
#define xQueueGenericSend MPU_xQueueGenericSend
|
||||
#define xQueueGenericReceive MPU_xQueueGenericReceive
|
||||
#define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting
|
||||
#define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable
|
||||
#define vQueueDelete MPU_vQueueDelete
|
||||
#define xQueueCreateMutex MPU_xQueueCreateMutex
|
||||
#define xQueueCreateMutexStatic MPU_xQueueCreateMutexStatic
|
||||
#define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore
|
||||
#define xQueueCreateCountingSemaphoreStatic MPU_xQueueCreateCountingSemaphoreStatic
|
||||
#define xQueueGetMutexHolder MPU_xQueueGetMutexHolder
|
||||
#define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive
|
||||
#define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive
|
||||
#define xQueueGenericCreate MPU_xQueueGenericCreate
|
||||
#define xQueueGenericCreateStatic MPU_xQueueGenericCreateStatic
|
||||
#define xQueueCreateSet MPU_xQueueCreateSet
|
||||
#define xQueueAddToSet MPU_xQueueAddToSet
|
||||
#define xQueueRemoveFromSet MPU_xQueueRemoveFromSet
|
||||
#define xQueueSelectFromSet MPU_xQueueSelectFromSet
|
||||
#define xQueueGenericReset MPU_xQueueGenericReset
|
||||
|
||||
#if( configQUEUE_REGISTRY_SIZE > 0 )
|
||||
#define vQueueAddToRegistry MPU_vQueueAddToRegistry
|
||||
#define vQueueUnregisterQueue MPU_vQueueUnregisterQueue
|
||||
#define pcQueueGetName MPU_pcQueueGetName
|
||||
#endif
|
||||
|
||||
/* Map standard timer.h API functions to the MPU equivalents. */
|
||||
#define xTimerCreate MPU_xTimerCreate
|
||||
#define xTimerCreateStatic MPU_xTimerCreateStatic
|
||||
#define pvTimerGetTimerID MPU_pvTimerGetTimerID
|
||||
#define vTimerSetTimerID MPU_vTimerSetTimerID
|
||||
#define xTimerIsTimerActive MPU_xTimerIsTimerActive
|
||||
#define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle
|
||||
#define xTimerPendFunctionCall MPU_xTimerPendFunctionCall
|
||||
#define pcTimerGetName MPU_pcTimerGetName
|
||||
#define xTimerGetPeriod MPU_xTimerGetPeriod
|
||||
#define xTimerGetExpiryTime MPU_xTimerGetExpiryTime
|
||||
#define xTimerGenericCommand MPU_xTimerGenericCommand
|
||||
|
||||
/* Map standard event_group.h API functions to the MPU equivalents. */
|
||||
#define xEventGroupCreate MPU_xEventGroupCreate
|
||||
#define xEventGroupCreateStatic MPU_xEventGroupCreateStatic
|
||||
#define xEventGroupWaitBits MPU_xEventGroupWaitBits
|
||||
#define xEventGroupClearBits MPU_xEventGroupClearBits
|
||||
#define xEventGroupSetBits MPU_xEventGroupSetBits
|
||||
#define xEventGroupSync MPU_xEventGroupSync
|
||||
#define vEventGroupDelete MPU_vEventGroupDelete
|
||||
|
||||
/* Remove the privileged function macro. */
|
||||
#define PRIVILEGED_FUNCTION
|
||||
|
||||
#else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
|
||||
|
||||
/* Ensure API functions go in the privileged execution section. */
|
||||
#define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions")))
|
||||
#define PRIVILEGED_DATA __attribute__((section("privileged_data")))
|
||||
|
||||
#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
|
||||
|
||||
#else /* portUSING_MPU_WRAPPERS */
|
||||
|
||||
#define PRIVILEGED_FUNCTION
|
||||
#define PRIVILEGED_DATA
|
||||
#define portUSING_MPU_WRAPPERS 0
|
||||
|
||||
#endif /* portUSING_MPU_WRAPPERS */
|
||||
|
||||
|
||||
#endif /* MPU_WRAPPERS_H */
|
||||
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Portable layer API. Each function must be defined for each port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
#ifndef PORTABLE_H
|
||||
#define PORTABLE_H
|
||||
|
||||
/* Each FreeRTOS port has a unique portmacro.h header file. Originally a
|
||||
pre-processor definition was used to ensure the pre-processor found the correct
|
||||
portmacro.h file for the port being used. That scheme was deprecated in favour
|
||||
of setting the compiler's include path such that it found the correct
|
||||
portmacro.h file - removing the need for the constant and allowing the
|
||||
portmacro.h file to be located anywhere in relation to the port being used.
|
||||
Purely for reasons of backward compatibility the old method is still valid, but
|
||||
to make it clear that new projects should not use it, support for the port
|
||||
specific constants has been moved into the deprecated_definitions.h header
|
||||
file. */
|
||||
#include "deprecated_definitions.h"
|
||||
|
||||
/* If portENTER_CRITICAL is not defined then including deprecated_definitions.h
|
||||
did not result in a portmacro.h header file being included - and it should be
|
||||
included here. In this case the path to the correct portmacro.h header file
|
||||
must be set in the compiler's include path. */
|
||||
#ifndef portENTER_CRITICAL
|
||||
#include "portmacro.h"
|
||||
#endif
|
||||
|
||||
#if portBYTE_ALIGNMENT == 32
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x001f )
|
||||
#endif
|
||||
|
||||
#if portBYTE_ALIGNMENT == 16
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x000f )
|
||||
#endif
|
||||
|
||||
#if portBYTE_ALIGNMENT == 8
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x0007 )
|
||||
#endif
|
||||
|
||||
#if portBYTE_ALIGNMENT == 4
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x0003 )
|
||||
#endif
|
||||
|
||||
#if portBYTE_ALIGNMENT == 2
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x0001 )
|
||||
#endif
|
||||
|
||||
#if portBYTE_ALIGNMENT == 1
|
||||
#define portBYTE_ALIGNMENT_MASK ( 0x0000 )
|
||||
#endif
|
||||
|
||||
#ifndef portBYTE_ALIGNMENT_MASK
|
||||
#error "Invalid portBYTE_ALIGNMENT definition"
|
||||
#endif
|
||||
|
||||
#ifndef portNUM_CONFIGURABLE_REGIONS
|
||||
#define portNUM_CONFIGURABLE_REGIONS 1
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/*
|
||||
* Setup the stack of a new task so it is ready to be placed under the
|
||||
* scheduler control. The registers have to be placed on the stack in
|
||||
* the order that the port expects to find them.
|
||||
*
|
||||
*/
|
||||
#if( portUSING_MPU_WRAPPERS == 1 )
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) PRIVILEGED_FUNCTION;
|
||||
#else
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
/* Used by heap_5.c. */
|
||||
typedef struct HeapRegion
|
||||
{
|
||||
uint8_t *pucStartAddress;
|
||||
size_t xSizeInBytes;
|
||||
} HeapRegion_t;
|
||||
|
||||
/*
|
||||
* Used to define multiple heap regions for use by heap_5.c. This function
|
||||
* must be called before any calls to pvPortMalloc() - not creating a task,
|
||||
* queue, semaphore, mutex, software timer, event group, etc. will result in
|
||||
* pvPortMalloc being called.
|
||||
*
|
||||
* pxHeapRegions passes in an array of HeapRegion_t structures - each of which
|
||||
* defines a region of memory that can be used as the heap. The array is
|
||||
* terminated by a HeapRegions_t structure that has a size of 0. The region
|
||||
* with the lowest start address must appear first in the array.
|
||||
*/
|
||||
//static void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION;
|
||||
|
||||
|
||||
/*
|
||||
* Map to the memory management routines required for the port.
|
||||
*/
|
||||
void *pvPortMalloc( size_t xSize ) PRIVILEGED_FUNCTION;
|
||||
void vPortFree( void *pv ) PRIVILEGED_FUNCTION;
|
||||
void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION;
|
||||
size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION;
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Setup the hardware ready for the scheduler to take control. This generally
|
||||
* sets up a tick interrupt and sets timers for the correct tick frequency.
|
||||
*/
|
||||
BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Undo any hardware/ISR setup that was performed by xPortStartScheduler() so
|
||||
* the hardware is left in its original condition after the scheduler stops
|
||||
* executing.
|
||||
*/
|
||||
void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* The structures and methods of manipulating the MPU are contained within the
|
||||
* port layer.
|
||||
*
|
||||
* Fills the xMPUSettings structure with the memory region information
|
||||
* contained in xRegions.
|
||||
*/
|
||||
#if( portUSING_MPU_WRAPPERS == 1 )
|
||||
struct xMEMORY_REGION;
|
||||
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth ) PRIVILEGED_FUNCTION;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTABLE_H */
|
||||
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef PROJDEFS_H
|
||||
#define PROJDEFS_H
|
||||
|
||||
/*
|
||||
* Defines the prototype to which task functions must conform. Defined in this
|
||||
* file to ensure the type is known before portable.h is included.
|
||||
*/
|
||||
typedef void (*TaskFunction_t)( void * );
|
||||
|
||||
/* Converts a time in milliseconds to a time in ticks. This macro can be
|
||||
overridden by a macro of the same name defined in FreeRTOSConfig.h in case the
|
||||
definition here is not suitable for your application. */
|
||||
#ifndef pdMS_TO_TICKS
|
||||
#define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) )
|
||||
#endif
|
||||
|
||||
#define pdFALSE ( ( BaseType_t ) 0 )
|
||||
#define pdTRUE ( ( BaseType_t ) 1 )
|
||||
|
||||
#define pdPASS ( pdTRUE )
|
||||
#define pdFAIL ( pdFALSE )
|
||||
#define errQUEUE_EMPTY ( ( BaseType_t ) 0 )
|
||||
#define errQUEUE_FULL ( ( BaseType_t ) 0 )
|
||||
|
||||
/* FreeRTOS error definitions. */
|
||||
#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 )
|
||||
#define errQUEUE_BLOCKED ( -4 )
|
||||
#define errQUEUE_YIELD ( -5 )
|
||||
|
||||
/* Macros used for basic data corruption checks. */
|
||||
#ifndef configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES
|
||||
#define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0
|
||||
#endif
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
#define pdINTEGRITY_CHECK_VALUE 0x5a5a
|
||||
#else
|
||||
#define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL
|
||||
#endif
|
||||
|
||||
/* The following errno values are used by FreeRTOS+ components, not FreeRTOS
|
||||
itself. */
|
||||
#define pdFREERTOS_ERRNO_NONE 0 /* No errors */
|
||||
#define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */
|
||||
#define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */
|
||||
#define pdFREERTOS_ERRNO_EIO 5 /* I/O error */
|
||||
#define pdFREERTOS_ERRNO_ENXIO 6 /* No such device or address */
|
||||
#define pdFREERTOS_ERRNO_EBADF 9 /* Bad file number */
|
||||
#define pdFREERTOS_ERRNO_EAGAIN 11 /* No more processes */
|
||||
#define pdFREERTOS_ERRNO_EWOULDBLOCK 11 /* Operation would block */
|
||||
#define pdFREERTOS_ERRNO_ENOMEM 12 /* Not enough memory */
|
||||
#define pdFREERTOS_ERRNO_EACCES 13 /* Permission denied */
|
||||
#define pdFREERTOS_ERRNO_EFAULT 14 /* Bad address */
|
||||
#define pdFREERTOS_ERRNO_EBUSY 16 /* Mount device busy */
|
||||
#define pdFREERTOS_ERRNO_EEXIST 17 /* File exists */
|
||||
#define pdFREERTOS_ERRNO_EXDEV 18 /* Cross-device link */
|
||||
#define pdFREERTOS_ERRNO_ENODEV 19 /* No such device */
|
||||
#define pdFREERTOS_ERRNO_ENOTDIR 20 /* Not a directory */
|
||||
#define pdFREERTOS_ERRNO_EISDIR 21 /* Is a directory */
|
||||
#define pdFREERTOS_ERRNO_EINVAL 22 /* Invalid argument */
|
||||
#define pdFREERTOS_ERRNO_ENOSPC 28 /* No space left on device */
|
||||
#define pdFREERTOS_ERRNO_ESPIPE 29 /* Illegal seek */
|
||||
#define pdFREERTOS_ERRNO_EROFS 30 /* Read only file system */
|
||||
#define pdFREERTOS_ERRNO_EUNATCH 42 /* Protocol driver not attached */
|
||||
#define pdFREERTOS_ERRNO_EBADE 50 /* Invalid exchange */
|
||||
#define pdFREERTOS_ERRNO_EFTYPE 79 /* Inappropriate file type or format */
|
||||
#define pdFREERTOS_ERRNO_ENMFILE 89 /* No more files */
|
||||
#define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */
|
||||
#define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */
|
||||
#define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||
#define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */
|
||||
#define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */
|
||||
#define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */
|
||||
#define pdFREERTOS_ERRNO_ETIMEDOUT 116 /* Connection timed out */
|
||||
#define pdFREERTOS_ERRNO_EINPROGRESS 119 /* Connection already in progress */
|
||||
#define pdFREERTOS_ERRNO_EALREADY 120 /* Socket already connected */
|
||||
#define pdFREERTOS_ERRNO_EADDRNOTAVAIL 125 /* Address not available */
|
||||
#define pdFREERTOS_ERRNO_EISCONN 127 /* Socket is already connected */
|
||||
#define pdFREERTOS_ERRNO_ENOTCONN 128 /* Socket is not connected */
|
||||
#define pdFREERTOS_ERRNO_ENOMEDIUM 135 /* No medium inserted */
|
||||
#define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */
|
||||
#define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */
|
||||
|
||||
/* The following endian values are used by FreeRTOS+ components, not FreeRTOS
|
||||
itself. */
|
||||
#define pdFREERTOS_LITTLE_ENDIAN 0
|
||||
#define pdFREERTOS_BIG_ENDIAN 1
|
||||
|
||||
#endif /* PROJDEFS_H */
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
#ifndef FREERTOS_STDINT
|
||||
#define FREERTOS_STDINT
|
||||
|
||||
/*******************************************************************************
|
||||
* THIS IS NOT A FULL stdint.h IMPLEMENTATION - It only contains the definitions
|
||||
* necessary to build the FreeRTOS code. It is provided to allow FreeRTOS to be
|
||||
* built using compilers that do not provide their own stdint.h definition.
|
||||
*
|
||||
* To use this file:
|
||||
*
|
||||
* 1) Copy this file into the directory that contains your FreeRTOSConfig.h
|
||||
* header file, as that directory will already be in the compilers include
|
||||
* path.
|
||||
*
|
||||
* 2) Rename the copied file stdint.h.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef long int32_t;
|
||||
typedef unsigned long uint32_t;
|
||||
|
||||
#endif /* FREERTOS_STDINT */
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "list.h"
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* PUBLIC LIST API documented in list.h
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
void vListInitialise( List_t * const pxList )
|
||||
{
|
||||
/* The list structure contains a list item which is used to mark the
|
||||
end of the list. To initialise the list the list end is inserted
|
||||
as the only list entry. */
|
||||
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
|
||||
|
||||
/* The list end value is the highest possible value in the list to
|
||||
ensure it remains at the end of the list. */
|
||||
pxList->xListEnd.xItemValue = portMAX_DELAY;
|
||||
|
||||
/* The list end next and previous pointers point to itself so we know
|
||||
when the list is empty. */
|
||||
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
|
||||
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
|
||||
|
||||
pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
|
||||
|
||||
/* Write known values into the list if
|
||||
configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
|
||||
listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vListInitialiseItem( ListItem_t * const pxItem )
|
||||
{
|
||||
/* Make sure the list item is not recorded as being on a list. */
|
||||
pxItem->pvContainer = NULL;
|
||||
|
||||
/* Write known values into the list item if
|
||||
configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
|
||||
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )
|
||||
{
|
||||
ListItem_t * const pxIndex = pxList->pxIndex;
|
||||
|
||||
/* Only effective when configASSERT() is also defined, these tests may catch
|
||||
the list data structures being overwritten in memory. They will not catch
|
||||
data errors caused by incorrect configuration or use of FreeRTOS. */
|
||||
listTEST_LIST_INTEGRITY( pxList );
|
||||
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
|
||||
|
||||
/* Insert a new list item into pxList, but rather than sort the list,
|
||||
makes the new list item the last item to be removed by a call to
|
||||
listGET_OWNER_OF_NEXT_ENTRY(). */
|
||||
pxNewListItem->pxNext = pxIndex;
|
||||
pxNewListItem->pxPrevious = pxIndex->pxPrevious;
|
||||
|
||||
/* Only used during decision coverage testing. */
|
||||
mtCOVERAGE_TEST_DELAY();
|
||||
|
||||
pxIndex->pxPrevious->pxNext = pxNewListItem;
|
||||
pxIndex->pxPrevious = pxNewListItem;
|
||||
|
||||
/* Remember which list the item is in. */
|
||||
pxNewListItem->pvContainer = ( void * ) pxList;
|
||||
|
||||
( pxList->uxNumberOfItems )++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
|
||||
{
|
||||
ListItem_t *pxIterator;
|
||||
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
|
||||
|
||||
/* Only effective when configASSERT() is also defined, these tests may catch
|
||||
the list data structures being overwritten in memory. They will not catch
|
||||
data errors caused by incorrect configuration or use of FreeRTOS. */
|
||||
listTEST_LIST_INTEGRITY( pxList );
|
||||
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
|
||||
|
||||
/* Insert the new list item into the list, sorted in xItemValue order.
|
||||
|
||||
If the list already contains a list item with the same item value then the
|
||||
new list item should be placed after it. This ensures that TCB's which are
|
||||
stored in ready lists (all of which have the same xItemValue value) get a
|
||||
share of the CPU. However, if the xItemValue is the same as the back marker
|
||||
the iteration loop below will not end. Therefore the value is checked
|
||||
first, and the algorithm slightly modified if necessary. */
|
||||
if( xValueOfInsertion == portMAX_DELAY )
|
||||
{
|
||||
pxIterator = pxList->xListEnd.pxPrevious;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* *** NOTE ***********************************************************
|
||||
If you find your application is crashing here then likely causes are
|
||||
listed below. In addition see http://www.freertos.org/FAQHelp.html for
|
||||
more tips, and ensure configASSERT() is defined!
|
||||
http://www.freertos.org/a00110.html#configASSERT
|
||||
|
||||
1) Stack overflow -
|
||||
see http://www.freertos.org/Stacks-and-stack-overflow-checking.html
|
||||
2) Incorrect interrupt priority assignment, especially on Cortex-M
|
||||
parts where numerically high priority values denote low actual
|
||||
interrupt priorities, which can seem counter intuitive. See
|
||||
http://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition
|
||||
of configMAX_SYSCALL_INTERRUPT_PRIORITY on
|
||||
http://www.freertos.org/a00110.html
|
||||
3) Calling an API function from within a critical section or when
|
||||
the scheduler is suspended, or calling an API function that does
|
||||
not end in "FromISR" from an interrupt.
|
||||
4) Using a queue or semaphore before it has been initialised or
|
||||
before the scheduler has been started (are interrupts firing
|
||||
before vTaskStartScheduler() has been called?).
|
||||
**********************************************************************/
|
||||
|
||||
for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 The mini list structure is used as the list end to save RAM. This is checked and valid. */
|
||||
{
|
||||
/* There is nothing to do here, just iterating to the wanted
|
||||
insertion position. */
|
||||
}
|
||||
}
|
||||
|
||||
pxNewListItem->pxNext = pxIterator->pxNext;
|
||||
pxNewListItem->pxNext->pxPrevious = pxNewListItem;
|
||||
pxNewListItem->pxPrevious = pxIterator;
|
||||
pxIterator->pxNext = pxNewListItem;
|
||||
|
||||
/* Remember which list the item is in. This allows fast removal of the
|
||||
item later. */
|
||||
pxNewListItem->pvContainer = ( void * ) pxList;
|
||||
|
||||
( pxList->uxNumberOfItems )++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
|
||||
{
|
||||
/* The list item knows which list it is in. Obtain the list from the list
|
||||
item. */
|
||||
List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;
|
||||
|
||||
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
|
||||
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
|
||||
|
||||
/* Only used during decision coverage testing. */
|
||||
mtCOVERAGE_TEST_DELAY();
|
||||
|
||||
/* Make sure the index is left pointing to a valid item. */
|
||||
if( pxList->pxIndex == pxItemToRemove )
|
||||
{
|
||||
pxList->pxIndex = pxItemToRemove->pxPrevious;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
pxItemToRemove->pvContainer = NULL;
|
||||
( pxList->uxNumberOfItems )--;
|
||||
|
||||
return pxList->uxNumberOfItems;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,716 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM CM3 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is
|
||||
defined. The value should also ensure backward compatibility.
|
||||
FreeRTOS.org versions prior to V4.4.0 did not include this definition. */
|
||||
#ifndef configKERNEL_INTERRUPT_PRIORITY
|
||||
#define configKERNEL_INTERRUPT_PRIORITY 255
|
||||
#endif
|
||||
|
||||
#ifndef configSYSTICK_CLOCK_HZ
|
||||
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||
#else
|
||||
/* The way the SysTick is clocked is not modified in case it is not the same
|
||||
as the core. */
|
||||
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||
#endif
|
||||
|
||||
/* Constants required to manipulate the core. Registers first... */
|
||||
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||
/* ...then bits in the registers. */
|
||||
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
|
||||
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
|
||||
|
||||
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||
|
||||
/* Constants required to check the validity of an interrupt priority. */
|
||||
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||
#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
|
||||
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
|
||||
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
|
||||
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||
#define portPRIGROUP_SHIFT ( 8UL )
|
||||
|
||||
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
|
||||
#define portVECTACTIVE_MASK ( 0xFFUL )
|
||||
|
||||
/* Constants required to set up the initial stack. */
|
||||
#define portINITIAL_XPSR ( 0x01000000UL )
|
||||
|
||||
/* 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. */
|
||||
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||
|
||||
/* 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. */
|
||||
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
||||
|
||||
/* 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
|
||||
debugger. */
|
||||
#ifdef configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#else
|
||||
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#endif
|
||||
|
||||
/* Each task maintains its own interrupt status in the critical nesting
|
||||
variable. */
|
||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* Exception handlers.
|
||||
*/
|
||||
void xPortPendSVHandler( void ) __attribute__ (( naked ));
|
||||
void xPortSysTickHandler( void );
|
||||
void vPortSVCHandler( void ) __attribute__ (( naked ));
|
||||
|
||||
/*
|
||||
* Start first task is a separate function so it can be tested in isolation.
|
||||
*/
|
||||
static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
|
||||
|
||||
/*
|
||||
* Used to catch tasks that attempt to return from their implementing function.
|
||||
*/
|
||||
static void prvTaskExitError( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
/*
|
||||
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
*/
|
||||
#if ( configASSERT_DEFINED == 1 )
|
||||
static uint8_t ucMaxSysCallPriority = 0;
|
||||
static uint32_t ulMaxPRIGROUPValue = 0;
|
||||
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
interrupt. */
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvTaskExitError( void )
|
||||
{
|
||||
/* A function that implements a task must not exit or attempt to return to
|
||||
its caller as there is nothing to return to. If a task wants to exit it
|
||||
should instead call vTaskDelete( NULL ).
|
||||
|
||||
Artificially force an assert() to be triggered if configASSERT() is
|
||||
defined, then stop here so application writers can catch the error. */
|
||||
configASSERT( uxCriticalNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
for( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortSVCHandler( void )
|
||||
{
|
||||
__asm volatile (
|
||||
" ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */
|
||||
" ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
|
||||
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
|
||||
" ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
|
||||
" msr psp, r0 \n" /* Restore the task stack pointer. */
|
||||
" isb \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"
|
||||
" orr r14, #0xd \n"
|
||||
" bx r14 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvPortStartFirstTask( void )
|
||||
{
|
||||
__asm volatile(
|
||||
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"
|
||||
" ldr r0, [r0] \n"
|
||||
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
|
||||
" cpsie i \n" /* Globally enable interrupts. */
|
||||
" cpsie f \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc 0 \n" /* System call to start first task. */
|
||||
" nop \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
|
||||
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
||||
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
volatile uint32_t ulOriginalPriority;
|
||||
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||
volatile uint8_t ucMaxPriorityValue;
|
||||
|
||||
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||
functions can be called. ISR safe functions are those that end in
|
||||
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||
ensure interrupt entry is as fast and simple as possible.
|
||||
|
||||
Save the interrupt priority value that is about to be clobbered. */
|
||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Determine the number of priority bits available. First write to all
|
||||
possible bits. */
|
||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||
|
||||
/* Read the value back to see how many bits stuck. */
|
||||
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Use the same mask on the maximum system call priority. */
|
||||
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||
|
||||
/* Calculate the maximum acceptable priority group value for the number
|
||||
of bits read back. */
|
||||
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
||||
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||
{
|
||||
ulMaxPRIGROUPValue--;
|
||||
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
|
||||
}
|
||||
|
||||
/* Shift the priority group value back to its position within the AIRCR
|
||||
register. */
|
||||
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||
|
||||
/* Restore the clobbered interrupt priority register to its original
|
||||
value. */
|
||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||
}
|
||||
#endif /* conifgASSERT_DEFINED */
|
||||
|
||||
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
vPortSetupTimerInterrupt();
|
||||
|
||||
/* Initialise the critical nesting count ready for the first task. */
|
||||
uxCriticalNesting = 0;
|
||||
|
||||
/* Start the first task. */
|
||||
prvPortStartFirstTask();
|
||||
|
||||
/* Should never get here as the tasks will now be executing! Call the task
|
||||
exit error function to prevent compiler warnings about a static function
|
||||
not being called in the case that the application writer overrides this
|
||||
functionality by defining configTASK_RETURN_ADDRESS. */
|
||||
prvTaskExitError();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( uxCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
uxCriticalNesting++;
|
||||
|
||||
/* 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
|
||||
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
|
||||
assert function also uses a critical section. */
|
||||
if( uxCriticalNesting == 1 )
|
||||
{
|
||||
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
configASSERT( uxCriticalNesting );
|
||||
uxCriticalNesting--;
|
||||
if( uxCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void xPortPendSVHandler( void )
|
||||
{
|
||||
/* This is a naked function. */
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, psp \n"
|
||||
" isb \n"
|
||||
" \n"
|
||||
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
|
||||
" ldr r2, [r3] \n"
|
||||
" \n"
|
||||
" stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */
|
||||
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
|
||||
" \n"
|
||||
" stmdb sp!, {r3, r14} \n"
|
||||
" mov r0, %0 \n"
|
||||
" msr basepri, r0 \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"
|
||||
" ldmia sp!, {r3, r14} \n"
|
||||
" \n" /* Restore the context, including the critical nesting count. */
|
||||
" ldr r1, [r3] \n"
|
||||
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
|
||||
" ldmia r0!, {r4-r11} \n" /* Pop the registers. */
|
||||
" msr psp, r0 \n"
|
||||
" isb \n"
|
||||
" bx r14 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void xPortSysTickHandler( void )
|
||||
{
|
||||
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
|
||||
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
|
||||
known. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* A context switch is required. Context switching is performed in
|
||||
the PendSV interrupt. Pend the PendSV interrupt. */
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||
}
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if configUSE_TICKLESS_IDLE == 1
|
||||
|
||||
__attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||
{
|
||||
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
|
||||
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" );
|
||||
__asm volatile( "dsb" ); //-rt812
|
||||
__asm volatile( "isb" ); //-rt812
|
||||
|
||||
/* 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" );
|
||||
}
|
||||
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" );
|
||||
__asm volatile( "wfi" );
|
||||
__asm volatile( "isb" );
|
||||
}
|
||||
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||
|
||||
/* Stop SysTick. 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. */
|
||||
ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
|
||||
portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
|
||||
|
||||
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||
above. */
|
||||
__asm volatile( "cpsie i" );
|
||||
|
||||
if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||
{
|
||||
uint32_t ulCalculatedLoadValue;
|
||||
|
||||
/* The tick interrupt has already executed, 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;
|
||||
|
||||
/* The tick interrupt handler will already have pended the tick
|
||||
processing in the kernel. 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. The critical section is used to ensure the tick interrupt
|
||||
can only execute once in the case that the reload register is near
|
||||
zero. */
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
vTaskStepTick( ulCompleteTickPeriods );
|
||||
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #if configUSE_TICKLESS_IDLE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the systick timer to generate the tick interrupts at the required
|
||||
* frequency.
|
||||
*/
|
||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Calculate the constants required to configure the tick interrupt. */
|
||||
#if configUSE_TICKLESS_IDLE == 1
|
||||
{
|
||||
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||
}
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
uint8_t ucCurrentPriority;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
|
||||
|
||||
/* Is the interrupt number a user defined interrupt? */
|
||||
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||
{
|
||||
/* Look up the interrupt's priority. */
|
||||
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
an interrupt that has been assigned a priority above
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
function. ISR safe FreeRTOS API functions must *only* be called
|
||||
from interrupts that have been assigned a priority at or below
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
|
||||
Numerically low interrupt priority numbers represent logically high
|
||||
interrupt priorities, therefore the priority of the interrupt must
|
||||
be set to a value equal to or numerically *higher* than
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
|
||||
Interrupts that use the FreeRTOS API must not be left at their
|
||||
default priority of zero as that is the highest possible priority,
|
||||
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||
and therefore also guaranteed to be invalid.
|
||||
|
||||
FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||
interrupt entry is as fast and simple as possible.
|
||||
|
||||
The following links provide detailed information:
|
||||
http://www.freertos.org/RTOS-Cortex-M3-M4.html
|
||||
http://www.freertos.org/FAQHelp.html */
|
||||
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||
}
|
||||
|
||||
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
||||
that define each interrupt's priority to be split between bits that
|
||||
define the interrupt's pre-emption priority bits and bits that define
|
||||
the interrupt's sub-priority. For simplicity all bits must be defined
|
||||
to be pre-emption priority bits. The following assertion will fail if
|
||||
this is not the case (if some bits represent a sub-priority).
|
||||
|
||||
If the application only uses CMSIS libraries for interrupt
|
||||
configuration then the correct setting can be achieved on all Cortex-M
|
||||
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||
scheduler. Note however that some vendor specific peripheral libraries
|
||||
assume a non-zero priority group setting, in which cases using a value
|
||||
of zero will result in unpredicable behaviour. */
|
||||
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||
}
|
||||
|
||||
#endif /* configASSERT_DEFINED */
|
||||
/*-----------------------------------------------------------*/
|
||||
#if configUSE_IDLE_HOOK
|
||||
extern void WDGRefresh(void);
|
||||
void vApplicationIdleHook( void )
|
||||
{
|
||||
/* Use the idle task to place the CPU into a low power mode. Greater power
|
||||
saving could be achieved by not including any demo tasks that never block. */
|
||||
#ifdef CONFIG_WDG_ON_IDLE
|
||||
WDGRefresh();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if configCHECK_FOR_STACK_OVERFLOW
|
||||
#include "diag.h"
|
||||
void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName )
|
||||
{
|
||||
/* This function will be called if a task overflows its stack, if
|
||||
configCHECK_FOR_STACK_OVERFLOW != 0. It might be that the function
|
||||
parameters have been corrupted, depending on the severity of the stack
|
||||
overflow. When this is the case pxCurrentTCB can be inspected in the
|
||||
debugger to find the offending task. */
|
||||
DiagPrintf("\nSTACK OVERFLOW - TaskName(%s)\n", pcTaskName);
|
||||
for( ;; );
|
||||
}
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#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;
|
||||
|
||||
#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
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler utilities. */
|
||||
#define portYIELD() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
\
|
||||
/* Barriers are normally not required but do ensure the code is completely \
|
||||
within the specified behaviour for the architecture. */ \
|
||||
__asm volatile( "dsb" ); \
|
||||
__asm volatile( "isb" ); \
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER // IntelliSense, ñóïåð êðèâîé âàðèàíò, ÷òî áû óáðàòü îøèáêó...
|
||||
#undef portYIELD()
|
||||
#define portYIELD()
|
||||
#endif
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
|
||||
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
|
||||
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
not necessary for to use this port. They are defined so the common demo files
|
||||
(which build with all the ports) will build. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Generic helper function. */
|
||||
#ifndef _MSC_VER // IntelliSense
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
#else
|
||||
static inline uint8_t ucPortCountLeadingZeros(uint32_t ulBitmap)
|
||||
#endif
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) );
|
||||
return ucReturn;
|
||||
}
|
||||
|
||||
/* Check the configuration. */
|
||||
#if( configMAX_PRIORITIES > 32 )
|
||||
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||
#endif
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
|
||||
/* portNOP() is not required by this port. */
|
||||
#define portNOP()
|
||||
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifndef portFORCE_INLINE
|
||||
#ifndef _MSC_VER // IntelliSense
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||
#else
|
||||
#define portFORCE_INLINE
|
||||
#endif
|
||||
#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 ) );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mov %0, %1 \n" \
|
||||
" msr basepri, %0 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mrs %0, basepri \n" \
|
||||
" mov %1, %2 \n" \
|
||||
" msr basepri, %1 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
|
||||
/* This return will not be reached but is necessary to prevent compiler
|
||||
warnings. */
|
||||
return ulOriginalBASEPRI;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, %0 " :: "r" ( ulNewMaskValue )
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
@ -0,0 +1,771 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM CM3 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "queue.h"
|
||||
#include "timers.h"
|
||||
#include "event_groups.h"
|
||||
#include "mpu_prototypes.h"
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Constants required to access and manipulate the NVIC. */
|
||||
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||
#define portNVIC_SYSPRI1_REG ( * ( ( volatile uint32_t * ) 0xe000ed1c ) )
|
||||
#define portNVIC_SYS_CTRL_STATE_REG ( * ( ( volatile uint32_t * ) 0xe000ed24 ) )
|
||||
#define portNVIC_MEM_FAULT_ENABLE ( 1UL << 16UL )
|
||||
|
||||
/* Constants required to access and manipulate the MPU. */
|
||||
#define portMPU_TYPE_REG ( * ( ( volatile uint32_t * ) 0xe000ed90 ) )
|
||||
#define portMPU_REGION_BASE_ADDRESS_REG ( * ( ( volatile uint32_t * ) 0xe000ed9C ) )
|
||||
#define portMPU_REGION_ATTRIBUTE_REG ( * ( ( volatile uint32_t * ) 0xe000edA0 ) )
|
||||
#define portMPU_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed94 ) )
|
||||
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
||||
#define portMPU_ENABLE ( 0x01UL )
|
||||
#define portMPU_BACKGROUND_ENABLE ( 1UL << 2UL )
|
||||
#define portPRIVILEGED_EXECUTION_START_ADDRESS ( 0UL )
|
||||
#define portMPU_REGION_VALID ( 0x10UL )
|
||||
#define portMPU_REGION_ENABLE ( 0x01UL )
|
||||
#define portPERIPHERALS_START_ADDRESS 0x40000000UL
|
||||
#define portPERIPHERALS_END_ADDRESS 0x5FFFFFFFUL
|
||||
|
||||
/* Constants required to access and manipulate the SysTick. */
|
||||
#define portNVIC_SYSTICK_CLK ( 0x00000004UL )
|
||||
#define portNVIC_SYSTICK_INT ( 0x00000002UL )
|
||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001UL )
|
||||
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||
#define portNVIC_SVC_PRI ( ( ( uint32_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL ) << 24UL )
|
||||
|
||||
/* Constants required to set up the initial stack. */
|
||||
#define portINITIAL_XPSR ( 0x01000000 )
|
||||
#define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 )
|
||||
#define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 )
|
||||
|
||||
/* Constants required to check the validity of an interrupt priority. */
|
||||
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||
#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
|
||||
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
|
||||
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
|
||||
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||
#define portPRIGROUP_SHIFT ( 8UL )
|
||||
|
||||
/* Offsets in the stack to the parameters when inside the SVC handler. */
|
||||
#define portOFFSET_TO_PC ( 6 )
|
||||
|
||||
/* 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. */
|
||||
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
||||
|
||||
/* 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
|
||||
switches can only occur when uxCriticalNesting is zero. */
|
||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||
|
||||
/*
|
||||
* Setup the timer to generate the tick interrupts.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Configure a number of standard MPU regions that are used by all tasks.
|
||||
*/
|
||||
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Return the smallest MPU region size that a given number of bytes will fit
|
||||
* into. The region size is returned as the value that should be programmed
|
||||
* into the region attribute register for that region.
|
||||
*/
|
||||
static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Checks to see if being called from the context of an unprivileged task, and
|
||||
* if so raises the privilege level and returns false - otherwise does nothing
|
||||
* other than return true.
|
||||
*/
|
||||
BaseType_t xPortRaisePrivilege( void ) __attribute__(( naked ));
|
||||
|
||||
/*
|
||||
* Standard FreeRTOS exception handlers.
|
||||
*/
|
||||
void xPortPendSVHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void xPortSysTickHandler( void ) __attribute__ ((optimize("3"))) PRIVILEGED_FUNCTION;
|
||||
void vPortSVCHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Starts the scheduler by restoring the context of the first task to run.
|
||||
*/
|
||||
static void prvRestoreContextOfFirstTask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* C portion of the SVC handler. The SVC handler is split between an asm entry
|
||||
* and a C wrapper for simplicity of coding and maintenance.
|
||||
*/
|
||||
static void prvSVCHandler( uint32_t *pulRegisters ) __attribute__(( noinline )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
*/
|
||||
#if ( configASSERT_DEFINED == 1 )
|
||||
static uint8_t ucMaxSysCallPriority = 0;
|
||||
static uint32_t ulMaxPRIGROUPValue = 0;
|
||||
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
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
|
||||
interrupt. */
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0; /* LR */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
|
||||
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_IF_PRIVILEGED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_IF_UNPRIVILEGED;
|
||||
}
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortSVCHandler( void )
|
||||
{
|
||||
/* Assumes psp was in use. */
|
||||
__asm volatile
|
||||
(
|
||||
#ifndef USE_PROCESS_STACK /* Code should not be required if a main() is using the process stack. */
|
||||
" tst lr, #4 \n"
|
||||
" ite eq \n"
|
||||
" mrseq r0, msp \n"
|
||||
" mrsne r0, psp \n"
|
||||
#else
|
||||
" mrs r0, psp \n"
|
||||
#endif
|
||||
" b %0 \n"
|
||||
::"i"(prvSVCHandler):"r0"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSVCHandler( uint32_t *pulParam )
|
||||
{
|
||||
uint8_t ucSVCNumber;
|
||||
|
||||
/* 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 )
|
||||
{
|
||||
case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI;
|
||||
prvRestoreContextOfFirstTask();
|
||||
break;
|
||||
|
||||
case portSVC_YIELD : portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||
/* Barriers are normally not required
|
||||
but do ensure the code is completely
|
||||
within the specified behaviour for the
|
||||
architecture. */
|
||||
__asm volatile( "dsb" );
|
||||
__asm volatile( "isb" );
|
||||
|
||||
break;
|
||||
|
||||
case portSVC_RAISE_PRIVILEGE : __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"
|
||||
);
|
||||
break;
|
||||
|
||||
default : /* Unknown SVC call. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvRestoreContextOfFirstTask( void )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"
|
||||
" ldr r0, [r0] \n"
|
||||
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
|
||||
" ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */
|
||||
" ldr r1, [r3] \n"
|
||||
" 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... */
|
||||
" ldr r2, =0xe000ed9c \n" /* Region Base Address register. */
|
||||
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */
|
||||
" stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */
|
||||
" ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */
|
||||
" msr control, r3 \n"
|
||||
" msr psp, r0 \n" /* Restore the task stack pointer. */
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"
|
||||
" ldr r14, =0xfffffffd \n" /* Load exec return code. */
|
||||
" bx r14 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See
|
||||
http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
||||
configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) );
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
volatile uint32_t ulOriginalPriority;
|
||||
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||
volatile uint8_t ucMaxPriorityValue;
|
||||
|
||||
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||
functions can be called. ISR safe functions are those that end in
|
||||
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||
ensure interrupt entry is as fast and simple as possible.
|
||||
|
||||
Save the interrupt priority value that is about to be clobbered. */
|
||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Determine the number of priority bits available. First write to all
|
||||
possible bits. */
|
||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||
|
||||
/* Read the value back to see how many bits stuck. */
|
||||
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Use the same mask on the maximum system call priority. */
|
||||
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||
|
||||
/* Calculate the maximum acceptable priority group value for the number
|
||||
of bits read back. */
|
||||
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
||||
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||
{
|
||||
ulMaxPRIGROUPValue--;
|
||||
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
|
||||
}
|
||||
|
||||
/* Shift the priority group value back to its position within the AIRCR
|
||||
register. */
|
||||
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||
|
||||
/* Restore the clobbered interrupt priority register to its original
|
||||
value. */
|
||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||
}
|
||||
#endif /* conifgASSERT_DEFINED */
|
||||
|
||||
/* 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
|
||||
lower priorities are masked). */
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||
|
||||
/* Configure the regions in the MPU that are common to all tasks. */
|
||||
prvSetupMPU();
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Initialise the critical nesting count ready for the first task. */
|
||||
uxCriticalNesting = 0;
|
||||
|
||||
/* Start the first task. */
|
||||
__asm volatile(
|
||||
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"
|
||||
" ldr r0, [r0] \n"
|
||||
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
|
||||
" cpsie i \n" /* Globally enable interrupts. */
|
||||
" cpsie f \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n" /* System call to start first task. */
|
||||
" nop \n"
|
||||
:: "i" (portSVC_START_SCHEDULER) );
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( uxCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
|
||||
|
||||
portDISABLE_INTERRUPTS();
|
||||
uxCriticalNesting++;
|
||||
|
||||
vPortResetPrivilege( xRunningPrivileged );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
|
||||
|
||||
configASSERT( uxCriticalNesting );
|
||||
uxCriticalNesting--;
|
||||
if( uxCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
vPortResetPrivilege( xRunningPrivileged );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void xPortPendSVHandler( void )
|
||||
{
|
||||
/* This is a naked function. */
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, psp \n"
|
||||
" \n"
|
||||
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
|
||||
" ldr r2, [r3] \n"
|
||||
" \n"
|
||||
" mrs r1, control \n"
|
||||
" stmdb r0!, {r1, r4-r11} \n" /* Save the remaining registers. */
|
||||
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
|
||||
" \n"
|
||||
" stmdb sp!, {r3, r14} \n"
|
||||
" mov r0, %0 \n"
|
||||
" msr basepri, r0 \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"
|
||||
" ldmia sp!, {r3, r14} \n"
|
||||
" \n" /* Restore the context. */
|
||||
" ldr r1, [r3] \n"
|
||||
" 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... */
|
||||
" ldr r2, =0xe000ed9c \n" /* Region Base Address register. */
|
||||
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */
|
||||
" stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */
|
||||
" ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */
|
||||
" msr control, r3 \n"
|
||||
" \n"
|
||||
" msr psp, r0 \n"
|
||||
" bx r14 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void xPortSysTickHandler( void )
|
||||
{
|
||||
uint32_t ulDummy;
|
||||
|
||||
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Pend a context switch. */
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||
}
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the systick timer to generate the tick interrupts at the required
|
||||
* frequency.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupMPU( void )
|
||||
{
|
||||
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__[];
|
||||
|
||||
/* Check the expected MPU is present. */
|
||||
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
|
||||
{
|
||||
/* First setup the entire flash for unprivileged read only access. */
|
||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portUNPRIVILEGED_FLASH_REGION );
|
||||
|
||||
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_ONLY ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* Setup the first 16K for privileged only access (even though less
|
||||
than 10K is actually being used). This is where the kernel code is
|
||||
placed. */
|
||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portPRIVILEGED_FLASH_REGION );
|
||||
|
||||
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* Setup the privileged data RAM region. This is where the kernel data
|
||||
is placed. */
|
||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portPRIVILEGED_RAM_REGION );
|
||||
|
||||
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* By default allow everything to access the general peripherals. The
|
||||
system peripherals and registers are protected. */
|
||||
portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) |
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portGENERAL_PERIPHERALS_REGION );
|
||||
|
||||
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_WRITE | portMPU_REGION_EXECUTE_NEVER ) |
|
||||
( prvGetMPURegionSizeSetting( portPERIPHERALS_END_ADDRESS - portPERIPHERALS_START_ADDRESS ) ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* Enable the memory fault exception. */
|
||||
portNVIC_SYS_CTRL_STATE_REG |= portNVIC_MEM_FAULT_ENABLE;
|
||||
|
||||
/* Enable the MPU with the background region configured. */
|
||||
portMPU_CTRL_REG |= ( portMPU_ENABLE | portMPU_BACKGROUND_ENABLE );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes )
|
||||
{
|
||||
uint32_t ulRegionSize, ulReturnValue = 4;
|
||||
|
||||
/* 32 is the smallest region size, 31 is the largest valid value for
|
||||
ulReturnValue. */
|
||||
for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) )
|
||||
{
|
||||
if( ulActualSizeInBytes <= ulRegionSize )
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulReturnValue++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Shift the code by one before returning so it can be written directly
|
||||
into the the correct bit position of the attribute register. */
|
||||
return ( ulReturnValue << 1UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortRaisePrivilege( void )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n"
|
||||
" tst r0, #1 \n" /* Is the task running privileged? */
|
||||
" itte ne \n"
|
||||
" movne r0, #0 \n" /* CONTROL[0]!=0, return false. */
|
||||
" svcne %0 \n" /* Switch to privileged. */
|
||||
" moveq r0, #1 \n" /* CONTROL[0]==0, return true. */
|
||||
" bx lr \n"
|
||||
:: "i" (portSVC_RAISE_PRIVILEGE) : "r0"
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth )
|
||||
{
|
||||
extern uint32_t __SRAM_segment_start__[];
|
||||
extern uint32_t __SRAM_segment_end__[];
|
||||
extern uint32_t __privileged_data_start__[];
|
||||
extern uint32_t __privileged_data_end__[];
|
||||
int32_t lIndex;
|
||||
uint32_t ul;
|
||||
|
||||
if( xRegions == NULL )
|
||||
{
|
||||
/* No MPU regions are specified so allow access to all RAM. */
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress =
|
||||
( ( uint32_t ) __SRAM_segment_start__ ) | /* Base address. */
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portSTACK_REGION );
|
||||
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
|
||||
( portMPU_REGION_READ_WRITE ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* Re-instate the privileged only RAM region as xRegion[ 0 ] will have
|
||||
just removed the privileged only parameters. */
|
||||
xMPUSettings->xRegion[ 1 ].ulRegionBaseAddress =
|
||||
( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portSTACK_REGION + 1 );
|
||||
|
||||
xMPUSettings->xRegion[ 1 ].ulRegionAttribute =
|
||||
( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* Invalidate all other regions. */
|
||||
for( ul = 2; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ )
|
||||
{
|
||||
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( portSTACK_REGION + ul ) | portMPU_REGION_VALID;
|
||||
xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This function is called automatically when the task is created - in
|
||||
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
|
||||
stack region has already been configured. */
|
||||
if( ulStackDepth > 0 )
|
||||
{
|
||||
/* Define the region that allows access to the stack. */
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress =
|
||||
( ( uint32_t ) pxBottomOfStack ) |
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portSTACK_REGION ); /* Region number. */
|
||||
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
|
||||
( portMPU_REGION_READ_WRITE ) | /* Read and write. */
|
||||
( prvGetMPURegionSizeSetting( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
}
|
||||
|
||||
lIndex = 0;
|
||||
|
||||
for( ul = 1; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ )
|
||||
{
|
||||
if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL )
|
||||
{
|
||||
/* Translate the generic region definition contained in
|
||||
xRegions into the CM3 specific MPU settings that are then
|
||||
stored in xMPUSettings. */
|
||||
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress =
|
||||
( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) |
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portSTACK_REGION + ul ); /* Region number. */
|
||||
|
||||
xMPUSettings->xRegion[ ul ].ulRegionAttribute =
|
||||
( prvGetMPURegionSizeSetting( xRegions[ lIndex ].ulLengthInBytes ) ) |
|
||||
( xRegions[ lIndex ].ulParameters ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalidate the region. */
|
||||
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( portSTACK_REGION + ul ) | portMPU_REGION_VALID;
|
||||
xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL;
|
||||
}
|
||||
|
||||
lIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
uint8_t ucCurrentPriority;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
|
||||
|
||||
/* Is the interrupt number a user defined interrupt? */
|
||||
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||
{
|
||||
/* Look up the interrupt's priority. */
|
||||
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
an interrupt that has been assigned a priority above
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
function. ISR safe FreeRTOS API functions must *only* be called
|
||||
from interrupts that have been assigned a priority at or below
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
|
||||
Numerically low interrupt priority numbers represent logically high
|
||||
interrupt priorities, therefore the priority of the interrupt must
|
||||
be set to a value equal to or numerically *higher* than
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
|
||||
Interrupts that use the FreeRTOS API must not be left at their
|
||||
default priority of zero as that is the highest possible priority,
|
||||
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||
and therefore also guaranteed to be invalid.
|
||||
|
||||
FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||
interrupt entry is as fast and simple as possible.
|
||||
|
||||
The following links provide detailed information:
|
||||
http://www.freertos.org/RTOS-Cortex-M3-M4.html
|
||||
http://www.freertos.org/FAQHelp.html */
|
||||
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||
}
|
||||
|
||||
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
||||
that define each interrupt's priority to be split between bits that
|
||||
define the interrupt's pre-emption priority bits and bits that define
|
||||
the interrupt's sub-priority. For simplicity all bits must be defined
|
||||
to be pre-emption priority bits. The following assertion will fail if
|
||||
this is not the case (if some bits represent a sub-priority).
|
||||
|
||||
If the application only uses CMSIS libraries for interrupt
|
||||
configuration then the correct setting can be achieved on all Cortex-M
|
||||
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||
scheduler. Note however that some vendor specific peripheral libraries
|
||||
assume a non-zero priority group setting, in which cases using a value
|
||||
of zero will result in unpredicable behaviour. */
|
||||
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||
}
|
||||
|
||||
#endif /* configASSERT_DEFINED */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,332 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#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;
|
||||
|
||||
#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
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* MPU specific constants. */
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
|
||||
#define portMPU_REGION_READ_WRITE ( 0x03UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
|
||||
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
|
||||
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 2UL )
|
||||
#define portGENERAL_PERIPHERALS_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
|
||||
#define portSWITCH_TO_USER_MODE() __asm volatile ( " mrs r0, control \n orr r0, #1 \n msr control, r0 " :::"r0" )
|
||||
|
||||
typedef struct MPU_REGION_REGISTERS
|
||||
{
|
||||
uint32_t ulRegionBaseAddress;
|
||||
uint32_t ulRegionAttribute;
|
||||
} xMPU_REGION_REGISTERS;
|
||||
|
||||
/* Plus 1 to create space for the stack region. */
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS ];
|
||||
} xMPU_SETTINGS;
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* SVC numbers for various services. */
|
||||
#define portSVC_START_SCHEDULER 0
|
||||
#define portSVC_YIELD 1
|
||||
#define portSVC_RAISE_PRIVILEGE 2
|
||||
|
||||
/* Scheduler utilities. */
|
||||
|
||||
#define portYIELD() __asm volatile ( " SVC %0 \n" :: "i" (portSVC_YIELD) )
|
||||
#define portYIELD_WITHIN_API() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
\
|
||||
/* Barriers are normally not required but do ensure the code is completely \
|
||||
within the specified behaviour for the architecture. */ \
|
||||
__asm volatile( "dsb" ); \
|
||||
__asm volatile( "isb" ); \
|
||||
}
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
|
||||
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
|
||||
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
not necessary for to use this port. They are defined so the common demo files
|
||||
(which build with all the ports) will build. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Generic helper function. */
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) );
|
||||
return ucReturn;
|
||||
}
|
||||
|
||||
/* Check the configuration. */
|
||||
#if( configMAX_PRIORITIES > 32 )
|
||||
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||
#endif
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
|
||||
/* portNOP() is not required by this port. */
|
||||
#define portNOP()
|
||||
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||
#endif
|
||||
|
||||
/* Set the privilege level to user mode if xRunningPrivileged is false. */
|
||||
portFORCE_INLINE static void vPortResetPrivilege( BaseType_t xRunningPrivileged )
|
||||
{
|
||||
if( xRunningPrivileged != pdTRUE )
|
||||
{
|
||||
__asm volatile ( " mrs r0, control \n" \
|
||||
" orr r0, #1 \n" \
|
||||
" msr control, r0 \n" \
|
||||
:::"r0" );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
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 ) );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mov %0, %1 \n" \
|
||||
" msr basepri, %0 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mrs %0, basepri \n" \
|
||||
" mov %1, %2 \n" \
|
||||
" msr basepri, %1 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
|
||||
/* This return will not be reached but is necessary to prevent compiler
|
||||
warnings. */
|
||||
return ulOriginalBASEPRI;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, %0 " :: "r" ( ulNewMaskValue )
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
@ -0,0 +1,763 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM CM4F port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#ifndef __VFP_FP__
|
||||
#error This port can only be used when the project options are configured to enable hardware floating point support.
|
||||
#endif
|
||||
|
||||
#ifndef configSYSTICK_CLOCK_HZ
|
||||
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||
#else
|
||||
/* The way the SysTick is clocked is not modified in case it is not the same
|
||||
as the core. */
|
||||
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||
#endif
|
||||
|
||||
/* Constants required to manipulate the core. Registers first... */
|
||||
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||
/* ...then bits in the registers. */
|
||||
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
|
||||
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
|
||||
|
||||
/* Constants used to detect a Cortex-M7 r0p1 core, which should use the ARM_CM7
|
||||
r0p1 port. */
|
||||
#define portCPUID ( * ( ( volatile uint32_t * ) 0xE000ed00 ) )
|
||||
#define portCORTEX_M7_r0p1_ID ( 0x410FC271UL )
|
||||
#define portCORTEX_M7_r0p0_ID ( 0x410FC270UL )
|
||||
|
||||
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||
|
||||
/* Constants required to check the validity of an interrupt priority. */
|
||||
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||
#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
|
||||
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
|
||||
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
|
||||
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||
#define portPRIGROUP_SHIFT ( 8UL )
|
||||
|
||||
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
|
||||
#define portVECTACTIVE_MASK ( 0xFFUL )
|
||||
|
||||
/* Constants required to manipulate the VFP. */
|
||||
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
|
||||
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
|
||||
|
||||
/* Constants required to set up the initial stack. */
|
||||
#define portINITIAL_XPSR ( 0x01000000 )
|
||||
#define portINITIAL_EXEC_RETURN ( 0xfffffffd )
|
||||
|
||||
/* The systick is a 24-bit counter. */
|
||||
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||
|
||||
/* 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. */
|
||||
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
||||
|
||||
/* A fiddle factor to estimate the number of SysTick counts that would have
|
||||
occurred while the SysTick counter is stopped during tickless idle
|
||||
calculations. */
|
||||
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||
|
||||
/* 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
|
||||
debugger. */
|
||||
#ifdef configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#else
|
||||
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#endif
|
||||
|
||||
/* Each task maintains its own interrupt status in the critical nesting
|
||||
variable. */
|
||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* Exception handlers.
|
||||
*/
|
||||
void xPortPendSVHandler( void ) __attribute__ (( naked ));
|
||||
void xPortSysTickHandler( void );
|
||||
void vPortSVCHandler( void ) __attribute__ (( naked ));
|
||||
|
||||
/*
|
||||
* Start first task is a separate function so it can be tested in isolation.
|
||||
*/
|
||||
static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
|
||||
|
||||
/*
|
||||
* Function to enable the VFP.
|
||||
*/
|
||||
static void vPortEnableVFP( void ) __attribute__ (( naked ));
|
||||
|
||||
/*
|
||||
* Used to catch tasks that attempt to return from their implementing function.
|
||||
*/
|
||||
static void prvTaskExitError( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
/*
|
||||
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
*/
|
||||
#if ( configASSERT_DEFINED == 1 )
|
||||
static uint8_t ucMaxSysCallPriority = 0;
|
||||
static uint32_t ulMaxPRIGROUPValue = 0;
|
||||
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
interrupt. */
|
||||
|
||||
/* Offset added to account for the way the MCU uses the stack on entry/exit
|
||||
of interrupts, and to ensure alignment. */
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
|
||||
|
||||
/* Save code space by skipping register initialisation. */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
|
||||
/* A save method is being used that requires each task to maintain its
|
||||
own exec return value. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_EXEC_RETURN;
|
||||
|
||||
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvTaskExitError( void )
|
||||
{
|
||||
/* A function that implements a task must not exit or attempt to return to
|
||||
its caller as there is nothing to return to. If a task wants to exit it
|
||||
should instead call vTaskDelete( NULL ).
|
||||
|
||||
Artificially force an assert() to be triggered if configASSERT() is
|
||||
defined, then stop here so application writers can catch the error. */
|
||||
configASSERT( uxCriticalNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
for( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortSVCHandler( void )
|
||||
{
|
||||
__asm volatile (
|
||||
" ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */
|
||||
" ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
|
||||
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
|
||||
" ldmia r0!, {r4-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
|
||||
" msr psp, r0 \n" /* Restore the task stack pointer. */
|
||||
" isb \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"
|
||||
" bx r14 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvPortStartFirstTask( void )
|
||||
{
|
||||
__asm volatile(
|
||||
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"
|
||||
" ldr r0, [r0] \n"
|
||||
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
|
||||
" cpsie i \n" /* Globally enable interrupts. */
|
||||
" cpsie f \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc 0 \n" /* System call to start first task. */
|
||||
" nop \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
|
||||
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
||||
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
|
||||
|
||||
/* 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
|
||||
/source/portable/GCC/ARM_CM7/r0p1 directory. */
|
||||
configASSERT( portCPUID != portCORTEX_M7_r0p1_ID );
|
||||
configASSERT( portCPUID != portCORTEX_M7_r0p0_ID );
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
volatile uint32_t ulOriginalPriority;
|
||||
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||
volatile uint8_t ucMaxPriorityValue;
|
||||
|
||||
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||
functions can be called. ISR safe functions are those that end in
|
||||
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||
ensure interrupt entry is as fast and simple as possible.
|
||||
|
||||
Save the interrupt priority value that is about to be clobbered. */
|
||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Determine the number of priority bits available. First write to all
|
||||
possible bits. */
|
||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||
|
||||
/* Read the value back to see how many bits stuck. */
|
||||
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Use the same mask on the maximum system call priority. */
|
||||
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||
|
||||
/* Calculate the maximum acceptable priority group value for the number
|
||||
of bits read back. */
|
||||
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
||||
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||
{
|
||||
ulMaxPRIGROUPValue--;
|
||||
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
|
||||
}
|
||||
|
||||
/* Shift the priority group value back to its position within the AIRCR
|
||||
register. */
|
||||
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||
|
||||
/* Restore the clobbered interrupt priority register to its original
|
||||
value. */
|
||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||
}
|
||||
#endif /* conifgASSERT_DEFINED */
|
||||
|
||||
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
vPortSetupTimerInterrupt();
|
||||
|
||||
/* Initialise the critical nesting count ready for the first task. */
|
||||
uxCriticalNesting = 0;
|
||||
|
||||
/* Ensure the VFP is enabled - it should be anyway. */
|
||||
vPortEnableVFP();
|
||||
|
||||
/* Lazy save always. */
|
||||
*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
|
||||
|
||||
/* Start the first task. */
|
||||
prvPortStartFirstTask();
|
||||
|
||||
/* Should never get here as the tasks will now be executing! Call the task
|
||||
exit error function to prevent compiler warnings about a static function
|
||||
not being called in the case that the application writer overrides this
|
||||
functionality by defining configTASK_RETURN_ADDRESS. */
|
||||
prvTaskExitError();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( uxCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
uxCriticalNesting++;
|
||||
|
||||
/* 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
|
||||
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
|
||||
assert function also uses a critical section. */
|
||||
if( uxCriticalNesting == 1 )
|
||||
{
|
||||
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
configASSERT( uxCriticalNesting );
|
||||
uxCriticalNesting--;
|
||||
if( uxCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void xPortPendSVHandler( void )
|
||||
{
|
||||
/* This is a naked function. */
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, psp \n"
|
||||
" isb \n"
|
||||
" \n"
|
||||
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
|
||||
" ldr r2, [r3] \n"
|
||||
" \n"
|
||||
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */
|
||||
" it eq \n"
|
||||
" vstmdbeq r0!, {s16-s31} \n"
|
||||
" \n"
|
||||
" stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */
|
||||
" \n"
|
||||
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
|
||||
" \n"
|
||||
" stmdb sp!, {r3} \n"
|
||||
" mov r0, %0 \n"
|
||||
" msr basepri, r0 \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"
|
||||
" ldmia sp!, {r3} \n"
|
||||
" \n"
|
||||
" ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */
|
||||
" ldr r0, [r1] \n"
|
||||
" \n"
|
||||
" ldmia r0!, {r4-r11, r14} \n" /* Pop the core registers. */
|
||||
" \n"
|
||||
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, pop the high vfp registers too. */
|
||||
" it eq \n"
|
||||
" vldmiaeq r0!, {s16-s31} \n"
|
||||
" \n"
|
||||
" msr psp, r0 \n"
|
||||
" isb \n"
|
||||
" \n"
|
||||
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */
|
||||
#if WORKAROUND_PMU_CM001 == 1
|
||||
" push { r14 } \n"
|
||||
" pop { pc } \n"
|
||||
#endif
|
||||
#endif
|
||||
" \n"
|
||||
" bx r14 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void xPortSysTickHandler( void )
|
||||
{
|
||||
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
|
||||
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
|
||||
known. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* A context switch is required. Context switching is performed in
|
||||
the PendSV interrupt. Pend the PendSV interrupt. */
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||
}
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if configUSE_TICKLESS_IDLE == 1
|
||||
|
||||
__attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||
{
|
||||
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
|
||||
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" );
|
||||
__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" );
|
||||
}
|
||||
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" );
|
||||
__asm volatile( "wfi" );
|
||||
__asm volatile( "isb" );
|
||||
}
|
||||
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||
|
||||
/* Stop SysTick. 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. */
|
||||
ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
|
||||
portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
|
||||
|
||||
/* Re-enable interrupts - see comments above the cpsid instruction()
|
||||
above. */
|
||||
__asm volatile( "cpsie i" );
|
||||
|
||||
if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||
{
|
||||
uint32_t ulCalculatedLoadValue;
|
||||
|
||||
/* The tick interrupt has already executed, 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;
|
||||
|
||||
/* The tick interrupt handler will already have pended the tick
|
||||
processing in the kernel. 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. The critical section is used to ensure the tick interrupt
|
||||
can only execute once in the case that the reload register is near
|
||||
zero. */
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
vTaskStepTick( ulCompleteTickPeriods );
|
||||
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||
}
|
||||
portEXIT_CRITICAL();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #if configUSE_TICKLESS_IDLE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the systick timer to generate the tick interrupts at the required
|
||||
* frequency.
|
||||
*/
|
||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Calculate the constants required to configure the tick interrupt. */
|
||||
#if configUSE_TICKLESS_IDLE == 1
|
||||
{
|
||||
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||
}
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* This is a naked function. */
|
||||
static void vPortEnableVFP( void )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" ldr.w r0, =0xE000ED88 \n" /* The FPU enable bits are in the CPACR. */
|
||||
" ldr r1, [r0] \n"
|
||||
" \n"
|
||||
" orr r1, r1, #( 0xf << 20 ) \n" /* Enable CP10 and CP11 coprocessors, then save back. */
|
||||
" str r1, [r0] \n"
|
||||
" bx r14 "
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
uint8_t ucCurrentPriority;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
|
||||
|
||||
/* Is the interrupt number a user defined interrupt? */
|
||||
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||
{
|
||||
/* Look up the interrupt's priority. */
|
||||
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
an interrupt that has been assigned a priority above
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
function. ISR safe FreeRTOS API functions must *only* be called
|
||||
from interrupts that have been assigned a priority at or below
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
|
||||
Numerically low interrupt priority numbers represent logically high
|
||||
interrupt priorities, therefore the priority of the interrupt must
|
||||
be set to a value equal to or numerically *higher* than
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
|
||||
Interrupts that use the FreeRTOS API must not be left at their
|
||||
default priority of zero as that is the highest possible priority,
|
||||
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||
and therefore also guaranteed to be invalid.
|
||||
|
||||
FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||
interrupt entry is as fast and simple as possible.
|
||||
|
||||
The following links provide detailed information:
|
||||
http://www.freertos.org/RTOS-Cortex-M3-M4.html
|
||||
http://www.freertos.org/FAQHelp.html */
|
||||
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||
}
|
||||
|
||||
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
||||
that define each interrupt's priority to be split between bits that
|
||||
define the interrupt's pre-emption priority bits and bits that define
|
||||
the interrupt's sub-priority. For simplicity all bits must be defined
|
||||
to be pre-emption priority bits. The following assertion will fail if
|
||||
this is not the case (if some bits represent a sub-priority).
|
||||
|
||||
If the application only uses CMSIS libraries for interrupt
|
||||
configuration then the correct setting can be achieved on all Cortex-M
|
||||
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||
scheduler. Note however that some vendor specific peripheral libraries
|
||||
assume a non-zero priority group setting, in which cases using a value
|
||||
of zero will result in unpredicable behaviour. */
|
||||
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||
}
|
||||
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#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;
|
||||
|
||||
#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
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler utilities. */
|
||||
#define portYIELD() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
\
|
||||
/* Barriers are normally not required but do ensure the code is completely \
|
||||
within the specified behaviour for the architecture. */ \
|
||||
__asm volatile( "dsb" ); \
|
||||
__asm volatile( "isb" ); \
|
||||
}
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
|
||||
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
|
||||
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
not necessary for to use this port. They are defined so the common demo files
|
||||
(which build with all the ports) will build. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Generic helper function. */
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) );
|
||||
return ucReturn;
|
||||
}
|
||||
|
||||
/* Check the configuration. */
|
||||
#if( configMAX_PRIORITIES > 32 )
|
||||
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||
#endif
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
|
||||
/* portNOP() is not required by this port. */
|
||||
#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 ) );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mov %0, %1 \n" \
|
||||
" msr basepri, %0 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mrs %0, basepri \n" \
|
||||
" mov %1, %2 \n" \
|
||||
" msr basepri, %1 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
|
||||
/* This return will not be reached but is necessary to prevent compiler
|
||||
warnings. */
|
||||
return ulOriginalBASEPRI;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, %0 " :: "r" ( ulNewMaskValue )
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
@ -0,0 +1,819 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM CM3 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "queue.h"
|
||||
#include "event_groups.h"
|
||||
#include "mpu_prototypes.h"
|
||||
|
||||
#ifndef __VFP_FP__
|
||||
#error This port can only be used when the project options are configured to enable hardware floating point support.
|
||||
#endif
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Constants required to access and manipulate the NVIC. */
|
||||
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||
#define portNVIC_SYSPRI1_REG ( * ( ( volatile uint32_t * ) 0xe000ed1c ) )
|
||||
#define portNVIC_SYS_CTRL_STATE_REG ( * ( ( volatile uint32_t * ) 0xe000ed24 ) )
|
||||
#define portNVIC_MEM_FAULT_ENABLE ( 1UL << 16UL )
|
||||
|
||||
/* Constants required to access and manipulate the MPU. */
|
||||
#define portMPU_TYPE_REG ( * ( ( volatile uint32_t * ) 0xe000ed90 ) )
|
||||
#define portMPU_REGION_BASE_ADDRESS_REG ( * ( ( volatile uint32_t * ) 0xe000ed9C ) )
|
||||
#define portMPU_REGION_ATTRIBUTE_REG ( * ( ( volatile uint32_t * ) 0xe000edA0 ) )
|
||||
#define portMPU_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed94 ) )
|
||||
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
||||
#define portMPU_ENABLE ( 0x01UL )
|
||||
#define portMPU_BACKGROUND_ENABLE ( 1UL << 2UL )
|
||||
#define portPRIVILEGED_EXECUTION_START_ADDRESS ( 0UL )
|
||||
#define portMPU_REGION_VALID ( 0x10UL )
|
||||
#define portMPU_REGION_ENABLE ( 0x01UL )
|
||||
#define portPERIPHERALS_START_ADDRESS 0x40000000UL
|
||||
#define portPERIPHERALS_END_ADDRESS 0x5FFFFFFFUL
|
||||
|
||||
/* Constants required to access and manipulate the SysTick. */
|
||||
#define portNVIC_SYSTICK_CLK ( 0x00000004UL )
|
||||
#define portNVIC_SYSTICK_INT ( 0x00000002UL )
|
||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001UL )
|
||||
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||
#define portNVIC_SVC_PRI ( ( ( uint32_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL ) << 24UL )
|
||||
|
||||
/* Constants required to manipulate the VFP. */
|
||||
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34UL ) /* Floating point context control register. */
|
||||
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
|
||||
|
||||
/* Constants required to set up the initial stack. */
|
||||
#define portINITIAL_XPSR ( 0x01000000UL )
|
||||
#define portINITIAL_EXEC_RETURN ( 0xfffffffdUL )
|
||||
#define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 )
|
||||
#define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 )
|
||||
|
||||
/* Constants required to check the validity of an interrupt priority. */
|
||||
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||
#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
|
||||
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
|
||||
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
|
||||
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||
#define portPRIGROUP_SHIFT ( 8UL )
|
||||
|
||||
/* Offsets in the stack to the parameters when inside the SVC handler. */
|
||||
#define portOFFSET_TO_PC ( 6 )
|
||||
|
||||
/* 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. */
|
||||
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
||||
|
||||
/* 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
|
||||
switches can only occur when uxCriticalNesting is zero. */
|
||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||
|
||||
/*
|
||||
* Setup the timer to generate the tick interrupts.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Configure a number of standard MPU regions that are used by all tasks.
|
||||
*/
|
||||
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Return the smallest MPU region size that a given number of bytes will fit
|
||||
* into. The region size is returned as the value that should be programmed
|
||||
* into the region attribute register for that region.
|
||||
*/
|
||||
static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Checks to see if being called from the context of an unprivileged task, and
|
||||
* if so raises the privilege level and returns false - otherwise does nothing
|
||||
* other than return true.
|
||||
*/
|
||||
BaseType_t xPortRaisePrivilege( void ) __attribute__(( naked ));
|
||||
|
||||
/*
|
||||
* Standard FreeRTOS exception handlers.
|
||||
*/
|
||||
void xPortPendSVHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
void xPortSysTickHandler( void ) __attribute__ ((optimize("3"))) PRIVILEGED_FUNCTION;
|
||||
void vPortSVCHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Starts the scheduler by restoring the context of the first task to run.
|
||||
*/
|
||||
static void prvRestoreContextOfFirstTask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* C portion of the SVC handler. The SVC handler is split between an asm entry
|
||||
* and a C wrapper for simplicity of coding and maintenance.
|
||||
*/
|
||||
static void prvSVCHandler( uint32_t *pulRegisters ) __attribute__(( noinline )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Function to enable the VFP.
|
||||
*/
|
||||
static void vPortEnableVFP( void ) __attribute__ (( naked ));
|
||||
|
||||
/*
|
||||
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
*/
|
||||
#if ( configASSERT_DEFINED == 1 )
|
||||
static uint8_t ucMaxSysCallPriority = 0;
|
||||
static uint32_t ulMaxPRIGROUPValue = 0;
|
||||
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
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
|
||||
interrupt. */
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0; /* LR */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
|
||||
/* A save method is being used that requires each task to maintain its
|
||||
own exec return value. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_EXEC_RETURN;
|
||||
|
||||
pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
|
||||
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_IF_PRIVILEGED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_IF_UNPRIVILEGED;
|
||||
}
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortSVCHandler( void )
|
||||
{
|
||||
/* Assumes psp was in use. */
|
||||
__asm volatile
|
||||
(
|
||||
#ifndef USE_PROCESS_STACK /* Code should not be required if a main() is using the process stack. */
|
||||
" tst lr, #4 \n"
|
||||
" ite eq \n"
|
||||
" mrseq r0, msp \n"
|
||||
" mrsne r0, psp \n"
|
||||
#else
|
||||
" mrs r0, psp \n"
|
||||
#endif
|
||||
" b %0 \n"
|
||||
::"i"(prvSVCHandler):"r0"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSVCHandler( uint32_t *pulParam )
|
||||
{
|
||||
uint8_t ucSVCNumber;
|
||||
|
||||
/* 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 )
|
||||
{
|
||||
case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI;
|
||||
prvRestoreContextOfFirstTask();
|
||||
break;
|
||||
|
||||
case portSVC_YIELD : portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||
/* Barriers are normally not required
|
||||
but do ensure the code is completely
|
||||
within the specified behaviour for the
|
||||
architecture. */
|
||||
__asm volatile( "dsb" );
|
||||
__asm volatile( "isb" );
|
||||
|
||||
break;
|
||||
|
||||
case portSVC_RAISE_PRIVILEGE : __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"
|
||||
);
|
||||
break;
|
||||
|
||||
default : /* Unknown SVC call. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvRestoreContextOfFirstTask( void )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"
|
||||
" ldr r0, [r0] \n"
|
||||
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
|
||||
" ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */
|
||||
" ldr r1, [r3] \n"
|
||||
" 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... */
|
||||
" ldr r2, =0xe000ed9c \n" /* Region Base Address register. */
|
||||
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */
|
||||
" stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */
|
||||
" ldmia r0!, {r3-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry. */
|
||||
" msr control, r3 \n"
|
||||
" msr psp, r0 \n" /* Restore the task stack pointer. */
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"
|
||||
" bx r14 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See
|
||||
http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
||||
configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) );
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
volatile uint32_t ulOriginalPriority;
|
||||
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||
volatile uint8_t ucMaxPriorityValue;
|
||||
|
||||
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||
functions can be called. ISR safe functions are those that end in
|
||||
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||
ensure interrupt entry is as fast and simple as possible.
|
||||
|
||||
Save the interrupt priority value that is about to be clobbered. */
|
||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Determine the number of priority bits available. First write to all
|
||||
possible bits. */
|
||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||
|
||||
/* Read the value back to see how many bits stuck. */
|
||||
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Use the same mask on the maximum system call priority. */
|
||||
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||
|
||||
/* Calculate the maximum acceptable priority group value for the number
|
||||
of bits read back. */
|
||||
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
||||
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||
{
|
||||
ulMaxPRIGROUPValue--;
|
||||
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
|
||||
}
|
||||
|
||||
/* Shift the priority group value back to its position within the AIRCR
|
||||
register. */
|
||||
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||
|
||||
/* Restore the clobbered interrupt priority register to its original
|
||||
value. */
|
||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||
}
|
||||
#endif /* conifgASSERT_DEFINED */
|
||||
|
||||
/* 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
|
||||
lower priorities are masked). */
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||
|
||||
/* Configure the regions in the MPU that are common to all tasks. */
|
||||
prvSetupMPU();
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Initialise the critical nesting count ready for the first task. */
|
||||
uxCriticalNesting = 0;
|
||||
|
||||
/* Ensure the VFP is enabled - it should be anyway. */
|
||||
vPortEnableVFP();
|
||||
|
||||
/* Lazy save always. */
|
||||
*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
|
||||
|
||||
/* Start the first task. */
|
||||
__asm volatile(
|
||||
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"
|
||||
" ldr r0, [r0] \n"
|
||||
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
|
||||
" cpsie i \n" /* Globally enable interrupts. */
|
||||
" cpsie f \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n" /* System call to start first task. */
|
||||
" nop \n"
|
||||
:: "i" (portSVC_START_SCHEDULER) );
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( uxCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
|
||||
|
||||
portDISABLE_INTERRUPTS();
|
||||
uxCriticalNesting++;
|
||||
|
||||
vPortResetPrivilege( xRunningPrivileged );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
|
||||
|
||||
configASSERT( uxCriticalNesting );
|
||||
uxCriticalNesting--;
|
||||
if( uxCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
vPortResetPrivilege( xRunningPrivileged );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void xPortPendSVHandler( void )
|
||||
{
|
||||
/* This is a naked function. */
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, psp \n"
|
||||
" \n"
|
||||
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
|
||||
" ldr r2, [r3] \n"
|
||||
" \n"
|
||||
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */
|
||||
" it eq \n"
|
||||
" vstmdbeq r0!, {s16-s31} \n"
|
||||
" \n"
|
||||
" mrs r1, control \n"
|
||||
" stmdb r0!, {r1, r4-r11, r14} \n" /* Save the remaining registers. */
|
||||
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
|
||||
" \n"
|
||||
" stmdb sp!, {r3} \n"
|
||||
" mov r0, %0 \n"
|
||||
" msr basepri, r0 \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"
|
||||
" ldmia sp!, {r3} \n"
|
||||
" \n" /* Restore the context. */
|
||||
" ldr r1, [r3] \n"
|
||||
" 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... */
|
||||
" ldr r2, =0xe000ed9c \n" /* Region Base Address register. */
|
||||
" ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */
|
||||
" stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */
|
||||
" ldmia r0!, {r3-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry. */
|
||||
" msr control, r3 \n"
|
||||
" \n"
|
||||
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, pop the high vfp registers too. */
|
||||
" it eq \n"
|
||||
" vldmiaeq r0!, {s16-s31} \n"
|
||||
" \n"
|
||||
" msr psp, r0 \n"
|
||||
" bx r14 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void xPortSysTickHandler( void )
|
||||
{
|
||||
uint32_t ulDummy;
|
||||
|
||||
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Pend a context switch. */
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||
}
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the systick timer to generate the tick interrupts at the required
|
||||
* frequency.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* This is a naked function. */
|
||||
static void vPortEnableVFP( void )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" ldr.w r0, =0xE000ED88 \n" /* The FPU enable bits are in the CPACR. */
|
||||
" ldr r1, [r0] \n"
|
||||
" \n"
|
||||
" orr r1, r1, #( 0xf << 20 ) \n" /* Enable CP10 and CP11 coprocessors, then save back. */
|
||||
" str r1, [r0] \n"
|
||||
" bx r14 "
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupMPU( void )
|
||||
{
|
||||
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__[];
|
||||
|
||||
/* Check the expected MPU is present. */
|
||||
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
|
||||
{
|
||||
/* First setup the entire flash for unprivileged read only access. */
|
||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portUNPRIVILEGED_FLASH_REGION );
|
||||
|
||||
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_ONLY ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* Setup the first 16K for privileged only access (even though less
|
||||
than 10K is actually being used). This is where the kernel code is
|
||||
placed. */
|
||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portPRIVILEGED_FLASH_REGION );
|
||||
|
||||
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* Setup the privileged data RAM region. This is where the kernel data
|
||||
is placed. */
|
||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portPRIVILEGED_RAM_REGION );
|
||||
|
||||
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* By default allow everything to access the general peripherals. The
|
||||
system peripherals and registers are protected. */
|
||||
portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) |
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portGENERAL_PERIPHERALS_REGION );
|
||||
|
||||
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_WRITE | portMPU_REGION_EXECUTE_NEVER ) |
|
||||
( prvGetMPURegionSizeSetting( portPERIPHERALS_END_ADDRESS - portPERIPHERALS_START_ADDRESS ) ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* Enable the memory fault exception. */
|
||||
portNVIC_SYS_CTRL_STATE_REG |= portNVIC_MEM_FAULT_ENABLE;
|
||||
|
||||
/* Enable the MPU with the background region configured. */
|
||||
portMPU_CTRL_REG |= ( portMPU_ENABLE | portMPU_BACKGROUND_ENABLE );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes )
|
||||
{
|
||||
uint32_t ulRegionSize, ulReturnValue = 4;
|
||||
|
||||
/* 32 is the smallest region size, 31 is the largest valid value for
|
||||
ulReturnValue. */
|
||||
for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) )
|
||||
{
|
||||
if( ulActualSizeInBytes <= ulRegionSize )
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulReturnValue++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Shift the code by one before returning so it can be written directly
|
||||
into the the correct bit position of the attribute register. */
|
||||
return ( ulReturnValue << 1UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortRaisePrivilege( void )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r0, control \n"
|
||||
" tst r0, #1 \n" /* Is the task running privileged? */
|
||||
" itte ne \n"
|
||||
" movne r0, #0 \n" /* CONTROL[0]!=0, return false. */
|
||||
" svcne %0 \n" /* Switch to privileged. */
|
||||
" moveq r0, #1 \n" /* CONTROL[0]==0, return true. */
|
||||
" bx lr \n"
|
||||
:: "i" (portSVC_RAISE_PRIVILEGE) : "r0"
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth )
|
||||
{
|
||||
extern uint32_t __SRAM_segment_start__[];
|
||||
extern uint32_t __SRAM_segment_end__[];
|
||||
extern uint32_t __privileged_data_start__[];
|
||||
extern uint32_t __privileged_data_end__[];
|
||||
int32_t lIndex;
|
||||
uint32_t ul;
|
||||
|
||||
if( xRegions == NULL )
|
||||
{
|
||||
/* No MPU regions are specified so allow access to all RAM. */
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress =
|
||||
( ( uint32_t ) __SRAM_segment_start__ ) | /* Base address. */
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portSTACK_REGION );
|
||||
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
|
||||
( portMPU_REGION_READ_WRITE ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* Re-instate the privileged only RAM region as xRegion[ 0 ] will have
|
||||
just removed the privileged only parameters. */
|
||||
xMPUSettings->xRegion[ 1 ].ulRegionBaseAddress =
|
||||
( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portSTACK_REGION + 1 );
|
||||
|
||||
xMPUSettings->xRegion[ 1 ].ulRegionAttribute =
|
||||
( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* Invalidate all other regions. */
|
||||
for( ul = 2; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ )
|
||||
{
|
||||
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( portSTACK_REGION + ul ) | portMPU_REGION_VALID;
|
||||
xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This function is called automatically when the task is created - in
|
||||
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
|
||||
stack region has already been configured. */
|
||||
if( ulStackDepth > 0 )
|
||||
{
|
||||
/* Define the region that allows access to the stack. */
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress =
|
||||
( ( uint32_t ) pxBottomOfStack ) |
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portSTACK_REGION ); /* Region number. */
|
||||
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
|
||||
( portMPU_REGION_READ_WRITE ) | /* Read and write. */
|
||||
( prvGetMPURegionSizeSetting( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
}
|
||||
|
||||
lIndex = 0;
|
||||
|
||||
for( ul = 1; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ )
|
||||
{
|
||||
if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL )
|
||||
{
|
||||
/* Translate the generic region definition contained in
|
||||
xRegions into the CM3 specific MPU settings that are then
|
||||
stored in xMPUSettings. */
|
||||
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress =
|
||||
( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) |
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portSTACK_REGION + ul ); /* Region number. */
|
||||
|
||||
xMPUSettings->xRegion[ ul ].ulRegionAttribute =
|
||||
( prvGetMPURegionSizeSetting( xRegions[ lIndex ].ulLengthInBytes ) ) |
|
||||
( xRegions[ lIndex ].ulParameters ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalidate the region. */
|
||||
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( portSTACK_REGION + ul ) | portMPU_REGION_VALID;
|
||||
xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL;
|
||||
}
|
||||
|
||||
lIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
uint8_t ucCurrentPriority;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
|
||||
|
||||
/* Is the interrupt number a user defined interrupt? */
|
||||
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||
{
|
||||
/* Look up the interrupt's priority. */
|
||||
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
an interrupt that has been assigned a priority above
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
function. ISR safe FreeRTOS API functions must *only* be called
|
||||
from interrupts that have been assigned a priority at or below
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
|
||||
Numerically low interrupt priority numbers represent logically high
|
||||
interrupt priorities, therefore the priority of the interrupt must
|
||||
be set to a value equal to or numerically *higher* than
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
|
||||
Interrupts that use the FreeRTOS API must not be left at their
|
||||
default priority of zero as that is the highest possible priority,
|
||||
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||
and therefore also guaranteed to be invalid.
|
||||
|
||||
FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||
interrupt entry is as fast and simple as possible.
|
||||
|
||||
The following links provide detailed information:
|
||||
http://www.freertos.org/RTOS-Cortex-M3-M4.html
|
||||
http://www.freertos.org/FAQHelp.html */
|
||||
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||
}
|
||||
|
||||
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
||||
that define each interrupt's priority to be split between bits that
|
||||
define the interrupt's pre-emption priority bits and bits that define
|
||||
the interrupt's sub-priority. For simplicity all bits must be defined
|
||||
to be pre-emption priority bits. The following assertion will fail if
|
||||
this is not the case (if some bits represent a sub-priority).
|
||||
|
||||
If the application only uses CMSIS libraries for interrupt
|
||||
configuration then the correct setting can be achieved on all Cortex-M
|
||||
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||
scheduler. Note however that some vendor specific peripheral libraries
|
||||
assume a non-zero priority group setting, in which cases using a value
|
||||
of zero will result in unpredicable behaviour. */
|
||||
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||
}
|
||||
|
||||
#endif /* configASSERT_DEFINED */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,332 @@
|
|||
/*
|
||||
FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#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;
|
||||
|
||||
#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
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* MPU specific constants. */
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
|
||||
#define portMPU_REGION_READ_WRITE ( 0x03UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
|
||||
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
|
||||
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 2UL )
|
||||
#define portGENERAL_PERIPHERALS_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
|
||||
#define portSWITCH_TO_USER_MODE() __asm volatile ( " mrs r0, control \n orr r0, #1 \n msr control, r0 " :::"r0" )
|
||||
|
||||
typedef struct MPU_REGION_REGISTERS
|
||||
{
|
||||
uint32_t ulRegionBaseAddress;
|
||||
uint32_t ulRegionAttribute;
|
||||
} xMPU_REGION_REGISTERS;
|
||||
|
||||
/* Plus 1 to create space for the stack region. */
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS ];
|
||||
} xMPU_SETTINGS;
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* SVC numbers for various services. */
|
||||
#define portSVC_START_SCHEDULER 0
|
||||
#define portSVC_YIELD 1
|
||||
#define portSVC_RAISE_PRIVILEGE 2
|
||||
|
||||
/* Scheduler utilities. */
|
||||
|
||||
#define portYIELD() __asm volatile ( " SVC %0 \n" :: "i" (portSVC_YIELD) )
|
||||
#define portYIELD_WITHIN_API() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
\
|
||||
/* Barriers are normally not required but do ensure the code is completely \
|
||||
within the specified behaviour for the architecture. */ \
|
||||
__asm volatile( "dsb" ); \
|
||||
__asm volatile( "isb" ); \
|
||||
}
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
|
||||
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
|
||||
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
not necessary for to use this port. They are defined so the common demo files
|
||||
(which build with all the ports) will build. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Generic helper function. */
|
||||
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
|
||||
{
|
||||
uint8_t ucReturn;
|
||||
|
||||
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) );
|
||||
return ucReturn;
|
||||
}
|
||||
|
||||
/* Check the configuration. */
|
||||
#if( configMAX_PRIORITIES > 32 )
|
||||
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||
#endif
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
|
||||
/* portNOP() is not required by this port. */
|
||||
#define portNOP()
|
||||
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||
#endif
|
||||
|
||||
/* Set the privilege level to user mode if xRunningPrivileged is false. */
|
||||
portFORCE_INLINE static void vPortResetPrivilege( BaseType_t xRunningPrivileged )
|
||||
{
|
||||
if( xRunningPrivileged != pdTRUE )
|
||||
{
|
||||
__asm volatile ( " mrs r0, control \n" \
|
||||
" orr r0, #1 \n" \
|
||||
" msr control, r0 \n" \
|
||||
:::"r0" );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
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 ) );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mov %0, %1 \n" \
|
||||
" msr basepri, %0 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
|
||||
{
|
||||
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
|
||||
|
||||
__asm volatile
|
||||
(
|
||||
" mrs %0, basepri \n" \
|
||||
" mov %1, %2 \n" \
|
||||
" msr basepri, %1 \n" \
|
||||
" isb \n" \
|
||||
" dsb \n" \
|
||||
:"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
|
||||
/* This return will not be reached but is necessary to prevent compiler
|
||||
warnings. */
|
||||
return ulOriginalBASEPRI;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" msr basepri, %0 " :: "r" ( ulNewMaskValue )
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
@ -0,0 +1,654 @@
|
|||
/*
|
||||
FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that has become a de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly and support the FreeRTOS *
|
||||
* project by purchasing a FreeRTOS tutorial book, reference *
|
||||
* manual, or both from: http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* Thank you! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
|
||||
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available from the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* Having a problem? Start by reading the FAQ "My application does *
|
||||
* not run, what could be wrong?" *
|
||||
* *
|
||||
* http://www.FreeRTOS.org/FAQHelp.html *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, books, training, latest versions,
|
||||
license and Real Time Engineers Ltd. contact details.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
|
||||
Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*
|
||||
* A sample implementation of pvPortMalloc() that allows the heap to be defined
|
||||
* across multiple non-contigous blocks and combines (coalescences) adjacent
|
||||
* memory blocks as they are freed.
|
||||
*
|
||||
* See heap_1.c, heap_2.c, heap_3.c and heap_4.c for alternative
|
||||
* implementations, and the memory management pages of http://www.FreeRTOS.org
|
||||
* for more information.
|
||||
*
|
||||
* Usage notes:
|
||||
*
|
||||
* vPortDefineHeapRegions() ***must*** be called before pvPortMalloc().
|
||||
* pvPortMalloc() will be called if any task objects (tasks, queues, event
|
||||
* groups, etc.) are created, therefore vPortDefineHeapRegions() ***must*** be
|
||||
* called before any other objects are defined.
|
||||
*
|
||||
* vPortDefineHeapRegions() takes a single parameter. The parameter is an array
|
||||
* of HeapRegion_t structures. HeapRegion_t is defined in portable.h as
|
||||
*
|
||||
* typedef struct HeapRegion
|
||||
* {
|
||||
* uint8_t *pucStartAddress; << Start address of a block of memory that will be part of the heap.
|
||||
* size_t xSizeInBytes; << Size of the block of memory.
|
||||
* } HeapRegion_t;
|
||||
*
|
||||
* The array is terminated using a NULL zero sized region definition, and the
|
||||
* memory regions defined in the array ***must*** appear in address order from
|
||||
* low address to high address. So the following is a valid example of how
|
||||
* to use the function.
|
||||
*
|
||||
* HeapRegion_t xHeapRegions[] =
|
||||
* {
|
||||
* { ( uint8_t * ) 0x80000000UL, 0x10000 }, << Defines a block of 0x10000 bytes starting at address 0x80000000
|
||||
* { ( uint8_t * ) 0x90000000UL, 0xa0000 }, << Defines a block of 0xa0000 bytes starting at address of 0x90000000
|
||||
* { NULL, 0 } << Terminates the array.
|
||||
* };
|
||||
*
|
||||
* vPortDefineHeapRegions( xHeapRegions ); << Pass the array into vPortDefineHeapRegions().
|
||||
*
|
||||
* Note 0x80000000 is the lower address so appears in the array first.
|
||||
*
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "diag.h"
|
||||
#include "platform_autoconf.h"
|
||||
#include "hal_misc.h"
|
||||
|
||||
/* 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
|
||||
task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Block sizes must not get too small. */
|
||||
#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( uxHeapStructSize << 1 ) )
|
||||
|
||||
/* Assumes 8bit bytes! */
|
||||
#define heapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
|
||||
/* Define the linked list structure. This is used to link free blocks in order
|
||||
of their memory address. */
|
||||
typedef struct A_BLOCK_LINK {
|
||||
struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */
|
||||
size_t xBlockSize; /*<< The size of the free block. */
|
||||
} BlockLink_t;
|
||||
|
||||
static void vPortDefineHeapRegions(const HeapRegion_t * const pxHeapRegions);
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Inserts a block of memory that is being freed into the correct position in
|
||||
* the list of free memory blocks. The block being freed will be merged with
|
||||
* the block in front it and/or the block behind it if the memory blocks are
|
||||
* adjacent to each other.
|
||||
*/
|
||||
static void prvInsertBlockIntoFreeList(BlockLink_t *pxBlockToInsert);
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The size of the structure placed at the beginning of each allocated memory
|
||||
block must by correctly byte aligned. */
|
||||
static const uint32_t uxHeapStructSize = ((sizeof(BlockLink_t)
|
||||
+ ( portBYTE_ALIGNMENT - 1)) & ~portBYTE_ALIGNMENT_MASK);
|
||||
|
||||
/* Create a couple of list links to mark the start and end of the list. */
|
||||
static BlockLink_t xStart, *pxEnd = NULL;
|
||||
|
||||
/* Keeps track of the number of free bytes remaining, but says nothing about
|
||||
fragmentation. */
|
||||
static size_t xFreeBytesRemaining = 0;
|
||||
static size_t xMinimumEverFreeBytesRemaining = 0;
|
||||
|
||||
/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize
|
||||
member of an BlockLink_t structure is set then the block belongs to the
|
||||
application. When the bit is free the block is still part of the free heap
|
||||
space. */
|
||||
//static size_t xBlockAllocatedBit = 0;
|
||||
/* Work out the position of the top bit in a size_t variable. */
|
||||
#define xBlockAllocatedBit (( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ))
|
||||
|
||||
/* Realtek test code start */
|
||||
//TODO: remove section when combine BD and BF
|
||||
#if (defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B))
|
||||
#include "section_config.h"
|
||||
SRAM_HEAP_SECTION
|
||||
#endif
|
||||
unsigned char ucHeap[configTOTAL_HEAP_SIZE];
|
||||
|
||||
//extern void * __sdram_bss_end__;
|
||||
//extern void * __ram_heap1_start__, __ram_heap1_end__, __ram_heap2_start__, __sdram_data_start__;
|
||||
|
||||
extern HeapRegion_t xHeapRegions[];
|
||||
|
||||
#if 0
|
||||
#if defined(CONFIG_PLATFORM_8195A)
|
||||
HeapRegion_t xHeapRegions[] =
|
||||
{
|
||||
{ (uint8_t*)0x10003000, 0x10006000 - 0x10003000}, // __ram_heap1_start__, __ram_heap1_end__ - __ram_heap1_start__
|
||||
{ ucHeap, sizeof(ucHeap)}, // Defines a block from ucHeap
|
||||
#ifdef CONFIG_SDR_EN
|
||||
{ (uint8_t*)&__sdram_bss_end__, 0x80000},
|
||||
#endif
|
||||
{ NULL, 0} // Terminates the array.
|
||||
};
|
||||
#elif (defined CONFIG_PLATFORM_8711B)
|
||||
HeapRegion_t xHeapRegions[] =
|
||||
{
|
||||
{ ucHeap, sizeof(ucHeap)}, // Defines a block from ucHeap
|
||||
{ NULL, 0} // Terminates the array.
|
||||
};
|
||||
#else
|
||||
#error NOT SUPPORT CHIP
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
Dump xBlock list
|
||||
*/
|
||||
void dump_mem_block_list(void) {
|
||||
if (pxEnd == NULL)
|
||||
vPortDefineHeapRegions(xHeapRegions);
|
||||
#if CONFIG_DEBUG_LOG > 1
|
||||
// if(pxEnd == NULL) vPortDefineHeapRegions( xHeapRegions ); // test code start
|
||||
BlockLink_t *pxBlock = &xStart;
|
||||
int count = 0;
|
||||
DBG_8195A("RAM Free Heap Memory List:\n");
|
||||
for (pxBlock = pxBlock->pxNextFreeBlock; pxBlock->pxNextFreeBlock != NULL;
|
||||
pxBlock = pxBlock->pxNextFreeBlock) {
|
||||
DBG_8195A(" [%d]=%p, %d\n", ++count, pxBlock, pxBlock->xBlockSize);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void *pvPortMalloc(size_t xWantedSize) {
|
||||
BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
|
||||
void *pvReturn = NULL;
|
||||
|
||||
/* Realtek test code start */
|
||||
if (pxEnd == NULL)
|
||||
vPortDefineHeapRegions(xHeapRegions);
|
||||
/* Realtek test code end */
|
||||
|
||||
/* The heap must be initialised before the first call to
|
||||
prvPortMalloc(). */
|
||||
configASSERT( pxEnd );
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Check the requested block size is not so large that the top bit is
|
||||
set. The top bit of the block size member of the BlockLink_t structure
|
||||
is used to determine who owns the block - the application or the
|
||||
kernel, so it must be free. */
|
||||
if ((xWantedSize & xBlockAllocatedBit) == 0) {
|
||||
/* The wanted size is increased so it can contain a BlockLink_t
|
||||
structure in addition to the requested amount of bytes. */
|
||||
if (xWantedSize > 0) {
|
||||
xWantedSize += uxHeapStructSize;
|
||||
|
||||
/* Ensure that blocks are always aligned to the required number
|
||||
of bytes. */
|
||||
if ((xWantedSize & portBYTE_ALIGNMENT_MASK) != 0x00) {
|
||||
/* Byte alignment required. */
|
||||
xWantedSize += ( portBYTE_ALIGNMENT
|
||||
- (xWantedSize & portBYTE_ALIGNMENT_MASK));
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if ((xWantedSize > 0) && (xWantedSize <= xFreeBytesRemaining)) {
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
while ((pxBlock->xBlockSize < xWantedSize)
|
||||
&& (pxBlock->pxNextFreeBlock != NULL)) {
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the end marker was reached then a block of adequate size
|
||||
was not found. */
|
||||
if (pxBlock != pxEnd) {
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
BlockLink_t structure at its start. */
|
||||
pvReturn =
|
||||
(void *) (((uint8_t *) pxPreviousBlock->pxNextFreeBlock)
|
||||
+ uxHeapStructSize);
|
||||
|
||||
/* This block is being returned for use so must be taken out
|
||||
of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
|
||||
/* If the block is larger than required it can be split into
|
||||
two. */
|
||||
if ((pxBlock->xBlockSize - xWantedSize)
|
||||
> heapMINIMUM_BLOCK_SIZE) {
|
||||
/* This block is to be split into two. Create a new
|
||||
block following the number of bytes requested. The void
|
||||
cast is used to prevent byte alignment warnings from the
|
||||
compiler. */
|
||||
pxNewBlockLink = (void *) (((uint8_t *) pxBlock)
|
||||
+ xWantedSize);
|
||||
|
||||
/* Calculate the sizes of two blocks split from the
|
||||
single block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize
|
||||
- xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
prvInsertBlockIntoFreeList((pxNewBlockLink));
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
|
||||
if (xFreeBytesRemaining < xMinimumEverFreeBytesRemaining) {
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The block is being returned - it is allocated and owned
|
||||
by the application and has no "next" block. */
|
||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
} traceMALLOC( pvReturn, xWantedSize );
|
||||
}
|
||||
(void) xTaskResumeAll();
|
||||
if (pvReturn == NULL) {
|
||||
DBG_RAM_HEAP_WARN("ram_alloc(%d): freeSpace(%d)!\n", xWantedSize,
|
||||
xFreeBytesRemaining);
|
||||
} else {
|
||||
// DBG_RAM_HEAP_INFO("ram_alloc:%p[%d]\n", pvReturn , xWantedSize);
|
||||
}
|
||||
#if( configUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
extern void vApplicationMallocFailedHook( void );
|
||||
vApplicationMallocFailedHook();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void __vPortFree(void *pv) {
|
||||
uint8_t *puc = (uint8_t *) pv;
|
||||
BlockLink_t *pxLink;
|
||||
|
||||
if (pv != NULL) {
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
before it. */
|
||||
puc -= uxHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = (void *) puc;
|
||||
|
||||
/* Check the block is actually allocated. */
|
||||
configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); configASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
|
||||
if ((pxLink->xBlockSize & xBlockAllocatedBit) != 0) {
|
||||
if (pxLink->pxNextFreeBlock == NULL) {
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
allocated. */
|
||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
prvInsertBlockIntoFreeList(((BlockLink_t *) pxLink));
|
||||
}
|
||||
(void) xTaskResumeAll();
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
// DBG_RAM_HEAP_INFO("ram_free:%p[%d]\n", pv , pxLink->xBlockSize);
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
/* Add by Alfa 2015/02/04 -----------------------------------*/
|
||||
static void (*ext_free)(void *p) = NULL;
|
||||
//static
|
||||
uint32_t ext_upper = 0;
|
||||
//static
|
||||
uint32_t ext_lower = 0;
|
||||
void vPortSetExtFree(void (*free)(void *p), uint32_t upper, uint32_t lower) {
|
||||
ext_free = free;
|
||||
ext_upper = upper;
|
||||
ext_lower = lower;
|
||||
}
|
||||
|
||||
void vPortFree(void *pv) {
|
||||
if (((uint32_t) pv >= ext_lower) && ((uint32_t) pv < ext_upper)) {
|
||||
// use external free function
|
||||
if (ext_free)
|
||||
ext_free(pv);
|
||||
} else
|
||||
__vPortFree(pv);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetFreeHeapSize(void) {
|
||||
return xFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetMinimumEverFreeHeapSize(void) {
|
||||
return xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInsertBlockIntoFreeList(BlockLink_t *pxBlockToInsert) {
|
||||
BlockLink_t *pxIterator;
|
||||
uint8_t *puc;
|
||||
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
than the block being inserted. */
|
||||
for (pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert;
|
||||
pxIterator = pxIterator->pxNextFreeBlock) {
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
make a contiguous block of memory? */
|
||||
puc = (uint8_t *) pxIterator;
|
||||
if ((puc + pxIterator->xBlockSize) == (uint8_t *) pxBlockToInsert) {
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
make a contiguous block of memory? */
|
||||
puc = (uint8_t *) pxBlockToInsert;
|
||||
if ((puc + pxBlockToInsert->xBlockSize)
|
||||
== (uint8_t *) pxIterator->pxNextFreeBlock) {
|
||||
if (pxIterator->pxNextFreeBlock != pxEnd) {
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize +=
|
||||
pxIterator->pxNextFreeBlock->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock =
|
||||
pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||
} else {
|
||||
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||
}
|
||||
} else {
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gab, so was merged with the block
|
||||
before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
already been set, and should not be set here as that would make it point
|
||||
to itself. */
|
||||
if (pxIterator != pxBlockToInsert) {
|
||||
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||
} else {
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
static void vPortDefineHeapRegions(const HeapRegion_t * const pxHeapRegions) {
|
||||
BlockLink_t *pxFirstFreeBlockInRegion = NULL, *pxPreviousFreeBlock;
|
||||
uint8_t *pucAlignedHeap;
|
||||
size_t xTotalRegionSize, xTotalHeapSize = 0;
|
||||
BaseType_t xDefinedRegions = 0;
|
||||
uint32_t ulAddress;
|
||||
const HeapRegion_t *pxHeapRegion;
|
||||
|
||||
#if defined(CONFIG_PLATFORM_8195A)
|
||||
/*
|
||||
xHeapRegions[0].pucStartAddress = (uint8_t*)&__ram_heap1_start__;
|
||||
xHeapRegions[0].xSizeInBytes = (u32)&__ram_heap1_end__ - (u32)xHeapRegions[0].pucStartAddress;
|
||||
xHeapRegions[1].pucStartAddress = &ucHeap; // (uint8_t*)&__ram_heap2_start__;
|
||||
xHeapRegions[1].xSizeInBytes = (u32)0x10070000 - (u32)xHeapRegions[1].pucStartAddress;
|
||||
xHeapRegions[2].pucStartAddress = (uint8_t*)&__sdram_data_start__;
|
||||
xHeapRegions[2].xSizeInBytes = (u32)0x30200000 - (u32)xHeapRegions[2].pucStartAddress;
|
||||
*/
|
||||
#endif
|
||||
/* Can only call once! */
|
||||
configASSERT( pxEnd == NULL );
|
||||
|
||||
pxHeapRegion = &(pxHeapRegions[xDefinedRegions]);
|
||||
|
||||
uint8 chip_id = HalGetChipId();
|
||||
while (pxHeapRegion->xSizeInBytes > 0) {
|
||||
if (pxHeapRegion->pucStartAddress
|
||||
> (uint8_t *) 0x20000000 && chip_id >= CHIP_ID_8711AN && chip_id <= CHIP_ID_8711AF) {
|
||||
// pxHeapRegion->pucStartAddress = 0;
|
||||
// pxHeapRegion->xSizeInBytes = 0;
|
||||
// DBG_8195A("ChipID: %p !\n", chip_id);
|
||||
} else {
|
||||
#if CONFIG_DEBUG_LOG > 2
|
||||
DBG_8195A("Init Heap Region: %p[%d]\n", pxHeapRegion->pucStartAddress, pxHeapRegion->xSizeInBytes);
|
||||
#endif
|
||||
#if CONFIG_DEBUG_LOG > 4
|
||||
rtl_memset(pxHeapRegion->pucStartAddress, 0, pxHeapRegion->xSizeInBytes);
|
||||
#endif
|
||||
xTotalRegionSize = pxHeapRegion->xSizeInBytes;
|
||||
/* Ensure the heap region starts on a correctly aligned boundary. */
|
||||
ulAddress = (uint32_t) pxHeapRegion->pucStartAddress;
|
||||
if ((ulAddress & portBYTE_ALIGNMENT_MASK) != 0) {
|
||||
ulAddress += ( portBYTE_ALIGNMENT - 1);
|
||||
ulAddress &= ~portBYTE_ALIGNMENT_MASK;
|
||||
|
||||
/* Adjust the size for the bytes lost to alignment. */
|
||||
xTotalRegionSize -= ulAddress
|
||||
- (uint32_t) pxHeapRegion->pucStartAddress;
|
||||
}
|
||||
|
||||
pucAlignedHeap = (uint8_t *) ulAddress;
|
||||
|
||||
/* Set xStart if it has not already been set. */
|
||||
if (xDefinedRegions == 0) {
|
||||
/* xStart is used to hold a pointer to the first item in the list of
|
||||
free blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = (BlockLink_t *) pucAlignedHeap;
|
||||
xStart.xBlockSize = (size_t) 0;
|
||||
} else {
|
||||
/* Should only get here if one region has already been added to the
|
||||
heap. */
|
||||
configASSERT( pxEnd != NULL );
|
||||
|
||||
/* Check blocks are passed in with increasing start addresses. */
|
||||
configASSERT( ulAddress > ( uint32_t ) pxEnd );
|
||||
}
|
||||
|
||||
/* Remember the location of the end marker in the previous region, if
|
||||
any. */
|
||||
pxPreviousFreeBlock = pxEnd;
|
||||
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is
|
||||
inserted at the end of the region space. */
|
||||
ulAddress = ((uint32_t) pucAlignedHeap) + xTotalRegionSize;
|
||||
ulAddress -= uxHeapStructSize;
|
||||
ulAddress &= ~portBYTE_ALIGNMENT_MASK;
|
||||
pxEnd = (BlockLink_t *) ulAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = NULL;
|
||||
|
||||
/* To start with there is a single free block in this region that is
|
||||
sized to take up the entire heap region minus the space taken by the
|
||||
free block structure. */
|
||||
pxFirstFreeBlockInRegion = (BlockLink_t *) pucAlignedHeap;
|
||||
pxFirstFreeBlockInRegion->xBlockSize = ulAddress
|
||||
- (uint32_t) pxFirstFreeBlockInRegion;
|
||||
pxFirstFreeBlockInRegion->pxNextFreeBlock = pxEnd;
|
||||
|
||||
/* If this is not the first region that makes up the entire heap space
|
||||
then link the previous region to this region. */
|
||||
if (pxPreviousFreeBlock != NULL) {
|
||||
pxPreviousFreeBlock->pxNextFreeBlock = pxFirstFreeBlockInRegion;
|
||||
}
|
||||
|
||||
xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize;
|
||||
}
|
||||
/* Move onto the next HeapRegion_t structure. */
|
||||
xDefinedRegions++;
|
||||
pxHeapRegion = &(pxHeapRegions[xDefinedRegions]);
|
||||
}
|
||||
|
||||
xMinimumEverFreeBytesRemaining = xTotalHeapSize;
|
||||
xFreeBytesRemaining = xTotalHeapSize;
|
||||
|
||||
/* Check something was actually defined before it is accessed. */
|
||||
configASSERT( xTotalHeapSize );
|
||||
|
||||
}
|
||||
|
||||
extern _LONG_CALL_ void * __rtl_memcpy_v1_00(void * __restrict dst0 , const void * __restrict src0 , size_t len0);
|
||||
|
||||
void* pvPortReAlloc(void *pv, size_t xWantedSize) {
|
||||
BlockLink_t *pxLink;
|
||||
|
||||
if (((uint32_t) pv >= ext_lower) && ((uint32_t) pv < ext_upper)) {
|
||||
if (ext_free)
|
||||
ext_free(pv);
|
||||
pv = NULL;
|
||||
}
|
||||
|
||||
unsigned char *puc = (unsigned char *) pv;
|
||||
|
||||
if (pv) {
|
||||
if (!xWantedSize) {
|
||||
vPortFree(pv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *newArea = pvPortMalloc(xWantedSize);
|
||||
if (newArea) {
|
||||
/* The memory being freed will have an xBlockLink structure immediately
|
||||
before it. */
|
||||
puc -= uxHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = (void *) puc;
|
||||
|
||||
int oldSize = (pxLink->xBlockSize & ~xBlockAllocatedBit) - uxHeapStructSize;
|
||||
int copySize = (oldSize < xWantedSize) ? oldSize : xWantedSize;
|
||||
__rtl_memcpy_v1_00(newArea, pv, copySize);
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
prvInsertBlockIntoFreeList(((BlockLink_t *) pxLink));
|
||||
}
|
||||
xTaskResumeAll();
|
||||
return newArea;
|
||||
}
|
||||
} else if (xWantedSize)
|
||||
return pvPortMalloc(xWantedSize);
|
||||
else
|
||||
return NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern _LONG_CALL_ROM_ void *_memset(void *s, int c, SIZE_T n);
|
||||
|
||||
void *pvPortZalloc(size_t xWantedSize) {
|
||||
void * prt = pvPortMalloc(xWantedSize);
|
||||
if (prt)
|
||||
_memset(prt, 0, xWantedSize);
|
||||
return prt;
|
||||
}
|
||||
|
||||
/*
|
||||
#ifdef ARDUINO_SDK
|
||||
int vPortAddHeapRegion(uint8_t *addr, size_t size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
2567
Firmware/RTLGDB/USDK/component/os/freertos/freertos/Source/queue.c
Normal file
2567
Firmware/RTLGDB/USDK/component/os/freertos/freertos/Source/queue.c
Normal file
File diff suppressed because it is too large
Load diff
4933
Firmware/RTLGDB/USDK/component/os/freertos/freertos/Source/tasks.c
Normal file
4933
Firmware/RTLGDB/USDK/component/os/freertos/freertos/Source/tasks.c
Normal file
File diff suppressed because it is too large
Load diff
1092
Firmware/RTLGDB/USDK/component/os/freertos/freertos/Source/timers.c
Normal file
1092
Firmware/RTLGDB/USDK/component/os/freertos/freertos/Source/timers.c
Normal file
File diff suppressed because it is too large
Load diff
155
Firmware/RTLGDB/USDK/component/os/freertos/freertos_pmu.h
Normal file
155
Firmware/RTLGDB/USDK/component/os/freertos/freertos_pmu.h
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
#ifndef __FREERTOS_PMU_H_
|
||||
#define __FREERTOS_PMU_H_
|
||||
|
||||
#ifdef CONFIG_PLATFORM_8195A
|
||||
#include "sleep_ex_api.h"
|
||||
#endif
|
||||
|
||||
#ifndef BIT
|
||||
#define BIT(n) (1<<n)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PLATFORM_8195A
|
||||
#define DEFAULT_WAKEUP_EVENT (SLEEP_WAKEUP_BY_STIMER | SLEEP_WAKEUP_BY_GTIMER | SLEEP_WAKEUP_BY_GPIO_INT | SLEEP_WAKEUP_BY_WLAN)
|
||||
|
||||
typedef enum PMU_DEVICE {
|
||||
|
||||
PMU_OS = 0,
|
||||
PMU_WLAN_DEVICE = 1,
|
||||
PMU_LOGUART_DEVICE = 2,
|
||||
PMU_SDIO_DEVICE = 3,
|
||||
|
||||
PMU_DEV_USER_BASE= 16,
|
||||
|
||||
PMU_MAX = 31
|
||||
|
||||
} PMU_DEVICE;
|
||||
|
||||
#ifndef BIT
|
||||
#define BIT(n) (1<<n)
|
||||
#endif
|
||||
// wakelock for system usage
|
||||
#define WAKELOCK_OS BIT(PMU_OS)
|
||||
#define WAKELOCK_WLAN BIT(PMU_WLAN_DEVICE)
|
||||
#define WAKELOCK_LOGUART BIT(PMU_LOGUART_DEVICE)
|
||||
#define WAKELOCK_SDIO_DEVICE BIT(PMU_SDIO_DEVICE)
|
||||
|
||||
// wakelock for user defined
|
||||
#define WAKELOCK_USER_BASE BIT(PMU_DEV_USER_BASE)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PLATFORM_8711B
|
||||
typedef enum {
|
||||
PMU_OS =0,
|
||||
PMU_WLAN_DEVICE =1,
|
||||
PMU_LOGUART_DEVICE =2,
|
||||
PMU_SDIO_DEVICE =3,
|
||||
|
||||
PMU_UART0_DEVICE =4,
|
||||
PMU_UART1_DEVICE =5,
|
||||
PMU_I2C0_DEVICE =6,
|
||||
PMU_I2C1_DEVICE =7,
|
||||
PMU_USOC_DEVICE =8,
|
||||
PMU_DONGLE_DEVICE =9,
|
||||
PMU_RTC_DEVICE =10,
|
||||
PMU_CONSOL_DEVICE =11,
|
||||
PMU_ADC_DEVICE =12,
|
||||
PMU_DEV_USER_BASE =16,
|
||||
|
||||
PMU_MAX =31
|
||||
} PMU_DEVICE;
|
||||
|
||||
enum SLEEP_TYPE {
|
||||
SLEEP_PG = 0,
|
||||
SLEEP_CG = 1,
|
||||
};
|
||||
#endif
|
||||
|
||||
// default locked by OS and not to sleep until OS release wakelock in somewhere
|
||||
#define DEFAULT_WAKELOCK (BIT(PMU_OS))
|
||||
|
||||
typedef uint32_t (*PSM_HOOK_FUN)( unsigned int, void* param_ptr );
|
||||
|
||||
/** Acquire wakelock
|
||||
*
|
||||
* A wakelock is a 32-bit map. Each module own 1 bit in this bit map.
|
||||
* FreeRTOS tickless reference the wakelock and decide that if it can or cannot enter sleep state.
|
||||
* If any module acquire and hold a bit in wakelock, then the whole system won't enter sleep state.
|
||||
*
|
||||
* If wakelock is not equals to 0, then the system won't enter sleep.
|
||||
*
|
||||
* @param nDeviceId : The bit which is attempt to add into wakelock
|
||||
*/
|
||||
//void pmu_acquire_wakelock(uint32_t nDeviceId);
|
||||
void acquire_wakelock(uint32_t flg);
|
||||
#define pmu_acquire_wakelock(nDeviceId) acquire_wakelock(1<<(nDeviceId))
|
||||
|
||||
/** Release wakelock
|
||||
*
|
||||
* If wakelock equals to 0, then the system may enter sleep state if it is in idle state.
|
||||
*
|
||||
* @param nDeviceId : The bit which is attempt to remove from wakelock
|
||||
*/
|
||||
//void pmu_release_wakelock(uint32_t nDeviceId);
|
||||
void release_wakelock(uint32_t flg);
|
||||
#define pmu_release_wakelock(nDeviceId) release_wakelock(1<<(nDeviceId))
|
||||
|
||||
/** Get current wakelock bit map value
|
||||
*
|
||||
* @return : the current wakelock bit map value
|
||||
*/
|
||||
//uint32_t pmu_get_wakelock_status(void);
|
||||
uint32_t get_wakelock_status(void);
|
||||
#define pmu_get_wakelock_status get_wakelock_status
|
||||
|
||||
#if (configGENERATE_RUN_TIME_STATS == 1)
|
||||
|
||||
/** enable to keep wakelock stats
|
||||
*
|
||||
*/
|
||||
void pmu_enable_wakelock_stats( unsigned char enable );
|
||||
|
||||
/** Get text report that contain the statics of wakelock holding time
|
||||
*
|
||||
* Each time a module acquries or releases wakelock, a holding time is calculated and sum up to a table.
|
||||
* It is for debug that which module is power saving killer.
|
||||
*
|
||||
* @param pcWriteBuffer : The char buffer that contain the report
|
||||
*/
|
||||
void pmu_get_wakelock_hold_stats( char *pcWriteBuffer );
|
||||
|
||||
/** Recalculate the wakelock statics
|
||||
*
|
||||
* By default the wakelock statics is calculated from system boot up.
|
||||
* If we want to debug power saving killer from a specified timestamp, we can reset the statics.
|
||||
*/
|
||||
void pmu_clean_wakelock_stat(void);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief set system active time, system can not sleep beore timeout.
|
||||
* @param nDeviceId: PMU_DEVICE
|
||||
* @param timeout: system can not sleep beore timeout, unit is ms.
|
||||
* @retval status value:
|
||||
* - 0: _FAIL
|
||||
* - 1: _SUCCESS
|
||||
*/
|
||||
uint32_t pmu_set_sysactive_time(uint32_t nDeviceId, uint32_t timeout);
|
||||
|
||||
void pmu_add_wakeup_event(uint32_t event);
|
||||
void pmu_del_wakeup_event(uint32_t event);
|
||||
|
||||
void pmu_register_sleep_callback(uint32_t nDeviceId, PSM_HOOK_FUN sleep_hook_fun, void* sleep_param_ptr, PSM_HOOK_FUN wakeup_hook_fun, void* wakeup_param_ptr);
|
||||
void pmu_unregister_sleep_callback(uint32_t nDeviceId);
|
||||
|
||||
#ifdef CONFIG_PLATFORM_8195A
|
||||
/** Set PLL reserved or not when sleep is called
|
||||
*
|
||||
* @param reserve: true for sleep with PLL reserve
|
||||
*/
|
||||
void pmu_set_pll_reserved(unsigned char reserve);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
894
Firmware/RTLGDB/USDK/component/os/freertos/freertos_service.c
Normal file
894
Firmware/RTLGDB/USDK/component/os/freertos/freertos_service.c
Normal file
|
|
@ -0,0 +1,894 @@
|
|||
/* FreeRTOS includes */
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#include <timers.h>
|
||||
#include <semphr.h>
|
||||
//#include <autoconf.h>
|
||||
#include <osdep_service.h>
|
||||
#include <stdio.h>
|
||||
#include <freertos_pmu.h>
|
||||
#include <tcm_heap.h>
|
||||
#include <netdev.h>
|
||||
/********************* os depended utilities ********************/
|
||||
|
||||
#ifndef USE_MUTEX_FOR_SPINLOCK
|
||||
#define USE_MUTEX_FOR_SPINLOCK 1
|
||||
#endif
|
||||
|
||||
//----- ------------------------------------------------------------------
|
||||
// Misc Function
|
||||
//----- ------------------------------------------------------------------
|
||||
|
||||
void save_and_cli()
|
||||
{
|
||||
taskENTER_CRITICAL();
|
||||
}
|
||||
|
||||
void restore_flags()
|
||||
{
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
void cli()
|
||||
{
|
||||
taskDISABLE_INTERRUPTS();
|
||||
}
|
||||
|
||||
/* Not needed on 64bit architectures */
|
||||
static unsigned int __div64_32(uint64_t *n, unsigned int base)
|
||||
{
|
||||
uint64_t rem = *n;
|
||||
uint64_t b = base;
|
||||
uint64_t res, d = 1;
|
||||
unsigned int high = rem >> 32;
|
||||
|
||||
/* Reduce the thing a bit first */
|
||||
res = 0;
|
||||
if (high >= base) {
|
||||
high /= base;
|
||||
res = (uint64_t) high << 32;
|
||||
rem -= (uint64_t) (high * base) << 32;
|
||||
}
|
||||
|
||||
while ((uint64_t)b > 0 && b < rem) {
|
||||
b = b+b;
|
||||
d = d+d;
|
||||
}
|
||||
|
||||
do {
|
||||
if (rem >= b) {
|
||||
rem -= b;
|
||||
res += d;
|
||||
}
|
||||
b >>= 1;
|
||||
d >>= 1;
|
||||
} while (d);
|
||||
|
||||
*n = res;
|
||||
return rem;
|
||||
}
|
||||
|
||||
/********************* os depended service ********************/
|
||||
|
||||
uint8_t* _freertos_malloc(uint32_t sz)
|
||||
{
|
||||
return pvPortMalloc(sz);
|
||||
}
|
||||
|
||||
uint8_t* _freertos_zmalloc(uint32_t sz)
|
||||
{
|
||||
uint8_t *pbuf = _freertos_malloc(sz);
|
||||
|
||||
if (pbuf != NULL)
|
||||
memset(pbuf, 0, sz);
|
||||
|
||||
return pbuf;
|
||||
}
|
||||
|
||||
void _freertos_mfree(uint8_t *pbuf, uint32_t sz)
|
||||
{
|
||||
vPortFree(pbuf);
|
||||
}
|
||||
|
||||
static void _freertos_memcpy(void* dst, void* src, uint32_t sz)
|
||||
{
|
||||
memcpy(dst, src, sz);
|
||||
}
|
||||
|
||||
static int _freertos_memcmp(void *dst, void *src, uint32_t sz)
|
||||
{
|
||||
//under Linux/GNU/GLibc, the return value of memcmp for two same mem. chunk is 0
|
||||
if (!(memcmp(dst, src, sz)))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _freertos_memset(void *pbuf, int c, uint32_t sz)
|
||||
{
|
||||
memset(pbuf, c, sz);
|
||||
}
|
||||
|
||||
static void _freertos_init_sema(_sema *sema, int init_val)
|
||||
{
|
||||
*sema = xSemaphoreCreateCounting(0xffffffff, init_val); //Set max count 0xffffffff
|
||||
}
|
||||
|
||||
static void _freertos_free_sema(_sema *sema)
|
||||
{
|
||||
if(*sema != NULL)
|
||||
vSemaphoreDelete(*sema);
|
||||
|
||||
*sema = NULL;
|
||||
}
|
||||
|
||||
static void _freertos_up_sema(_sema *sema)
|
||||
{
|
||||
xSemaphoreGive(*sema);
|
||||
}
|
||||
|
||||
static void _freertos_up_sema_from_isr(_sema *sema)
|
||||
{
|
||||
portBASE_TYPE taskWoken = pdFALSE;
|
||||
xSemaphoreGiveFromISR(*sema, &taskWoken);
|
||||
portEND_SWITCHING_ISR(taskWoken);
|
||||
}
|
||||
|
||||
static uint32_t _freertos_down_sema(_sema *sema, uint32_t timeout)
|
||||
{
|
||||
if(timeout == RTW_MAX_DELAY) {
|
||||
timeout = portMAX_DELAY;
|
||||
} else {
|
||||
timeout = rtw_ms_to_systime(timeout);
|
||||
}
|
||||
|
||||
if(xSemaphoreTake(*sema, timeout) != pdTRUE) {
|
||||
return pdFALSE;
|
||||
}
|
||||
|
||||
return pdTRUE;
|
||||
}
|
||||
|
||||
static void _freertos_mutex_init(_mutex *pmutex)
|
||||
{
|
||||
*pmutex = xSemaphoreCreateMutex();
|
||||
}
|
||||
|
||||
static void _freertos_mutex_free(_mutex *pmutex)
|
||||
{
|
||||
if(*pmutex != NULL)
|
||||
vSemaphoreDelete(*pmutex);
|
||||
|
||||
*pmutex = NULL;
|
||||
}
|
||||
|
||||
static void _freertos_mutex_get(_lock *plock)
|
||||
{
|
||||
while(xSemaphoreTake(*plock, 60 * 1000 / portTICK_RATE_MS) != pdTRUE)
|
||||
DBG_ERR("[%s] %s(%p) failed, retry\n", pcTaskGetTaskName(NULL), __FUNCTION__, plock);
|
||||
}
|
||||
|
||||
static int _freertos_mutex_get_timeout(_lock *plock, uint32_t timeout_ms)
|
||||
{
|
||||
if(xSemaphoreTake(*plock, timeout_ms / portTICK_RATE_MS) != pdTRUE){
|
||||
DBG_ERR("[%s] %s(%p) failed, retry\n", pcTaskGetTaskName(NULL), __FUNCTION__, plock);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _freertos_mutex_put(_lock *plock)
|
||||
{
|
||||
xSemaphoreGive(*plock);
|
||||
}
|
||||
|
||||
static void _freertos_enter_critical(_lock *plock, _irqL *pirqL)
|
||||
{
|
||||
taskENTER_CRITICAL();
|
||||
}
|
||||
|
||||
static void _freertos_exit_critical(_lock *plock, _irqL *pirqL)
|
||||
{
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
static uint32_t uxSavedInterruptStatus = 0;
|
||||
static void _freertos_enter_critical_from_isr(_lock *plock, _irqL *pirqL)
|
||||
{
|
||||
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
|
||||
|
||||
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
}
|
||||
|
||||
static void _freertos_exit_critical_from_isr(_lock *plock, _irqL *pirqL)
|
||||
{
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
|
||||
}
|
||||
|
||||
static int _freertos_enter_critical_mutex(_mutex *pmutex, _irqL *pirqL)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
while(xSemaphoreTake(*pmutex, 60 * 1000 / portTICK_RATE_MS) != pdTRUE)
|
||||
printf("\n\r[%s] %s(%p) failed, retry\n", pcTaskGetTaskName(NULL), __FUNCTION__, pmutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void _freertos_exit_critical_mutex(_mutex *pmutex, _irqL *pirqL)
|
||||
{
|
||||
xSemaphoreGive(*pmutex);
|
||||
}
|
||||
|
||||
static void _freertos_spinlock_init(_lock *plock)
|
||||
{
|
||||
#if USE_MUTEX_FOR_SPINLOCK
|
||||
*plock = xSemaphoreCreateMutex();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _freertos_spinlock_free(_lock *plock)
|
||||
{
|
||||
#if USE_MUTEX_FOR_SPINLOCK
|
||||
if(*plock != NULL)
|
||||
vSemaphoreDelete(*plock);
|
||||
|
||||
*plock = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _freertos_spinlock(_lock *plock)
|
||||
{
|
||||
#if USE_MUTEX_FOR_SPINLOCK
|
||||
while(xSemaphoreTake(*plock, 60 * 1000 / portTICK_RATE_MS) != pdTRUE)
|
||||
DBG_ERR("[%s] %s(%p) failed, retry\n", pcTaskGetTaskName(NULL), __FUNCTION__, plock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _freertos_spinunlock(_lock *plock)
|
||||
{
|
||||
#if USE_MUTEX_FOR_SPINLOCK
|
||||
xSemaphoreGive(*plock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _freertos_spinlock_irqsave(_lock *plock, _irqL *irqL)
|
||||
{
|
||||
taskENTER_CRITICAL();
|
||||
#if USE_MUTEX_FOR_SPINLOCK
|
||||
while(xSemaphoreTake(*plock, 60 * 1000 / portTICK_RATE_MS) != pdTRUE)
|
||||
DBG_ERR("[%s] %s(%p) failed, retry\n", pcTaskGetTaskName(NULL), __FUNCTION__, plock);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _freertos_spinunlock_irqsave(_lock *plock, _irqL *irqL)
|
||||
{
|
||||
#if USE_MUTEX_FOR_SPINLOCK
|
||||
xSemaphoreGive(*plock);
|
||||
#endif
|
||||
taskEXIT_CRITICAL();
|
||||
}
|
||||
|
||||
static int _freertos_init_xqueue( _xqueue* queue, const char* name, uint32_t message_size, uint32_t number_of_messages )
|
||||
{
|
||||
if ( ( *queue = xQueueCreate( number_of_messages, message_size ) ) == NULL )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _freertos_push_to_xqueue( _xqueue* queue, void* message, uint32_t timeout_ms )
|
||||
{
|
||||
if(timeout_ms == RTW_MAX_DELAY) {
|
||||
timeout_ms = portMAX_DELAY;
|
||||
} else {
|
||||
timeout_ms = rtw_ms_to_systime(timeout_ms);
|
||||
}
|
||||
|
||||
if ( xQueueSendToBack( *queue, message, timeout_ms ) != pdPASS )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _freertos_pop_from_xqueue( _xqueue* queue, void* message, uint32_t timeout_ms )
|
||||
{
|
||||
if(timeout_ms == RTW_WAIT_FOREVER) {
|
||||
timeout_ms = portMAX_DELAY;
|
||||
} else {
|
||||
timeout_ms = rtw_ms_to_systime(timeout_ms);
|
||||
}
|
||||
|
||||
if ( xQueueReceive( *queue, message, timeout_ms ) != pdPASS )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _freertos_deinit_xqueue( _xqueue* queue )
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if( uxQueueMessagesWaiting( queue ) )
|
||||
{
|
||||
result = -1;
|
||||
}
|
||||
vQueueDelete( *queue );
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t _freertos_get_current_time(void)
|
||||
{
|
||||
return xTaskGetTickCount(); //The count of ticks since vTaskStartScheduler was called.
|
||||
}
|
||||
|
||||
static uint32_t _freertos_systime_to_ms(uint32_t systime)
|
||||
{
|
||||
return systime * portTICK_RATE_MS;
|
||||
}
|
||||
|
||||
static uint32_t _freertos_systime_to_sec(uint32_t systime)
|
||||
{
|
||||
return systime / configTICK_RATE_HZ;
|
||||
}
|
||||
|
||||
static uint32_t _freertos_ms_to_systime(uint32_t ms)
|
||||
{
|
||||
return ms / portTICK_RATE_MS;
|
||||
}
|
||||
|
||||
static uint32_t _freertos_sec_to_systime(uint32_t sec)
|
||||
{
|
||||
return sec * configTICK_RATE_HZ;
|
||||
}
|
||||
|
||||
static void _freertos_msleep_os(int ms)
|
||||
{
|
||||
#if defined(CONFIG_PLATFORM_8195A)
|
||||
vTaskDelay(ms / portTICK_RATE_MS);
|
||||
#elif defined(CONFIG_PLATFORM_8711B)
|
||||
if (pmu_yield_os_check()) {
|
||||
vTaskDelay(ms / portTICK_RATE_MS);
|
||||
} else {
|
||||
DelayMs(ms);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
extern void wait_us(int us); // До 2.147483648 секунды!
|
||||
|
||||
static void _freertos_usleep_os(int us)
|
||||
{
|
||||
#if defined(STM32F2XX) || defined(STM32F4XX) || defined(STM32F10X_XL)
|
||||
// FreeRTOS does not provide us level delay. Use busy wait
|
||||
WLAN_BSP_UsLoop(us);
|
||||
#elif defined(CONFIG_PLATFORM_8195A)
|
||||
wait_us(us);
|
||||
//DBG_ERR("%s: Please Implement micro-second delay\n", __FUNCTION__);
|
||||
#elif defined(CONFIG_PLATFORM_8711B)
|
||||
DelayUs(us);
|
||||
#else
|
||||
#error "Please implement hardware dependent micro second level sleep here"
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _freertos_mdelay_os(int ms)
|
||||
{
|
||||
vTaskDelay(ms / portTICK_RATE_MS);
|
||||
}
|
||||
|
||||
static void _freertos_udelay_os(int us)
|
||||
{
|
||||
#if defined(STM32F2XX) || defined(STM32F4XX) || defined(STM32F10X_XL)
|
||||
// FreeRTOS does not provide us level delay. Use busy wait
|
||||
WLAN_BSP_UsLoop(us);
|
||||
#elif defined(CONFIG_PLATFORM_8195A)
|
||||
// HalDelayUs(us);
|
||||
wait_us(us);
|
||||
#elif defined(CONFIG_PLATFORM_8711B)
|
||||
DelayUs(us);
|
||||
#else
|
||||
#error "Please implement hardware dependent micro second level sleep here"
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _freertos_yield_os(void)
|
||||
{
|
||||
#if defined(CONFIG_PLATFORM_8195A)
|
||||
taskYIELD();
|
||||
#elif defined(CONFIG_PLATFORM_8711B)
|
||||
if (pmu_yield_os_check()) {
|
||||
taskYIELD();
|
||||
} else {
|
||||
DelayMs(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void _freertos_ATOMIC_SET(ATOMIC_T *v, int i)
|
||||
{
|
||||
atomic_set(v,i);
|
||||
}
|
||||
|
||||
static int _freertos_ATOMIC_READ(ATOMIC_T *v)
|
||||
{
|
||||
return atomic_read(v);
|
||||
}
|
||||
|
||||
static void _freertos_ATOMIC_ADD(ATOMIC_T *v, int i)
|
||||
{
|
||||
save_and_cli();
|
||||
v->counter += i;
|
||||
restore_flags();
|
||||
}
|
||||
|
||||
static void _freertos_ATOMIC_SUB(ATOMIC_T *v, int i)
|
||||
{
|
||||
save_and_cli();
|
||||
v->counter -= i;
|
||||
restore_flags();
|
||||
}
|
||||
|
||||
static void _freertos_ATOMIC_INC(ATOMIC_T *v)
|
||||
{
|
||||
_freertos_ATOMIC_ADD(v, 1);
|
||||
}
|
||||
|
||||
static void _freertos_ATOMIC_DEC(ATOMIC_T *v)
|
||||
{
|
||||
_freertos_ATOMIC_SUB(v, 1);
|
||||
}
|
||||
|
||||
static int _freertos_ATOMIC_ADD_RETURN(ATOMIC_T *v, int i)
|
||||
{
|
||||
int temp;
|
||||
|
||||
save_and_cli();
|
||||
temp = v->counter;
|
||||
temp += i;
|
||||
v->counter = temp;
|
||||
restore_flags();
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
static int _freertos_ATOMIC_SUB_RETURN(ATOMIC_T *v, int i)
|
||||
{
|
||||
int temp;
|
||||
|
||||
save_and_cli();
|
||||
temp = v->counter;
|
||||
temp -= i;
|
||||
v->counter = temp;
|
||||
restore_flags();
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
static int _freertos_ATOMIC_INC_RETURN(ATOMIC_T *v)
|
||||
{
|
||||
return _freertos_ATOMIC_ADD_RETURN(v, 1);
|
||||
}
|
||||
|
||||
static int _freertos_ATOMIC_DEC_RETURN(ATOMIC_T *v)
|
||||
{
|
||||
return _freertos_ATOMIC_SUB_RETURN(v, 1);
|
||||
}
|
||||
|
||||
static uint64_t _freertos_modular64(uint64_t n, uint64_t base)
|
||||
{
|
||||
unsigned int __base = (base);
|
||||
unsigned int __rem;
|
||||
|
||||
if (((n) >> 32) == 0) {
|
||||
__rem = (unsigned int)(n) % __base;
|
||||
(n) = (unsigned int)(n) / __base;
|
||||
}
|
||||
else
|
||||
__rem = __div64_32(&(n), __base);
|
||||
|
||||
return __rem;
|
||||
}
|
||||
|
||||
/* Refer to ecos bsd tcpip codes */
|
||||
static int _freertos_arc4random(void)
|
||||
{
|
||||
uint32_t res = xTaskGetTickCount();
|
||||
static unsigned long seed = 0xDEADB00B;
|
||||
|
||||
#if CONFIG_PLATFORM_8711B
|
||||
if(random_seed){
|
||||
seed = random_seed;
|
||||
random_seed = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
seed = ((seed & 0x007F00FF) << 7) ^
|
||||
((seed & 0x0F80FF00) >> 8) ^ // be sure to stir those low bits
|
||||
(res << 13) ^ (res >> 9); // using the clock too!
|
||||
return (int)seed;
|
||||
}
|
||||
|
||||
static int _freertos_get_random_bytes(void *buf, size_t len)
|
||||
{
|
||||
#if 1 //becuase of 4-byte align, we use the follow code style.
|
||||
unsigned int ranbuf;
|
||||
unsigned int *lp;
|
||||
int i, count;
|
||||
count = len / sizeof(unsigned int);
|
||||
lp = (unsigned int *) buf;
|
||||
|
||||
for(i = 0; i < count; i ++) {
|
||||
lp[i] = _freertos_arc4random();
|
||||
len -= sizeof(unsigned int);
|
||||
}
|
||||
|
||||
if(len > 0) {
|
||||
ranbuf = _freertos_arc4random();
|
||||
_freertos_memcpy(&lp[i], &ranbuf, len);
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
unsigned long ranbuf, *lp;
|
||||
lp = (unsigned long *)buf;
|
||||
while (len > 0) {
|
||||
ranbuf = _freertos_arc4random();
|
||||
*lp++ = ranbuf; //this op need the pointer is 4Byte-align!
|
||||
len -= sizeof(ranbuf);
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t _freertos_GetFreeHeapSize(void)
|
||||
{
|
||||
return (uint32_t)xPortGetFreeHeapSize();
|
||||
}
|
||||
|
||||
//extern void *tcm_heap_malloc(int size);
|
||||
|
||||
static int _freertos_create_task(struct task_struct *ptask, const char *name,
|
||||
uint32_t stack_size, uint32_t priority, thread_func_t func, void *thctx)
|
||||
{
|
||||
thread_func_t task_func = NULL;
|
||||
void *task_ctx = NULL;
|
||||
int ret = 0;
|
||||
|
||||
ptask->task_name = name;
|
||||
ptask->blocked = 0;
|
||||
ptask->callback_running = 0;
|
||||
|
||||
_freertos_init_sema(&ptask->wakeup_sema, 0);
|
||||
_freertos_init_sema(&ptask->terminate_sema, 0);
|
||||
//rtw_init_queue(&wq->work_queue);
|
||||
|
||||
if(func){
|
||||
task_func = func;
|
||||
task_ctx = thctx;
|
||||
}
|
||||
//else{
|
||||
// task_func = freertos_wq_thread_handler;
|
||||
// task_ctx = wq;
|
||||
//}
|
||||
|
||||
priority += tskIDLE_PRIORITY + PRIORITIE_OFFSET;
|
||||
|
||||
if(rtw_if_wifi_thread((char *)name) == 0){
|
||||
|
||||
#if CONFIG_USE_TCM_HEAP
|
||||
void *stack_addr = tcm_heap_malloc(stack_size*sizeof(int));
|
||||
//void *stack_addr = rtw_malloc(stack_size*sizeof(int));
|
||||
if(stack_addr == NULL){
|
||||
DBG_INFO("Out of TCM heap in \"%s\" ", ptask->task_name);
|
||||
}
|
||||
ret = xTaskGenericCreate(
|
||||
task_func,
|
||||
(const char *)name,
|
||||
stack_size,
|
||||
task_ctx,
|
||||
priority,
|
||||
&ptask->task,
|
||||
stack_addr,
|
||||
NULL);
|
||||
#else
|
||||
ret = xTaskCreate(
|
||||
task_func,
|
||||
(const char *)name,
|
||||
stack_size,
|
||||
task_ctx,
|
||||
priority,
|
||||
&ptask->task);
|
||||
#endif
|
||||
}
|
||||
else{
|
||||
ret = xTaskCreate(
|
||||
task_func,
|
||||
(const char *)name,
|
||||
stack_size,
|
||||
task_ctx,
|
||||
priority,
|
||||
&ptask->task);
|
||||
|
||||
}
|
||||
if(ret != pdPASS){
|
||||
DBG_ERR("Create Task \"%s\" Failed! ret=%d\n", ptask->task_name, ret);
|
||||
}
|
||||
|
||||
DBG_TRACE("Create Task \"%s\"\n", ptask->task_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void _freertos_delete_task(struct task_struct *ptask)
|
||||
{
|
||||
if (!ptask->task){
|
||||
DBG_ERR("_freertos_delete_task(): ptask is NULL!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ptask->blocked = 1;
|
||||
|
||||
_freertos_up_sema(&ptask->wakeup_sema);
|
||||
_freertos_down_sema(&ptask->terminate_sema, TIMER_MAX_DELAY);
|
||||
|
||||
//rtw_deinit_queue(&wq->work_queue);
|
||||
_freertos_free_sema(&ptask->wakeup_sema);
|
||||
_freertos_free_sema(&ptask->terminate_sema);
|
||||
|
||||
ptask->task = 0;
|
||||
|
||||
DBG_TRACE("Delete Task \"%s\"\n", ptask->task_name);
|
||||
}
|
||||
|
||||
void _freertos_wakeup_task(struct task_struct *ptask)
|
||||
{
|
||||
_freertos_up_sema(&ptask->wakeup_sema);
|
||||
}
|
||||
|
||||
static void _freertos_thread_enter(char *name)
|
||||
{
|
||||
DBG_INFO("\n\rRTKTHREAD %s\n", name);
|
||||
}
|
||||
|
||||
static void _freertos_thread_exit(void)
|
||||
{
|
||||
DBG_INFO("\n\rRTKTHREAD exit %s\n", __FUNCTION__);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
_timerHandle _freertos_timerCreate( const signed char *pcTimerName,
|
||||
osdepTickType xTimerPeriodInTicks,
|
||||
uint32_t uxAutoReload,
|
||||
void * pvTimerID,
|
||||
TIMER_FUN pxCallbackFunction )
|
||||
{
|
||||
if(xTimerPeriodInTicks == TIMER_MAX_DELAY) {
|
||||
xTimerPeriodInTicks = portMAX_DELAY;
|
||||
}
|
||||
return xTimerCreate((const char *)pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction);
|
||||
}
|
||||
|
||||
uint32_t _freertos_timerDelete( _timerHandle xTimer,
|
||||
osdepTickType xBlockTime )
|
||||
{
|
||||
return (uint32_t)xTimerDelete(xTimer, xBlockTime);
|
||||
}
|
||||
|
||||
uint32_t _freertos_timerIsTimerActive( _timerHandle xTimer )
|
||||
{
|
||||
return (uint32_t)xTimerIsTimerActive(xTimer);
|
||||
}
|
||||
|
||||
uint32_t _freertos_timerStop( _timerHandle xTimer,
|
||||
osdepTickType xBlockTime )
|
||||
{
|
||||
return (uint32_t)xTimerStop(xTimer, xBlockTime);
|
||||
}
|
||||
|
||||
uint32_t _freertos_timerChangePeriod( _timerHandle xTimer,
|
||||
osdepTickType xNewPeriod,
|
||||
osdepTickType xBlockTime )
|
||||
{
|
||||
if(xNewPeriod == 0)
|
||||
xNewPeriod += 1;
|
||||
return (uint32_t)xTimerChangePeriod(xTimer, xNewPeriod, xBlockTime);
|
||||
}
|
||||
void *_freertos_timerGetID( _timerHandle xTimer ){
|
||||
|
||||
return pvTimerGetTimerID(xTimer);
|
||||
}
|
||||
|
||||
uint32_t _freertos_timerStart( _timerHandle xTimer,
|
||||
osdepTickType xBlockTime )
|
||||
{
|
||||
return (uint32_t)xTimerStart(xTimer, xBlockTime);
|
||||
}
|
||||
|
||||
uint32_t _freertos_timerStartFromISR( _timerHandle xTimer,
|
||||
osdepBASE_TYPE *pxHigherPriorityTaskWoken )
|
||||
{
|
||||
return (uint32_t)xTimerStartFromISR(xTimer, pxHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
uint32_t _freertos_timerStopFromISR( _timerHandle xTimer,
|
||||
osdepBASE_TYPE *pxHigherPriorityTaskWoken )
|
||||
{
|
||||
return (uint32_t)xTimerStopFromISR(xTimer, pxHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
uint32_t _freertos_timerResetFromISR( _timerHandle xTimer,
|
||||
osdepBASE_TYPE *pxHigherPriorityTaskWoken )
|
||||
{
|
||||
return (uint32_t)xTimerResetFromISR(xTimer, pxHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
uint32_t _freertos_timerChangePeriodFromISR( _timerHandle xTimer,
|
||||
osdepTickType xNewPeriod,
|
||||
osdepBASE_TYPE *pxHigherPriorityTaskWoken )
|
||||
{
|
||||
if(xNewPeriod == 0)
|
||||
xNewPeriod += 1;
|
||||
return (uint32_t)xTimerChangePeriodFromISR(xTimer, xNewPeriod, pxHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
uint32_t _freertos_timerReset( _timerHandle xTimer,
|
||||
osdepTickType xBlockTime )
|
||||
{
|
||||
return (uint32_t)xTimerReset(xTimer, xBlockTime);
|
||||
}
|
||||
|
||||
void _freertos_acquire_wakelock()
|
||||
{
|
||||
#if defined(CONFIG_PLATFORM_8195A)
|
||||
|
||||
#if defined(configUSE_WAKELOCK_PMU) && (configUSE_WAKELOCK_PMU == 1)
|
||||
pmu_acquire_wakelock(PMU_WLAN_DEVICE);
|
||||
#endif
|
||||
|
||||
#elif defined(CONFIG_PLATFORM_8711B)
|
||||
|
||||
#if defined(configUSE_WAKELOCK_PMU) && (configUSE_WAKELOCK_PMU == 1)
|
||||
if (pmu_yield_os_check())
|
||||
pmu_acquire_wakelock(PMU_WLAN_DEVICE);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void _freertos_release_wakelock()
|
||||
{
|
||||
|
||||
#if defined(CONFIG_PLATFORM_8195A)
|
||||
|
||||
#if defined(configUSE_WAKELOCK_PMU) && (configUSE_WAKELOCK_PMU == 1)
|
||||
pmu_release_wakelock(PMU_WLAN_DEVICE);
|
||||
#endif
|
||||
|
||||
#elif defined(CONFIG_PLATFORM_8711B)
|
||||
|
||||
#if defined(configUSE_WAKELOCK_PMU) && (configUSE_WAKELOCK_PMU == 1)
|
||||
if (pmu_yield_os_check())
|
||||
pmu_release_wakelock(PMU_WLAN_DEVICE);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void _freertos_wakelock_timeout(uint32_t timeout)
|
||||
{
|
||||
#if defined(CONFIG_PLATFORM_8195A)
|
||||
|
||||
#elif defined(CONFIG_PLATFORM_8711B)
|
||||
if (pmu_yield_os_check())
|
||||
pmu_set_sysactive_time(PMU_WLAN_DEVICE, timeout);
|
||||
else
|
||||
DBG_INFO("can't aquire wake during suspend flow!!\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t _freertos_get_scheduler_state(void)
|
||||
{
|
||||
uint8_t state = xTaskGetSchedulerState();
|
||||
switch(state){
|
||||
case taskSCHEDULER_NOT_STARTED: state = OS_SCHEDULER_NOT_STARTED; break;
|
||||
case taskSCHEDULER_RUNNING: state = OS_SCHEDULER_RUNNING; break;
|
||||
case taskSCHEDULER_SUSPENDED: state = OS_SCHEDULER_SUSPENDED; break;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
const struct osdep_service_ops osdep_service = {
|
||||
_freertos_malloc, //rtw_vmalloc
|
||||
_freertos_zmalloc, //rtw_zvmalloc
|
||||
_freertos_mfree, //rtw_vmfree
|
||||
_freertos_malloc, //rtw_malloc
|
||||
_freertos_zmalloc, //rtw_zmalloc
|
||||
_freertos_mfree, //rtw_mfree
|
||||
_freertos_memcpy, //rtw_memcpy
|
||||
_freertos_memcmp, //rtw_memcmp
|
||||
_freertos_memset, //rtw_memset
|
||||
_freertos_init_sema, //rtw_init_sema
|
||||
_freertos_free_sema, //rtw_free_sema
|
||||
_freertos_up_sema, //rtw_up_sema
|
||||
_freertos_up_sema_from_isr, //rtw_up_sema_from_isr
|
||||
_freertos_down_sema, //rtw_down_sema
|
||||
_freertos_mutex_init, //rtw_mutex_init
|
||||
_freertos_mutex_free, //rtw_mutex_free
|
||||
_freertos_mutex_get, //rtw_mutex_get
|
||||
_freertos_mutex_get_timeout,//rtw_mutex_get_timeout
|
||||
_freertos_mutex_put, //rtw_mutex_put
|
||||
_freertos_enter_critical, //rtw_enter_critical
|
||||
_freertos_exit_critical, //rtw_exit_critical
|
||||
_freertos_enter_critical_from_isr, //rtw_enter_critical_from_isr
|
||||
_freertos_exit_critical_from_isr, //rtw_exit_critical_from_isr
|
||||
NULL, //rtw_enter_critical_bh
|
||||
NULL, //rtw_exit_critical_bh
|
||||
_freertos_enter_critical_mutex, //rtw_enter_critical_mutex
|
||||
_freertos_exit_critical_mutex, //rtw_exit_critical_mutex
|
||||
_freertos_spinlock_init, //rtw_spinlock_init
|
||||
_freertos_spinlock_free, //rtw_spinlock_free
|
||||
_freertos_spinlock, //rtw_spin_lock
|
||||
_freertos_spinunlock, //rtw_spin_unlock
|
||||
_freertos_spinlock_irqsave, //rtw_spinlock_irqsave
|
||||
_freertos_spinunlock_irqsave, //rtw_spinunlock_irqsave
|
||||
_freertos_init_xqueue, //rtw_init_xqueue
|
||||
_freertos_push_to_xqueue, //rtw_push_to_xqueue
|
||||
_freertos_pop_from_xqueue, //rtw_pop_from_xqueue
|
||||
_freertos_deinit_xqueue, //rtw_deinit_xqueue
|
||||
_freertos_get_current_time, //rtw_get_current_time
|
||||
_freertos_systime_to_ms, //rtw_systime_to_ms
|
||||
_freertos_systime_to_sec, //rtw_systime_to_sec
|
||||
_freertos_ms_to_systime, //rtw_ms_to_systime
|
||||
_freertos_sec_to_systime, //rtw_sec_to_systime
|
||||
_freertos_msleep_os, //rtw_msleep_os
|
||||
_freertos_usleep_os, //rtw_usleep_os
|
||||
_freertos_mdelay_os, //rtw_mdelay_os
|
||||
_freertos_udelay_os, //rtw_udelay_os
|
||||
_freertos_yield_os, //rtw_yield_os
|
||||
|
||||
_freertos_ATOMIC_SET, //ATOMIC_SET
|
||||
_freertos_ATOMIC_READ, //ATOMIC_READ
|
||||
_freertos_ATOMIC_ADD, //ATOMIC_ADD
|
||||
_freertos_ATOMIC_SUB, //ATOMIC_SUB
|
||||
_freertos_ATOMIC_INC, //ATOMIC_INC
|
||||
_freertos_ATOMIC_DEC, //ATOMIC_DEC
|
||||
_freertos_ATOMIC_ADD_RETURN, //ATOMIC_ADD_RETURN
|
||||
_freertos_ATOMIC_SUB_RETURN, //ATOMIC_SUB_RETURN
|
||||
_freertos_ATOMIC_INC_RETURN, //ATOMIC_INC_RETURN
|
||||
_freertos_ATOMIC_DEC_RETURN, //ATOMIC_DEC_RETURN
|
||||
|
||||
_freertos_modular64, //rtw_modular64
|
||||
_freertos_get_random_bytes, //rtw_get_random_bytes
|
||||
_freertos_GetFreeHeapSize, //rtw_getFreeHeapSize
|
||||
|
||||
_freertos_create_task, //rtw_create_task
|
||||
_freertos_delete_task, //rtw_delete_task
|
||||
_freertos_wakeup_task, //rtw_wakeup_task
|
||||
|
||||
_freertos_thread_enter, //rtw_thread_enter
|
||||
_freertos_thread_exit, //rtw_thread_exit
|
||||
|
||||
_freertos_timerCreate, //rtw_timerCreate,
|
||||
_freertos_timerDelete, //rtw_timerDelete,
|
||||
_freertos_timerIsTimerActive, //rtw_timerIsTimerActive,
|
||||
_freertos_timerStop, //rtw_timerStop,
|
||||
_freertos_timerChangePeriod, //rtw_timerChangePeriod
|
||||
_freertos_timerGetID, //rtw_timerGetID
|
||||
_freertos_timerStart, //rtw_timerStart
|
||||
_freertos_timerStartFromISR, //rtw_timerStartFromISR
|
||||
_freertos_timerStopFromISR, //rtw_timerStopFromISR
|
||||
_freertos_timerResetFromISR, //rtw_timerResetFromISR
|
||||
_freertos_timerChangePeriodFromISR, //rtw_timerChangePeriodFromISR
|
||||
_freertos_timerReset, //rtw_timerReset
|
||||
|
||||
_freertos_acquire_wakelock, //rtw_acquire_wakelock
|
||||
_freertos_release_wakelock, //rtw_release_wakelock
|
||||
_freertos_wakelock_timeout, //rtw_wakelock_timeout
|
||||
_freertos_get_scheduler_state //rtw_get_scheduler_state
|
||||
};
|
||||
259
Firmware/RTLGDB/USDK/component/os/freertos/freertos_service.h
Normal file
259
Firmware/RTLGDB/USDK/component/os/freertos/freertos_service.h
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
#ifndef _FREERTOS_SERVICE_H_
|
||||
#define _FREERTOS_SERVICE_H_
|
||||
|
||||
//----- ------------------------------------------------------------------
|
||||
// Include Files
|
||||
//----- ------------------------------------------------------------------
|
||||
//#include "wireless.h"
|
||||
#include "dlist.h"
|
||||
|
||||
// --------------------------------------------
|
||||
// Platform dependent include file
|
||||
// --------------------------------------------
|
||||
#if defined(CONFIG_PLATFORM_8195A)
|
||||
#include "platform/platform_stdlib.h"
|
||||
extern void RtlUdelayOS(uint32_t us);
|
||||
#elif defined(CONFIG_PLATFORM_8711B)
|
||||
#include "platform/platform_stdlib.h"
|
||||
#else
|
||||
// other MCU may use standard library
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
|
||||
#if (defined CONFIG_GSPI_HCI || defined CONFIG_SDIO_HCI) || defined(CONFIG_LX_HCI)
|
||||
/* For SPI interface transfer and us delay implementation */
|
||||
#if !defined(CONFIG_PLATFORM_8195A) && !defined(CONFIG_PLATFORM_8711B)
|
||||
#include <rtwlan_bsp.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// --------------------------------------------
|
||||
// Platform dependent type define
|
||||
// --------------------------------------------
|
||||
#if !defined(CONFIG_PLATFORM_8195A) && !defined(CONFIG_PLATFORM_8711B)
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef signed long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef unsigned int uint;
|
||||
typedef signed int sint;
|
||||
|
||||
#ifndef bool
|
||||
typedef int bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#define IN
|
||||
#define OUT
|
||||
#define void void
|
||||
#define NDIS_OID uint
|
||||
#define NDIS_STATUS uint
|
||||
#ifndef PVOID
|
||||
typedef void * PVOID;
|
||||
#endif
|
||||
|
||||
typedef unsigned int __kernel_size_t;
|
||||
typedef int __kernel_ssize_t;
|
||||
typedef __kernel_size_t SIZE_T;
|
||||
typedef __kernel_ssize_t SSIZE_T;
|
||||
|
||||
#endif //CONFIG_PLATFORM_8195A
|
||||
|
||||
#define FIELD_OFFSET(s,field) ((SSIZE_T)&((s*)(0))->field)
|
||||
|
||||
// os types
|
||||
typedef char osdepCHAR;
|
||||
typedef float osdepFLOAT;
|
||||
typedef double osdepDOUBLE;
|
||||
typedef long osdepLONG;
|
||||
typedef short osdepSHORT;
|
||||
typedef unsigned long osdepSTACK_TYPE;
|
||||
typedef long osdepBASE_TYPE;
|
||||
typedef unsigned long osdepTickType;
|
||||
|
||||
typedef void* _timerHandle;
|
||||
typedef void* _sema;
|
||||
typedef void* _mutex;
|
||||
typedef void* _lock;
|
||||
typedef void* _queueHandle;
|
||||
typedef void* _xqueue;
|
||||
typedef struct timer_list _timer;
|
||||
|
||||
typedef struct sk_buff _pkt;
|
||||
typedef unsigned char _buffer;
|
||||
|
||||
#ifndef __LIST_H
|
||||
#warning "DLIST_NOT_DEFINE!!!!!!"
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct __queue {
|
||||
struct list_head queue;
|
||||
_lock lock;
|
||||
};
|
||||
|
||||
typedef struct __queue _queue;
|
||||
typedef struct list_head _list;
|
||||
typedef unsigned long _irqL;
|
||||
|
||||
typedef void* _thread_hdl_;
|
||||
typedef void thread_return;
|
||||
typedef void* thread_context;
|
||||
|
||||
#define ATOMIC_T atomic_t
|
||||
#define HZ configTICK_RATE_HZ
|
||||
|
||||
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
|
||||
/* emulate a modern version */
|
||||
#define LINUX_VERSION_CODE KERNEL_VERSION(2, 6, 17)
|
||||
|
||||
static __inline _list *get_next(_list *list)
|
||||
{
|
||||
return list->next;
|
||||
}
|
||||
|
||||
static __inline _list *get_list_head(_queue *queue)
|
||||
{
|
||||
return (&(queue->queue));
|
||||
}
|
||||
|
||||
#define LIST_CONTAINOR(ptr, type, member) \
|
||||
((type *)((char *)(ptr)-(SIZE_T)((char *)&((type *)ptr)->member - (char *)ptr)))
|
||||
//#define container_of(p,t,n) (t*)((p)-&(((t*)0)->n))
|
||||
#define container_of(ptr, type, member) \
|
||||
((type *)((char *)(ptr)-(SIZE_T)(&((type *)0)->member)))
|
||||
#define TASK_PRORITY_LOW 1
|
||||
#define TASK_PRORITY_MIDDLE 2
|
||||
#define TASK_PRORITY_HIGH 3
|
||||
#define TASK_PRORITY_SUPER 4
|
||||
|
||||
#define TIMER_MAX_DELAY 0xFFFFFFFF
|
||||
|
||||
void save_and_cli(void);
|
||||
void restore_flags(void);
|
||||
void cli(void);
|
||||
|
||||
#ifndef mdelay
|
||||
#define mdelay(t) ((t/portTICK_RATE_MS)>0)?(vTaskDelay(t/portTICK_RATE_MS)):(vTaskDelay(1))
|
||||
#endif
|
||||
|
||||
#ifndef udelay
|
||||
#define udelay(t) ((t/(portTICK_RATE_MS*1000))>0)?vTaskDelay(t/(portTICK_RATE_MS*1000)):(vTaskDelay(1))
|
||||
#endif
|
||||
//----- ------------------------------------------------------------------
|
||||
// Common Definition
|
||||
//----- ------------------------------------------------------------------
|
||||
|
||||
#define __init
|
||||
#define __exit
|
||||
#define __devinit
|
||||
#define __devexit
|
||||
|
||||
#define KERN_ERR
|
||||
#define KERN_INFO
|
||||
#define KERN_NOTICE
|
||||
|
||||
#undef GFP_KERNEL
|
||||
#define GFP_KERNEL 1
|
||||
#define GFP_ATOMIC 1
|
||||
|
||||
#define SET_MODULE_OWNER(some_struct) do { } while (0)
|
||||
#define SET_NETDEV_DEV(dev, obj) do { } while (0)
|
||||
#define register_netdev(dev) (0)
|
||||
#define unregister_netdev(dev) do { } while (0)
|
||||
#define netif_queue_stopped(dev) (0)
|
||||
#define netif_wake_queue(dev) do { } while (0)
|
||||
#define printk printf
|
||||
|
||||
#define DBG_ERR(fmt, args...) printf("\n\r[%s] " fmt, __FUNCTION__, ## args)
|
||||
#if WLAN_INTF_DBG
|
||||
#define DBG_TRACE(fmt, args...) printf("\n\r[%s] " fmt, __FUNCTION__, ## args)
|
||||
#define DBG_INFO(fmt, args...) printf("\n\r[%s] " fmt, __FUNCTION__, ## args)
|
||||
#else
|
||||
#define DBG_TRACE(fmt, args...)
|
||||
#define DBG_INFO(fmt, args...)
|
||||
#endif
|
||||
#define HALT() do { cli(); for(;;);} while(0)
|
||||
#undef ASSERT
|
||||
#define ASSERT(x) do { \
|
||||
if((x) == 0) \
|
||||
printf("\n\rAssert(" #x ") failed on line %d in file %s", __LINE__, __FILE__); \
|
||||
HALT(); \
|
||||
} while(0)
|
||||
|
||||
#undef DBG_ASSERT
|
||||
#define DBG_ASSERT(x, msg) do { \
|
||||
if((x) == 0) \
|
||||
printf("\n\r%s, Assert(" #x ") failed on line %d in file %s", msg, __LINE__, __FILE__); \
|
||||
} while(0)
|
||||
|
||||
//----- ------------------------------------------------------------------
|
||||
// Atomic Operation
|
||||
//----- ------------------------------------------------------------------
|
||||
#if !defined(CONFIG_PLATFORM_8195A) && !defined(CONFIG_PLATFORM_8711B) // for 8195A, it is defined in ..system../basic_types.h
|
||||
typedef struct { volatile int counter; } atomic_t;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* atomic_read - read atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically reads the value of @v. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#undef atomic_read
|
||||
#define atomic_read(v) ((v)->counter)
|
||||
|
||||
/*
|
||||
* atomic_set - set atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
* @i: required value
|
||||
*
|
||||
* Atomically sets the value of @v to @i. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#undef atomic_set
|
||||
#define atomic_set(v,i) ((v)->counter = (i))
|
||||
|
||||
/*
|
||||
* These inlines deal with timer wrapping correctly. You are
|
||||
* strongly encouraged to use them
|
||||
* 1. Because people otherwise forget
|
||||
* 2. Because if the timer wrap changes in future you wont have to
|
||||
* alter your driver code.
|
||||
*
|
||||
* time_after(a,b) returns true if the time a is after time b.
|
||||
*
|
||||
* Do this with "<0" and ">=0" to only test the sign of the result. A
|
||||
* good compiler would generate better code (and a really good compiler
|
||||
* wouldn't care). Gcc is currently neither.
|
||||
*/
|
||||
#define time_after(a,b) ((long)(b) - (long)(a) < 0)
|
||||
#define time_before(a,b) time_after(b,a)
|
||||
|
||||
#define time_after_eq(a,b) ((long)(a) - (long)(b) >= 0)
|
||||
#define time_before_eq(a,b) time_after_eq(b,a)
|
||||
|
||||
|
||||
extern void rtw_init_listhead(_list *list);
|
||||
extern uint32_t rtw_is_list_empty(_list *phead);
|
||||
extern void rtw_list_insert_head(_list *plist, _list *phead);
|
||||
extern void rtw_list_insert_tail(_list *plist, _list *phead);
|
||||
extern void rtw_list_delete(_list *plist);
|
||||
|
||||
#if CONFIG_PLATFORM_8711B
|
||||
extern uint32_t random_seed;
|
||||
#endif
|
||||
|
||||
#endif /* _FREERTOS_SERVICE_H_ */
|
||||
65
Firmware/RTLGDB/USDK/component/os/os_dep/device_lock.c
Normal file
65
Firmware/RTLGDB/USDK/component/os/os_dep/device_lock.c
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Routines to access hardware
|
||||
*
|
||||
* Copyright (c) 2013 Realtek Semiconductor Corp.
|
||||
*
|
||||
* This module is a confidential and proprietary property of RealTek and
|
||||
* possession or use of this module requires written permission of RealTek.
|
||||
*/
|
||||
|
||||
#include "osdep_service.h"
|
||||
#include "device_lock.h"
|
||||
|
||||
//------------------------------------------------------
|
||||
#define DEVICE_MUTEX_IS_INIT(device) (mutex_init & (1<<device))
|
||||
#define DEVICE_MUTEX_SET_INIT(device) (mutex_init |= (1<<device))
|
||||
#define DEVICE_MUTEX_CLR_INIT(device) (mutex_init &= (~(1<<device)))
|
||||
|
||||
static uint32_t mutex_init = 0;
|
||||
static _mutex device_mutex[RT_DEV_LOCK_MAX];
|
||||
|
||||
//======================================================
|
||||
static void device_mutex_init(RT_DEV_LOCK_E device)
|
||||
{
|
||||
if(!DEVICE_MUTEX_IS_INIT(device)){
|
||||
_lock lock;
|
||||
_irqL irqL;
|
||||
rtw_enter_critical(&lock, &irqL);
|
||||
if(!DEVICE_MUTEX_IS_INIT(device)){
|
||||
rtw_mutex_init(&device_mutex[device]);
|
||||
DEVICE_MUTEX_SET_INIT(device);
|
||||
}
|
||||
rtw_exit_critical(&lock, &irqL);
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================
|
||||
/*
|
||||
static void device_mutex_free(RT_DEV_LOCK_E device)
|
||||
{
|
||||
if(DEVICE_MUTEX_IS_INIT(device)){
|
||||
_lock lock;
|
||||
_irqL irqL;
|
||||
rtw_enter_critical(&lock, &irqL);
|
||||
if(!DEVICE_MUTEX_IS_INIT(device)){
|
||||
rtw_mutex_free(&device_mutex[device]);
|
||||
DEVICE_MUTEX_CLR_INIT(device);
|
||||
}
|
||||
rtw_exit_critical(&lock, &irqL);
|
||||
}
|
||||
}
|
||||
*/
|
||||
//======================================================
|
||||
void device_mutex_lock(RT_DEV_LOCK_E device)
|
||||
{
|
||||
device_mutex_init(device);
|
||||
while(rtw_mutex_get_timeout(&device_mutex[device], 10000)<0)
|
||||
printf("device lock timeout: %d\n", device);
|
||||
}
|
||||
|
||||
//======================================================
|
||||
void device_mutex_unlock(RT_DEV_LOCK_E device)
|
||||
{
|
||||
device_mutex_init(device);
|
||||
rtw_mutex_put(&device_mutex[device]);
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Routines to access hardware
|
||||
*
|
||||
* Copyright (c) 2013 Realtek Semiconductor Corp.
|
||||
*
|
||||
* This module is a confidential and proprietary property of RealTek and
|
||||
* possession or use of this module requires written permission of RealTek.
|
||||
*/
|
||||
|
||||
#ifndef _DEVICE_LOCK_H_
|
||||
#define _DEVICE_LOCK_H_
|
||||
|
||||
typedef enum _RT_DEV_LOCK_E
|
||||
{
|
||||
RT_DEV_LOCK_EFUSE = 0,
|
||||
RT_DEV_LOCK_FLASH = 1,
|
||||
RT_DEV_LOCK_CRYPTO = 2,
|
||||
RT_DEV_LOCK_PTA = 3,
|
||||
RT_DEV_LOCK_MAX = 4
|
||||
}RT_DEV_LOCK_E;
|
||||
|
||||
void device_mutex_lock(RT_DEV_LOCK_E device);
|
||||
void device_mutex_unlock(RT_DEV_LOCK_E device);
|
||||
|
||||
#endif //_DEVICE_LOCK_H_
|
||||
343
Firmware/RTLGDB/USDK/component/os/os_dep/include/os_support.h
Normal file
343
Firmware/RTLGDB/USDK/component/os/os_dep/include/os_support.h
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Name: sys-support.h - System type support for Linux
|
||||
* $Revision: 1.1.1.1 $
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __OS_SUPPORT_H__
|
||||
#define __OS_SUPPORT_H__
|
||||
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <basic_types.h>
|
||||
#include "os_support.h"
|
||||
//#include "diag.h"
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
#define __init
|
||||
#define __exit
|
||||
#define __devinit
|
||||
#define __devexit
|
||||
#endif
|
||||
#define RTL_HZ 100
|
||||
|
||||
#define SemaInit(sem, value) vSemaphoreCreateBinary(sem)
|
||||
#define SemaPost(sem) xSemaphoreGive(sem)
|
||||
#define SemaWait(sem, block_time) xSemaphoreTake(sem, block_time)
|
||||
//#define printk DiagPrintf
|
||||
|
||||
#define SpinLockInit(lock) do { } while (0)
|
||||
#define SpinLock(x) do { } while (0)
|
||||
#define SpinUnlock(x) do { } while (0)
|
||||
#define SpinLockBh(x) do { } while (0)
|
||||
#define SpinUnlockBh(x) do { } while (0)
|
||||
#ifdef PLATFORM_FREERTOS
|
||||
#define RestoreFlags() portEXIT_CRITICAL()
|
||||
#define SaveAndCli() portENTER_CRITICAL()
|
||||
#define SpinLockIrqSave(lock, flags) SaveAndCli()
|
||||
#define SpinUnlockIrqRestore(l, f) RestoreFlags()
|
||||
#else
|
||||
#define RestoreFlags(x) portENABLE_INTERRUPTS()
|
||||
#define SaveAndCli(x) portDISABLE_INTERRUPTS()
|
||||
#define SpinLockIrqSave(lock, flags) SaveAndCli(flags)
|
||||
#define SpinUnlockIrqRestore(l, f) RestoreFlags(f)
|
||||
#endif
|
||||
|
||||
|
||||
//#define RtlKmalloc(size, flag) pvPortMallocAligned(size, 0)
|
||||
#define RtlKmalloc(size, flag) pvPortMalloc(size)
|
||||
#define RtlKfree(pv) vPortFreeAligned(pv)
|
||||
|
||||
|
||||
|
||||
#ifdef CONFIG_TIMER_MODULE
|
||||
#define __Delay(t) HalDelayUs(t)
|
||||
#else
|
||||
static __inline__ uint32_t __Delay(uint32_t us)
|
||||
{
|
||||
DBG_8195A("No Delay: please enable hardware Timer\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define Mdelay(t) __Delay(t*1000)
|
||||
#define Udelay(t) __Delay(t)
|
||||
|
||||
|
||||
#define ASSERT(_bool_) do { } while (0)
|
||||
|
||||
//#define panic_printk DiagPrintf
|
||||
//#define sprintf DiagPrintf
|
||||
//#define diag_sprintf DiagPrintf
|
||||
|
||||
|
||||
//1TODO: Need check again; the below just for compile ok ; chris
|
||||
|
||||
/*
|
||||
* ATOMIC_READ - read atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically reads the value of @v. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
//#define AtomicRead(v) ((*v))
|
||||
|
||||
static __inline__ uint32_t
|
||||
AtomicRead(
|
||||
IN atomic_t * v
|
||||
)
|
||||
{
|
||||
#ifdef PLATFORM_FREERTOS
|
||||
uint32_t Temp;
|
||||
|
||||
SaveAndCli();
|
||||
Temp = v->counter;
|
||||
RestoreFlags();
|
||||
|
||||
return Temp;
|
||||
|
||||
#else
|
||||
uint32_t Temp, Flags;
|
||||
|
||||
SaveAndCli(Flags);
|
||||
Temp = v->counter;
|
||||
RestoreFlags(Flags);
|
||||
|
||||
return Temp;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* ATOMIC_SET - set atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
* @i: required value
|
||||
*
|
||||
* Atomically sets the value of @v to @i. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
//#define AtomicSet(v,i) ((v)->counter = (i))
|
||||
|
||||
static __inline__ void
|
||||
AtomicSet(
|
||||
IN uint32_t i,
|
||||
IN atomic_t * v
|
||||
)
|
||||
{
|
||||
#ifdef PLATFORM_FREERTOS
|
||||
SaveAndCli();
|
||||
v->counter = i;
|
||||
RestoreFlags();
|
||||
#else
|
||||
uint32_t Flags;
|
||||
|
||||
SaveAndCli(Flags);
|
||||
v->counter = i;
|
||||
RestoreFlags(Flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* The MIPS I implementation is only atomic with respect to
|
||||
* interrupts. R3000 based multiprocessor machines are rare anyway ...
|
||||
*
|
||||
* AtomicAdd - add integer to atomic variable
|
||||
* @i: integer value to add
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically adds @i to @v. Note that the guaranteed useful range
|
||||
* of an atomic_t is only 24 bits.
|
||||
*/
|
||||
static __inline__ void
|
||||
AtomicAdd(
|
||||
IN uint32_t i,
|
||||
IN atomic_t * v
|
||||
)
|
||||
{
|
||||
#ifdef PLATFORM_FREERTOS
|
||||
SaveAndCli();
|
||||
v->counter += i;
|
||||
RestoreFlags();
|
||||
#else
|
||||
uint32_t Flags;
|
||||
|
||||
SaveAndCli(Flags);
|
||||
v->counter += i;
|
||||
RestoreFlags(Flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* AtomicSub - subtract the atomic variable
|
||||
* @i: integer value to subtract
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically subtracts @i from @v. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
static __inline__ void
|
||||
AtomicSub(
|
||||
IN uint32_t i,
|
||||
IN atomic_t * v
|
||||
)
|
||||
{
|
||||
#ifdef PLATFORM_FREERTOS
|
||||
SaveAndCli();
|
||||
v->counter -= i;
|
||||
RestoreFlags();
|
||||
#else
|
||||
uint32_t Flags;
|
||||
|
||||
SaveAndCli(Flags);
|
||||
v->counter -= i;
|
||||
RestoreFlags(Flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline__ uint32_t
|
||||
AtomicAddReturn(
|
||||
IN uint32_t i,
|
||||
IN atomic_t * v
|
||||
)
|
||||
{
|
||||
#ifdef PLATFORM_FREERTOS
|
||||
uint32_t Temp;
|
||||
|
||||
SaveAndCli();
|
||||
Temp = v->counter;
|
||||
Temp += i;
|
||||
v->counter = Temp;
|
||||
RestoreFlags();
|
||||
|
||||
return Temp;
|
||||
|
||||
#else
|
||||
uint32_t Temp, Flags;
|
||||
|
||||
SaveAndCli(Flags);
|
||||
Temp = v->counter;
|
||||
Temp += i;
|
||||
v->counter = Temp;
|
||||
RestoreFlags(Flags);
|
||||
|
||||
return Temp;
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline__ uint32_t
|
||||
AtomicSubReturn(
|
||||
IN uint32_t i,
|
||||
IN atomic_t * v
|
||||
)
|
||||
{
|
||||
#ifdef PLATFORM_FREERTOS
|
||||
uint32_t Temp;
|
||||
|
||||
SaveAndCli();
|
||||
Temp = v->counter;
|
||||
Temp -= i;
|
||||
v->counter = Temp;
|
||||
RestoreFlags();
|
||||
|
||||
return Temp;
|
||||
|
||||
#else
|
||||
|
||||
uint32_t Temp, Flags;
|
||||
|
||||
SaveAndCli(Flags);
|
||||
Temp = v->counter;
|
||||
Temp -= i;
|
||||
v->counter = Temp;
|
||||
RestoreFlags(Flags);
|
||||
|
||||
return Temp;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* ATOMIC_INC - increment atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically increments @v by 1. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#define AtomicInc(v) AtomicAdd(1,(v))
|
||||
|
||||
#define AtomicIncReturn(v) AtomicAddReturn(1,(v))
|
||||
|
||||
/*
|
||||
* ATOMIC_DEC - decrement and test
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically decrements @v by 1. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#define AtomicDec(v) AtomicSub(1,(v))
|
||||
|
||||
#define AtomicDecReturn(v) AtomicSubReturn(1,(v))
|
||||
|
||||
/*
|
||||
* ATOMIC_DEC_AND_TEST - decrement by 1 and test
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically decrements @v by 1 and
|
||||
* returns true if the result is 0, or false for all other
|
||||
* cases. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#define AtomicDecAndTest(v) (AtomicSubReturn(1, (v)) == 0)
|
||||
|
||||
/* Not needed on 64bit architectures */
|
||||
static __inline__ uint32_t
|
||||
__Div64_32(
|
||||
IN __uint64_t *n,
|
||||
IN uint32_t base
|
||||
)
|
||||
{
|
||||
__uint64_t rem = *n;
|
||||
__uint64_t b = base;
|
||||
__uint64_t res, d = 1;
|
||||
uint32_t high = rem >> 32;
|
||||
|
||||
/* Reduce the thing a bit first */
|
||||
res = 0;
|
||||
if (high >= base) {
|
||||
high /= base;
|
||||
res = (__uint64_t) high << 32;
|
||||
rem -= (__uint64_t) (high*base) << 32;
|
||||
}
|
||||
|
||||
while ((__int64_t)b > 0 && b < rem) {
|
||||
b = b+b;
|
||||
d = d+d;
|
||||
}
|
||||
|
||||
do {
|
||||
if (rem >= b) {
|
||||
rem -= b;
|
||||
res += d;
|
||||
}
|
||||
b >>= 1;
|
||||
d >>= 1;
|
||||
} while (d);
|
||||
|
||||
*n = res;
|
||||
return rem;
|
||||
}
|
||||
|
||||
#define DO_DIV(n,base) ({ \
|
||||
unsigned int __base = (base); \
|
||||
unsigned int __rem; \
|
||||
(void)(((typeof((n)) *)0) == ((__uint64_t *)0)); \
|
||||
if (((n) >> 32) == 0) { \
|
||||
__rem = (unsigned int)(n) % __base; \
|
||||
(n) = (unsigned int)(n) / __base; \
|
||||
} else \
|
||||
__rem = __Div64_32(&(n), __base); \
|
||||
__rem; \
|
||||
})
|
||||
|
||||
#endif /* __SYS_SUPPORT_H__ */
|
||||
1354
Firmware/RTLGDB/USDK/component/os/os_dep/include/osdep_service.h
Normal file
1354
Firmware/RTLGDB/USDK/component/os/os_dep/include/osdep_service.h
Normal file
File diff suppressed because it is too large
Load diff
74
Firmware/RTLGDB/USDK/component/os/os_dep/include/tcm_heap.h
Normal file
74
Firmware/RTLGDB/USDK/component/os/os_dep/include/tcm_heap.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef STRUCT_HEAP_H
|
||||
#define STRUCT_HEAP_H
|
||||
|
||||
//#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <osdep_service.h>
|
||||
|
||||
|
||||
|
||||
#define TCM_HEAP_SIZE (42*1024) // min size
|
||||
|
||||
// MAX_BACKUP_SIZE in hal_soc_ps_monitor = 129*4, 0x1FFFFFFC - 129*4 = 0x1FFFFD18 !
|
||||
#define tcm_heap_size ((0x20000000 - (uint32_t)&tcm_heap - 768 + sizeof(heap_buf_t) - 1)/sizeof(heap_buf_t))*sizeof(heap_buf_t)
|
||||
|
||||
/* NOTE: struct size must be a 2's power! */
|
||||
typedef struct _MemChunk
|
||||
{
|
||||
struct _MemChunk *next;
|
||||
int size;
|
||||
} MemChunk;
|
||||
|
||||
typedef MemChunk heap_buf_t;
|
||||
|
||||
/// A heap
|
||||
typedef struct Heap
|
||||
{
|
||||
struct _MemChunk *FreeList; ///< Head of the free list
|
||||
} Heap;
|
||||
|
||||
/**
|
||||
* Utility macro to allocate a heap of size \a size.
|
||||
*
|
||||
* \param name Variable name for the heap.
|
||||
* \param size Heap size in bytes.
|
||||
*/
|
||||
#define HEAP_DEFINE_BUF(name, size) \
|
||||
heap_buf_t name[((size) + sizeof(heap_buf_t) - 1) / sizeof(heap_buf_t)]
|
||||
|
||||
/// Initialize \a heap within the buffer pointed by \a memory which is of \a size bytes
|
||||
void tcm_heap_init(void);
|
||||
|
||||
/// Allocate a chunk of memory of \a size bytes from the heap
|
||||
// void *tcm_heap_allocmem(int size);
|
||||
|
||||
/// Free a chunk of memory of \a size bytes from the heap
|
||||
// void tcm_heap_freemem(void *mem, int size);
|
||||
|
||||
int tcm_heap_freeSpace(void);
|
||||
|
||||
#define HNEW(heap, type) \
|
||||
(type*)tcm_heap_allocmem(heap, sizeof(type))
|
||||
|
||||
#define HNEWVEC(heap, type, nelem) \
|
||||
(type*)tcm_heap_allocmem(heap, sizeof(type) * (nelem))
|
||||
|
||||
#define HDELETE(heap, type, mem) \
|
||||
tcm_heap_freemem(heap, mem, sizeof(type))
|
||||
|
||||
#define HDELETEVEC(heap, type, nelem, mem) \
|
||||
tcm_heap_freemem(heap, mem, sizeof(type) * (nelem))
|
||||
|
||||
extern HEAP_DEFINE_BUF(tcm_heap, TCM_HEAP_SIZE);
|
||||
|
||||
/**
|
||||
* \name Compatibility interface with C standard library
|
||||
* \{
|
||||
*/
|
||||
void *tcm_heap_malloc(int size);
|
||||
void *tcm_heap_calloc(int size);
|
||||
void tcm_heap_free(void * mem);
|
||||
void tcm_heap_dump(void);
|
||||
/** \} */
|
||||
|
||||
#endif /* STRUCT_HEAP_H */
|
||||
1309
Firmware/RTLGDB/USDK/component/os/os_dep/osdep_service.c
Normal file
1309
Firmware/RTLGDB/USDK/component/os/os_dep/osdep_service.c
Normal file
File diff suppressed because it is too large
Load diff
347
Firmware/RTLGDB/USDK/component/os/os_dep/tcm_heap.c
Normal file
347
Firmware/RTLGDB/USDK/component/os/os_dep/tcm_heap.c
Normal file
|
|
@ -0,0 +1,347 @@
|
|||
//#include <autoconf.h>
|
||||
#include "tcm_heap.h"
|
||||
|
||||
#include <string.h> // memset()
|
||||
|
||||
#include <osdep_service.h>
|
||||
|
||||
//#define _DEBUG
|
||||
|
||||
#if CONFIG_USE_TCM_HEAP
|
||||
#define FREE_FILL_CODE 0xDEAD
|
||||
#define ALLOC_FILL_CODE 0xBEEF
|
||||
|
||||
#define ROUND_UP2(x, pad) (((x) + ((pad) - 1)) & ~((pad) - 1))
|
||||
|
||||
//static
|
||||
struct Heap g_tcm_heap;
|
||||
|
||||
#if defined (__ICCARM__)
|
||||
#pragma location=".tcm.heap"
|
||||
#else
|
||||
__attribute__((section(".tcm.heap")))
|
||||
#endif
|
||||
HEAP_DEFINE_BUF(tcm_heap, TCM_HEAP_SIZE);
|
||||
//unsigned char tcm_heap[TCM_HEAP_SIZE];
|
||||
|
||||
static int g_heap_inited = 0;
|
||||
static _lock tcm_lock;
|
||||
|
||||
extern void vPortSetExtFree( void (*free)( void *p ), uint32_t upper, uint32_t lower );
|
||||
|
||||
void tcm_heap_init(void)
|
||||
{
|
||||
//#ifdef _DEBUG
|
||||
//memset(memory, FREE_FILL_CODE, size);
|
||||
//#endif
|
||||
|
||||
//ASSERT2(((int)memory % alignof(heap_buf_t)) == 0,
|
||||
//"memory buffer is unaligned, please use the HEAP_DEFINE_BUF() macro to declare heap buffers!\n");
|
||||
|
||||
/* Initialize heap with a single big chunk */
|
||||
g_tcm_heap.FreeList = (MemChunk *)&tcm_heap;
|
||||
g_tcm_heap.FreeList->next = NULL;
|
||||
// g_tcm_heap.FreeList->size = sizeof(tcm_heap);
|
||||
g_tcm_heap.FreeList->size = tcm_heap_size; // ((0x20000000 - (uint32_t)&tcm_heap - 520 + sizeof(heap_buf_t) - 1)/sizeof(heap_buf_t))*sizeof(heap_buf_t);
|
||||
|
||||
g_heap_inited = 1;
|
||||
rtw_spinlock_init(&tcm_lock);
|
||||
|
||||
#if PLATFORM_FREERTOS
|
||||
// let RTOS know how to free memory if using as task stack
|
||||
vPortSetExtFree(tcm_heap_free, 0x20000000, 0x1fff0000);
|
||||
#endif
|
||||
}
|
||||
|
||||
void tcm_heap_dump(void)
|
||||
{
|
||||
#if CONFIG_DEBUG_LOG > 1
|
||||
if(!g_heap_inited) tcm_heap_init();
|
||||
MemChunk *chunk;
|
||||
struct Heap* h = &g_tcm_heap;
|
||||
int count = 0;
|
||||
|
||||
DBG_8195A("TCM Free Heap Memory List:\n");
|
||||
for (chunk = h->FreeList; chunk; chunk = chunk->next) {
|
||||
DBG_8195A(" [%d]=%p, %d\n", ++count, chunk, chunk->size);
|
||||
}
|
||||
|
||||
/*
|
||||
MemChunk *prev;
|
||||
for (prev = (MemChunk *)&h->FreeList, chunk = h->FreeList;
|
||||
chunk;
|
||||
prev = chunk, chunk = chunk->next)
|
||||
{
|
||||
DBG_8195A(" [%d]=%p, %d\n", ++count, chunk, chunk->size);
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
static void *tcm_heap_allocmem(int size)
|
||||
{
|
||||
MemChunk *chunk, *prev;
|
||||
struct Heap* h = &g_tcm_heap;
|
||||
_irqL irqL;
|
||||
|
||||
rtw_enter_critical(&tcm_lock, &irqL);
|
||||
|
||||
if(!g_heap_inited) tcm_heap_init();
|
||||
|
||||
/* Round size up to the allocation granularity */
|
||||
size = ROUND_UP2(size, sizeof(MemChunk));
|
||||
|
||||
/* Handle allocations of 0 bytes */
|
||||
if (!size)
|
||||
size = sizeof(MemChunk);
|
||||
|
||||
/* Walk on the free list looking for any chunk big enough to
|
||||
* fit the requested block size.
|
||||
*/
|
||||
for (prev = (MemChunk *)&h->FreeList, chunk = h->FreeList;
|
||||
chunk;
|
||||
prev = chunk, chunk = chunk->next)
|
||||
{
|
||||
if (chunk->size >= size)
|
||||
{
|
||||
if (chunk->size == size)
|
||||
{
|
||||
/* Just remove this chunk from the free list */
|
||||
prev->next = chunk->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate from the END of an existing chunk */
|
||||
chunk->size -= size;
|
||||
chunk = (MemChunk *)((uint8_t *)chunk + chunk->size);
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
memset(chunk, ALLOC_FILL_CODE, size);
|
||||
#endif
|
||||
|
||||
rtw_exit_critical(&tcm_lock, &irqL);
|
||||
DBG_TCM_HEAP_INFO("tcm_alloc:%p[%d]\n", chunk, size);
|
||||
return (void *)chunk;
|
||||
}
|
||||
}
|
||||
rtw_exit_critical(&tcm_lock, &irqL);
|
||||
DBG_TCM_HEAP_WARN("tcm_alloc(%d) - freeSpace(%d)!\n", size, tcm_heap_freeSpace());
|
||||
return NULL; /* fail */
|
||||
}
|
||||
|
||||
static void tcm_heap_freemem(void *mem, int size)
|
||||
{
|
||||
MemChunk *prev;
|
||||
//ASSERT(mem);
|
||||
struct Heap* h = &g_tcm_heap;
|
||||
_irqL irqL;
|
||||
|
||||
rtw_enter_critical(&tcm_lock, &irqL);
|
||||
|
||||
// if(!g_heap_inited) tcm_heap_init();
|
||||
|
||||
#ifdef _DEBUG
|
||||
memset(mem, FREE_FILL_CODE, size);
|
||||
#endif
|
||||
|
||||
/* Round size up to the allocation granularity */
|
||||
size = ROUND_UP2(size, sizeof(MemChunk));
|
||||
|
||||
/* Handle allocations of 0 bytes */
|
||||
if (!size)
|
||||
size = sizeof(MemChunk);
|
||||
|
||||
/* Special cases: first chunk in the free list or memory completely full */
|
||||
//ASSERT((uint8_t*)mem != (uint8_t*)h->FreeList);
|
||||
if (((uint8_t *)mem) < ((uint8_t *)h->FreeList) || !h->FreeList)
|
||||
{
|
||||
/* Insert memory block before the current free list head */
|
||||
prev = (MemChunk *)mem;
|
||||
prev->next = h->FreeList;
|
||||
prev->size = size;
|
||||
h->FreeList = prev;
|
||||
}
|
||||
else /* Normal case: not the first chunk in the free list */
|
||||
{
|
||||
/*
|
||||
* Walk on the free list. Stop at the insertion point (when mem
|
||||
* is between prev and prev->next)
|
||||
*/
|
||||
prev = h->FreeList;
|
||||
while (prev->next < (MemChunk *)mem && prev->next)
|
||||
prev = prev->next;
|
||||
|
||||
/* Make sure mem is not *within* prev */
|
||||
//ASSERT((uint8_t*)mem >= (uint8_t*)prev + prev->size);
|
||||
|
||||
/* Should it be merged with previous block? */
|
||||
if (((uint8_t *)prev) + prev->size == ((uint8_t *)mem))
|
||||
{
|
||||
/* Yes */
|
||||
prev->size += size;
|
||||
}
|
||||
else /* not merged with previous chunk */
|
||||
{
|
||||
MemChunk *curr = (MemChunk*)mem;
|
||||
|
||||
/* insert it after the previous node
|
||||
* and move the 'prev' pointer forward
|
||||
* for the following operations
|
||||
*/
|
||||
curr->next = prev->next;
|
||||
curr->size = size;
|
||||
prev->next = curr;
|
||||
|
||||
/* Adjust for the following test */
|
||||
prev = curr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Also merge with next chunk? */
|
||||
if (((uint8_t *)prev) + prev->size == ((uint8_t *)prev->next))
|
||||
{
|
||||
prev->size += prev->next->size;
|
||||
prev->next = prev->next->next;
|
||||
|
||||
/* There should be only one merge opportunity, becuase we always merge on free */
|
||||
//ASSERT((uint8_t*)prev + prev->size != (uint8_t*)prev->next);
|
||||
}
|
||||
|
||||
rtw_exit_critical(&tcm_lock, &irqL);
|
||||
DBG_TCM_HEAP_INFO("tcm_free:%p[%d]\n", mem, size);
|
||||
}
|
||||
|
||||
int tcm_heap_freeSpace(void)
|
||||
{
|
||||
int free_mem = 0;
|
||||
struct Heap* h = &g_tcm_heap;
|
||||
_irqL irqL;
|
||||
MemChunk *chunk;
|
||||
|
||||
rtw_enter_critical(&tcm_lock, &irqL);
|
||||
|
||||
if(!g_heap_inited) tcm_heap_init();
|
||||
|
||||
for (chunk = h->FreeList; chunk; chunk = chunk->next)
|
||||
free_mem += chunk->size;
|
||||
|
||||
rtw_exit_critical(&tcm_lock, &irqL);
|
||||
return free_mem;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Standard malloc interface
|
||||
*/
|
||||
void *tcm_heap_malloc(int size)
|
||||
{
|
||||
int *mem;
|
||||
|
||||
size += sizeof(int);
|
||||
if ((mem = (int*)tcm_heap_allocmem(size))){
|
||||
*mem++ = size;
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard calloc interface
|
||||
*/
|
||||
void *tcm_heap_calloc(int size)
|
||||
{
|
||||
void *mem;
|
||||
|
||||
if ((mem = tcm_heap_malloc(size)))
|
||||
memset(mem, 0, size);
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a block of memory, determining its size automatically.
|
||||
*
|
||||
* \param h Heap from which the block was allocated.
|
||||
* \param mem Pointer to a block of memory previously allocated with
|
||||
* either heap_malloc() or heap_calloc().
|
||||
*
|
||||
* \note If \a mem is a NULL pointer, no operation is performed.
|
||||
*
|
||||
* \note Freeing the same memory block twice has undefined behavior.
|
||||
*
|
||||
* \note This function works like the ANSI C free().
|
||||
*/
|
||||
void tcm_heap_free(void *mem)
|
||||
{
|
||||
int *_mem = (int *)mem;
|
||||
|
||||
if (_mem)
|
||||
{
|
||||
--_mem;
|
||||
tcm_heap_freemem(_mem, *_mem);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
//----------- Tests -------------
|
||||
static void alloc_test(int size, int test_len)
|
||||
{
|
||||
//Simple test
|
||||
uint8_t *a[100];
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < test_len; i++)
|
||||
{
|
||||
a[i] = tcm_heap_allocmem(size);
|
||||
//ASSERT(a[i]);
|
||||
for (j = 0; j < size; j++)
|
||||
a[i][j] = i;
|
||||
}
|
||||
|
||||
//ASSERT(heap_freeSpace(&h) == HEAP_SIZE - test_len * ROUND_UP2(size, sizeof(MemChunk)));
|
||||
|
||||
for (i = 0; i < test_len; i++)
|
||||
{
|
||||
for (j = 0; j < size; j++)
|
||||
{
|
||||
DBG_8195A("a[%d][%d] = %d\n", i, j, a[i][j]);
|
||||
//ASSERT(a[i][j] == i);
|
||||
}
|
||||
tcm_heap_freemem(a[i], size);
|
||||
}
|
||||
//ASSERT(heap_freeSpace(&h) == HEAP_SIZE);
|
||||
}
|
||||
|
||||
#define ALLOC_SIZE 256
|
||||
#define ALLOC_SIZE2 1024
|
||||
#define TEST_LEN 20
|
||||
#define TEST_LEN2 10
|
||||
#define HEAP_SIZE 59*1024
|
||||
int tcm_heap_testRun(void)
|
||||
{
|
||||
alloc_test(ALLOC_SIZE, TEST_LEN);
|
||||
alloc_test(ALLOC_SIZE2, TEST_LEN2);
|
||||
/* Try to allocate the whole heap */
|
||||
uint8_t *b = tcm_heap_allocmem(HEAP_SIZE);
|
||||
int i, j;
|
||||
//ASSERT(b);
|
||||
//ASSERT(heap_freeSpace(&h) == 0);
|
||||
|
||||
//ASSERT(!heap_allocmem(&h, HEAP_SIZE));
|
||||
|
||||
for (j = 0; j < HEAP_SIZE; j++)
|
||||
b[j] = j;
|
||||
|
||||
for (j = 0; j < HEAP_SIZE; j++)
|
||||
{
|
||||
DBG_8195A("b[%d] = %d\n", j, j);
|
||||
//ASSERT(b[j] == (j & 0xff));
|
||||
}
|
||||
tcm_heap_freemem(b, HEAP_SIZE);
|
||||
//ASSERT(heap_freeSpace(&h) == HEAP_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif // tests
|
||||
|
||||
#endif
|
||||
1109
Firmware/RTLGDB/USDK/component/os/rtx/rtx_service.c
Normal file
1109
Firmware/RTLGDB/USDK/component/os/rtx/rtx_service.c
Normal file
File diff suppressed because it is too large
Load diff
309
Firmware/RTLGDB/USDK/component/os/rtx/rtx_service.h
Normal file
309
Firmware/RTLGDB/USDK/component/os/rtx/rtx_service.h
Normal file
|
|
@ -0,0 +1,309 @@
|
|||
#ifndef _RTX_SERVICE_H_
|
||||
#define _RTX_SERVICE_H_
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Include Files
|
||||
//-----------------------------------------------------------------------
|
||||
#include "wireless.h"
|
||||
#include "dlist.h"
|
||||
#include <cmsis_os.h>
|
||||
#include <rt_TypeDef.h>
|
||||
#include "RTX_Config.h"
|
||||
#include <rt_Task.h>
|
||||
#include <rt_Semaphore.h>
|
||||
#include <rt_System.h>
|
||||
|
||||
// --------------------------------------------
|
||||
// Platform dependent include file
|
||||
// --------------------------------------------
|
||||
#if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B)
|
||||
//#include "platform_stdlib.h"
|
||||
//#include "basic_types.h"
|
||||
#include <rtl8195a.h>
|
||||
#else
|
||||
// other MCU may use standard library
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
|
||||
#if (defined CONFIG_GSPI_HCI || defined CONFIG_SDIO_HCI) || defined(CONFIG_LX_HCI)
|
||||
/* For SPI interface transfer and us delay implementation */
|
||||
#if !defined(CONFIG_PLATFORM_8195A) && !defined(CONFIG_PLATFORM_8711B)
|
||||
#include <rtwlan_bsp.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// --------------------------------------------
|
||||
// Platform dependent type define
|
||||
// --------------------------------------------
|
||||
#if !defined(CONFIG_PLATFORM_8195A) && !defined(CONFIG_PLATFORM_8711B)
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
typedef signed char s8;
|
||||
typedef signed short s16;
|
||||
typedef signed int s32;
|
||||
typedef signed long long s64;
|
||||
typedef unsigned long long u64;
|
||||
typedef unsigned int uint;
|
||||
typedef signed int sint;
|
||||
|
||||
#ifndef bool
|
||||
typedef int bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#define IN
|
||||
#define OUT
|
||||
#define VOID void
|
||||
#define NDIS_OID uint
|
||||
#define NDIS_STATUS uint
|
||||
#ifndef PVOID
|
||||
typedef void * PVOID;
|
||||
#endif
|
||||
|
||||
typedef unsigned int __kernel_size_t;
|
||||
typedef int __kernel_ssize_t;
|
||||
typedef __kernel_size_t SIZE_T;
|
||||
typedef __kernel_ssize_t SSIZE_T;
|
||||
|
||||
#endif //CONFIG_PLATFORM_8195A
|
||||
|
||||
// === SEMAPHORE ===
|
||||
typedef struct {
|
||||
osSemaphoreId id;
|
||||
osSemaphoreDef_t def;
|
||||
#ifdef CMSIS_OS_RTX
|
||||
uint32_t data[2];
|
||||
#endif
|
||||
} rtx_sema_t;
|
||||
|
||||
// === THREAD ===
|
||||
typedef struct {
|
||||
osThreadId id;
|
||||
osThreadDef_t def;
|
||||
} rtx_thread_data_t;
|
||||
|
||||
// === MUTEX ===
|
||||
typedef struct {
|
||||
osMutexId id;
|
||||
osMutexDef_t def;
|
||||
#ifdef CMSIS_OS_RTX
|
||||
#if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM)
|
||||
int32_t data[4];
|
||||
#else
|
||||
int32_t data[3];
|
||||
#endif
|
||||
#endif
|
||||
} rtx_mutex_t;
|
||||
|
||||
// === MAIL BOX ===
|
||||
#define RTX_MB_SIZE 8
|
||||
|
||||
typedef struct {
|
||||
osMessageQId id;
|
||||
osMessageQDef_t def;
|
||||
#ifdef CMSIS_OS_RTX
|
||||
uint32_t queue; /* The (queue_size+4)*sizeof(uint32_t) is required for RTX OS_MCB overhead. */
|
||||
#endif
|
||||
} rtx_mqueue_t;
|
||||
|
||||
typedef struct {
|
||||
osMailQId id;
|
||||
osMailQDef_t def;
|
||||
#ifdef CMSIS_OS_RTX
|
||||
uint32_t os_mailQ_q; /* memory block, (4+queue_size)*sizeof(uint32_t)*/
|
||||
uint32_t os_mailQ_m; /* memory block, (3 + (item_size+3)/4)*queue_size*/
|
||||
void * os_mailQ_p[2];
|
||||
#endif
|
||||
} rtx_mbox_t;
|
||||
|
||||
typedef struct{
|
||||
osTimerId id;
|
||||
osTimerDef_t def;
|
||||
#if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM)
|
||||
uint32_t data[5];
|
||||
#else
|
||||
uint32_t data[6];
|
||||
#endif
|
||||
}rtx_tmr_t;
|
||||
|
||||
#define FIELD_OFFSET(s,field) ((SSIZE_T)&((s*)(0))->field)
|
||||
|
||||
// os types
|
||||
typedef char osdepCHAR;
|
||||
typedef float osdepFLOAT;
|
||||
typedef double osdepDOUBLE;
|
||||
typedef long osdepLONG;
|
||||
typedef short osdepSHORT;
|
||||
typedef unsigned long osdepSTACK_TYPE;
|
||||
typedef long osdepBASE_TYPE;
|
||||
typedef unsigned long osdepTickType;
|
||||
|
||||
typedef void * _timerHandle;
|
||||
typedef void * _sema;
|
||||
typedef void * _mutex;
|
||||
typedef void * _lock;
|
||||
typedef void * _queueHandle;
|
||||
typedef void * _xqueue;
|
||||
typedef struct timer_list _timer;
|
||||
|
||||
typedef struct sk_buff _pkt;
|
||||
typedef unsigned char _buffer;
|
||||
|
||||
#ifndef __LIST_H
|
||||
#warning "DLIST_NOT_DEFINE!!!!!!"
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct __queue {
|
||||
struct list_head queue;
|
||||
_lock lock;
|
||||
};
|
||||
|
||||
typedef struct __queue _queue;
|
||||
typedef struct list_head _list;
|
||||
typedef unsigned long _irqL;
|
||||
|
||||
typedef void* _thread_hdl_;
|
||||
typedef void thread_return;
|
||||
typedef void* thread_context;
|
||||
|
||||
#define ATOMIC_T atomic_t
|
||||
#define HZ configTICK_RATE_HZ
|
||||
|
||||
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
|
||||
/* emulate a modern version */
|
||||
#define LINUX_VERSION_CODE KERNEL_VERSION(2, 6, 17)
|
||||
|
||||
static __inline _list *get_next(_list *list)
|
||||
{
|
||||
return list->next;
|
||||
}
|
||||
|
||||
static __inline _list *get_list_head(_queue *queue)
|
||||
{
|
||||
return (&(queue->queue));
|
||||
}
|
||||
|
||||
#define LIST_CONTAINOR(ptr, type, member) \
|
||||
((type *)((char *)(ptr)-(SIZE_T)((char *)&((type *)ptr)->member - (char *)ptr)))
|
||||
//#define container_of(p,t,n) (t*)((p)-&(((t*)0)->n))
|
||||
#define container_of(ptr, type, member) \
|
||||
((type *)((char *)(ptr)-(SIZE_T)(&((type *)0)->member)))
|
||||
#define TASK_PRORITY_LOW osPriorityAboveNormal//osPriorityNormal
|
||||
#define TASK_PRORITY_MIDDLE osPriorityHigh//osPriorityAboveNormal
|
||||
#define TASK_PRORITY_HIGH osPriorityRealtime//osPriorityHigh
|
||||
#define TASK_PRORITY_SUPER osPriorityRealtime
|
||||
#define TASK_PRORITY_IDEL osPriorityIdle
|
||||
|
||||
|
||||
#define TIMER_MAX_DELAY 0xFFFFFFFF
|
||||
void save_and_cli(void);
|
||||
void restore_flags(void);
|
||||
void cli(void);
|
||||
|
||||
//----- ------------------------------------------------------------------
|
||||
// Common Definition
|
||||
//----- ------------------------------------------------------------------
|
||||
|
||||
#define __init
|
||||
#define __exit
|
||||
#define __devinit
|
||||
#define __devexit
|
||||
|
||||
#define KERN_ERR
|
||||
#define KERN_INFO
|
||||
#define KERN_NOTICE
|
||||
|
||||
#define GFP_KERNEL 1
|
||||
#define GFP_ATOMIC 1
|
||||
|
||||
#define SET_MODULE_OWNER(some_struct) do { } while (0)
|
||||
#define SET_NETDEV_DEV(dev, obj) do { } while (0)
|
||||
#define register_netdev(dev) (0)
|
||||
#define unregister_netdev(dev) do { } while (0)
|
||||
#define netif_queue_stopped(dev) (0)
|
||||
#define netif_wake_queue(dev) do { } while (0)
|
||||
#define printk printf
|
||||
|
||||
#define DBG_ERR(fmt, args...) printf("\n\r[%s] " fmt, __FUNCTION__, ## args)
|
||||
#if WLAN_INTF_DBG
|
||||
#define DBG_TRACE(fmt, args...) printf("\n\r[%s] " fmt, __FUNCTION__, ## args)
|
||||
#define DBG_INFO(fmt, args...) printf("\n\r[%s] " fmt, __FUNCTION__, ## args)
|
||||
#else
|
||||
#define DBG_TRACE(fmt, args...)
|
||||
#define DBG_INFO(fmt, args...)
|
||||
#endif
|
||||
#define HALT() do { cli(); for(;;);} while(0)
|
||||
#define ASSERT(x) do { \
|
||||
if((x) == 0) \
|
||||
printf("\n\rAssert(" #x ") failed on line %d in file %s", __LINE__, __FILE__); \
|
||||
HALT(); \
|
||||
} while(0)
|
||||
|
||||
#undef DBG_ASSERT
|
||||
#define DBG_ASSERT(x, msg) do { \
|
||||
if((x) == 0) \
|
||||
printf("\n\r%s, Assert(" #x ") failed on line %d in file %s", msg, __LINE__, __FILE__); \
|
||||
} while(0)
|
||||
|
||||
//----- ------------------------------------------------------------------
|
||||
// Atomic Operation
|
||||
//----- ------------------------------------------------------------------
|
||||
#if !defined(CONFIG_PLATFORM_8195A) && !defined(CONFIG_PLATFORM_8711B) // for 8195A, it is defined in ..system../basic_types.h
|
||||
typedef struct { volatile int counter; } atomic_t;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* atomic_read - read atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
*
|
||||
* Atomically reads the value of @v. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#define atomic_read(v) ((v)->counter)
|
||||
|
||||
/*
|
||||
* atomic_set - set atomic variable
|
||||
* @v: pointer of type atomic_t
|
||||
* @i: required value
|
||||
*
|
||||
* Atomically sets the value of @v to @i. Note that the guaranteed
|
||||
* useful range of an atomic_t is only 24 bits.
|
||||
*/
|
||||
#define atomic_set(v,i) ((v)->counter = (i))
|
||||
|
||||
/*
|
||||
* These inlines deal with timer wrapping correctly. You are
|
||||
* strongly encouraged to use them
|
||||
* 1. Because people otherwise forget
|
||||
* 2. Because if the timer wrap changes in future you wont have to
|
||||
* alter your driver code.
|
||||
*
|
||||
* time_after(a,b) returns true if the time a is after time b.
|
||||
*
|
||||
* Do this with "<0" and ">=0" to only test the sign of the result. A
|
||||
* good compiler would generate better code (and a really good compiler
|
||||
* wouldn't care). Gcc is currently neither.
|
||||
*/
|
||||
#define time_after(a,b) ((long)(b) - (long)(a) < 0)
|
||||
#define time_before(a,b) time_after(b,a)
|
||||
|
||||
#define time_after_eq(a,b) ((long)(a) - (long)(b) >= 0)
|
||||
#define time_before_eq(a,b) time_after_eq(b,a)
|
||||
|
||||
|
||||
extern void rtw_init_listhead(_list *list);
|
||||
extern u32 rtw_is_list_empty(_list *phead);
|
||||
extern void rtw_list_insert_head(_list *plist, _list *phead);
|
||||
extern void rtw_list_insert_tail(_list *plist, _list *phead);
|
||||
extern void rtw_list_delete(_list *plist);
|
||||
#define vPortExitCritical save_and_cli
|
||||
#endif /* _RTX_SERVICE_H_ */
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue