initial commit

This commit is contained in:
2024-12-15 00:34:01 +06:00
commit 31efbc726f
1576 changed files with 657692 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,816 @@
/* ----------------------------------------------------------------------
* $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 = \
{ (os_pthread)(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
#define malloc pvPortMalloc
#define free vPortFree
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

View File

@@ -0,0 +1,157 @@
#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;
#endif
#ifdef CONFIG_PLATFORM_8711B
typedef enum {
PMU_OS =0,
PMU_UART0_DEVICE =1,
PMU_UART1_DEVICE =2,
PMU_WLAN_DEVICE =3,
PMU_LOGUART_DEVICE =4,
PMU_SDIO_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_WAKWLOCK_TIMEOUT=13,
PMU_IPS_DEVICE =14,
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);
/** 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);
/** Acquire wakelock from isr
*
* 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_from_isr(uint32_t nDeviceId);
/** Release wakelock from isr
*
* 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_from_isr(uint32_t nDeviceId);
/** Get current wakelock bit map value
*
* @return : the current wakelock bit map value
*/
uint32_t pmu_get_wakelock_status(void);
#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
* @param BufferSize : The maximum size of buffer
*/
void pmu_get_wakelock_hold_stats( char *pcWriteBuffer, unsigned int BufferSize );
/** 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 timeout_ms);
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

View File

@@ -0,0 +1,912 @@
/* 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>
/********************* 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(u64 *n, unsigned int base)
{
u64 rem = *n;
u64 b = base;
u64 res, d = 1;
unsigned int high = rem >> 32;
/* Reduce the thing a bit first */
res = 0;
if (high >= base) {
high /= base;
res = (u64) high << 32;
rem -= (u64) (high * base) << 32;
}
while ((u64)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 ********************/
u8* _freertos_malloc(u32 sz)
{
return pvPortMalloc(sz);
}
u8* _freertos_zmalloc(u32 sz)
{
u8 *pbuf = _freertos_malloc(sz);
if (pbuf != NULL)
memset(pbuf, 0, sz);
return pbuf;
}
void _freertos_mfree(u8 *pbuf, u32 sz)
{
vPortFree(pbuf);
}
static void _freertos_memcpy(void* dst, void* src, u32 sz)
{
memcpy(dst, src, sz);
}
static int _freertos_memcmp(void *dst, void *src, u32 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, u32 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 u32 _freertos_down_sema(_sema *sema, u32 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, u32 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 u32 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, u32 message_size, u32 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, u32 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, u32 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_peek_from_xqueue( _xqueue* queue, void* message, u32 timeout_ms )
{
if(timeout_ms == RTW_WAIT_FOREVER) {
timeout_ms = portMAX_DELAY;
} else {
timeout_ms = rtw_ms_to_systime(timeout_ms);
}
if ( xQueuePeek( *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 u32 _freertos_get_current_time(void)
{
return xTaskGetTickCount(); //The count of ticks since vTaskStartScheduler was called.
}
static u32 _freertos_systime_to_ms(u32 systime)
{
return systime * portTICK_RATE_MS;
}
static u32 _freertos_systime_to_sec(u32 systime)
{
return systime / configTICK_RATE_HZ;
}
static u32 _freertos_ms_to_systime(u32 ms)
{
return ms / portTICK_RATE_MS;
}
static u32 _freertos_sec_to_systime(u32 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
}
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)
//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)
{
#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
}
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);
#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 u64 _freertos_modular64(u64 n, u64 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)
{
u32 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 u32 _freertos_GetFreeHeapSize(void)
{
return (u32)xPortGetFreeHeapSize();
}
void *tcm_heap_malloc(int size);
static int _freertos_create_task(struct task_struct *ptask, const char *name,
u32 stack_size, u32 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 + PRIORITY_OFFSET;
if(rtw_if_wifi_thread(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,
u32 uxAutoReload,
void * pvTimerID,
TIMER_FUN pxCallbackFunction )
{
if(xTimerPeriodInTicks == TIMER_MAX_DELAY) {
xTimerPeriodInTicks = portMAX_DELAY;
}
return xTimerCreate((const char *)pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction);
}
u32 _freertos_timerDelete( _timerHandle xTimer,
osdepTickType xBlockTime )
{
return (u32)xTimerDelete(xTimer, xBlockTime);
}
u32 _freertos_timerIsTimerActive( _timerHandle xTimer )
{
return (u32)xTimerIsTimerActive(xTimer);
}
u32 _freertos_timerStop( _timerHandle xTimer,
osdepTickType xBlockTime )
{
return (u32)xTimerStop(xTimer, xBlockTime);
}
u32 _freertos_timerChangePeriod( _timerHandle xTimer,
osdepTickType xNewPeriod,
osdepTickType xBlockTime )
{
if(xNewPeriod == 0)
xNewPeriod += 1;
return (u32)xTimerChangePeriod(xTimer, xNewPeriod, xBlockTime);
}
void *_freertos_timerGetID( _timerHandle xTimer ){
return pvTimerGetTimerID(xTimer);
}
u32 _freertos_timerStart( _timerHandle xTimer,
osdepTickType xBlockTime )
{
return (u32)xTimerStart(xTimer, xBlockTime);
}
u32 _freertos_timerStartFromISR( _timerHandle xTimer,
osdepBASE_TYPE *pxHigherPriorityTaskWoken )
{
return (u32)xTimerStartFromISR(xTimer, pxHigherPriorityTaskWoken);
}
u32 _freertos_timerStopFromISR( _timerHandle xTimer,
osdepBASE_TYPE *pxHigherPriorityTaskWoken )
{
return (u32)xTimerStopFromISR(xTimer, pxHigherPriorityTaskWoken);
}
u32 _freertos_timerResetFromISR( _timerHandle xTimer,
osdepBASE_TYPE *pxHigherPriorityTaskWoken )
{
return (u32)xTimerResetFromISR(xTimer, pxHigherPriorityTaskWoken);
}
u32 _freertos_timerChangePeriodFromISR( _timerHandle xTimer,
osdepTickType xNewPeriod,
osdepBASE_TYPE *pxHigherPriorityTaskWoken )
{
if(xNewPeriod == 0)
xNewPeriod += 1;
return (u32)xTimerChangePeriodFromISR(xTimer, xNewPeriod, pxHigherPriorityTaskWoken);
}
u32 _freertos_timerReset( _timerHandle xTimer,
osdepTickType xBlockTime )
{
return (u32)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(timeout);
else
DBG_INFO("can't aquire wake during suspend flow!!\n");
#endif
}
u8 _freertos_get_scheduler_state(void)
{
u8 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_peek_from_xqueue, //rtw_peek_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
};

View File

@@ -0,0 +1,263 @@
#ifndef _FREERTOS_SERVICE_H_
#define _FREERTOS_SERVICE_H_
//----- ------------------------------------------------------------------
// Include Files
//----- ------------------------------------------------------------------
//#include "wireless.h"
#include "dlist.h"
#include "FreeRTOS.h"
#include "task.h"
#include "event_groups.h"
#include "semphr.h"
#include "queue.h"
#include "timers.h"
// --------------------------------------------
// Platform dependent include file
// --------------------------------------------
#if defined(CONFIG_PLATFORM_8195A)
#include "platform/platform_stdlib.h"
extern VOID RtlUdelayOS(u32 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 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
#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 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);
#if CONFIG_PLATFORM_8711B
extern u32 random_seed;
#endif
#endif /* _FREERTOS_SERVICE_H_ */

View File

@@ -0,0 +1,64 @@
/*
* 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 u32 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]);
}

View File

@@ -0,0 +1,26 @@
/*
* 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_WLAN = 4,
RT_DEV_LOCK_MAX = 5
}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_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
#ifndef STRUCT_HEAP_H
#define STRUCT_HEAP_H
//#include <stdio.h>
#include <stdint.h>
#include <osdep_service.h>
/* 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))
/**
* \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);
/** \} */
#endif /* STRUCT_HEAP_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,352 @@
//#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))
#define TCM_HEAP_SIZE (40*1024)
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_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)
{
MemChunk *chunk, *prev;
struct Heap* h = &g_tcm_heap;
printf("---Free List--\n\r");
for (prev = (MemChunk *)&h->FreeList, chunk = h->FreeList;
chunk;
prev = chunk, chunk = chunk->next)
{
printf(" prev %x, chunk %x, size %d \n\r", prev, chunk, chunk->size);
}
printf("--------------\n\r");
}
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;
#ifdef _DEBUG
memset(chunk, ALLOC_FILL_CODE, size);
#endif
rtw_exit_critical(&tcm_lock, &irqL);
//printf("----ALLOC1-----\n\r");
//tcm_heap_dump();
//printf("--------------\n\r");
return (void *)chunk;
}
else
{
/* Allocate from the END of an existing chunk */
chunk->size -= size;
#ifdef _DEBUG
memset((uint8_t *)chunk + chunk->size, ALLOC_FILL_CODE, size);
#endif
rtw_exit_critical(&tcm_lock, &irqL);
//printf("----ALLOC2-----\n\r");
//tcm_heap_dump();
//printf("--------------\n\r");
return (void *)((uint8_t *)chunk + chunk->size);
}
}
}
rtw_exit_critical(&tcm_lock, &irqL);
//printf("----ALLOC3-----\n\r");
//tcm_heap_dump();
//printf("--------------\n\r");
return NULL; /* fail */
}
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);
//printf("---FREE %x--\n\r", mem);
//tcm_heap_dump();
//printf("--------------\n\r");
}
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);
}
}
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++)
{
printf("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++)
{
printf("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