update IDF libraries and includes

This commit is contained in:
me-no-dev
2016-10-28 01:53:02 +03:00
parent 261bc5ae85
commit 3c071e1d89
74 changed files with 1952 additions and 349 deletions

View File

@ -74,6 +74,7 @@
* Include the generic headers required for the FreeRTOS port being used.
*/
#include <stddef.h>
#include "sys/reent.h"
/*
* If stdint.h cannot be located then:
@ -739,6 +740,20 @@ extern "C" {
#define portTICK_TYPE_IS_ATOMIC 0
#endif
#ifndef configSUPPORT_STATIC_ALLOCATION
/* Defaults to 0 for backward compatibility. */
#define configSUPPORT_STATIC_ALLOCATION 0
#endif
#ifndef configSUPPORT_DYNAMIC_ALLOCATION
/* Defaults to 1 for backward compatibility. */
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#endif
#if( ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) )
#error configSUPPORT_STATIC_ALLOCATION and configSUPPORT_DYNAMIC_ALLOCATION cannot both be 0, but can both be 1.
#endif
#if( portTICK_TYPE_IS_ATOMIC == 0 )
/* Either variables of tick type cannot be read atomically, or
portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when
@ -791,6 +806,153 @@ V8 if desired. */
#define configESP32_PER_TASK_DATA 1
#endif
/*
* In line with software engineering best practice, FreeRTOS implements a strict
* data hiding policy, so the real structures used by FreeRTOS to maintain the
* state of tasks, queues, semaphores, etc. are not accessible to the application
* code. However, if the application writer wants to statically allocate such
* an object then the size of the object needs to be know. Dummy structures
* that are guaranteed to have the same size and alignment requirements of the
* real objects are used for this purpose. The dummy list and list item
* structures below are used for inclusion in such a dummy structure.
*/
struct xSTATIC_LIST_ITEM
{
TickType_t xDummy1;
void *pvDummy2[ 4 ];
};
typedef struct xSTATIC_LIST_ITEM StaticListItem_t;
/* See the comments above the struct xSTATIC_LIST_ITEM definition. */
struct xSTATIC_MINI_LIST_ITEM
{
TickType_t xDummy1;
void *pvDummy2[ 2 ];
};
typedef struct xSTATIC_MINI_LIST_ITEM StaticMiniListItem_t;
/* See the comments above the struct xSTATIC_LIST_ITEM definition. */
typedef struct xSTATIC_LIST
{
UBaseType_t uxDummy1;
void *pvDummy2;
StaticMiniListItem_t xDummy3;
} StaticList_t;
/*
* In line with software engineering best practice, especially when supplying a
* library that is likely to change in future versions, FreeRTOS implements a
* strict data hiding policy. This means the Task structure used internally by
* FreeRTOS is not accessible to application code. However, if the application
* writer wants to statically allocate the memory required to create a task then
* the size of the task object needs to be know. The StaticTask_t structure
* below is provided for this purpose. Its sizes and alignment requirements are
* guaranteed to match those of the genuine structure, no matter which
* architecture is being used, and no matter how the values in FreeRTOSConfig.h
* are set. Its contents are somewhat obfuscated in the hope users will
* recognise that it would be unwise to make direct use of the structure members.
*/
typedef struct xSTATIC_TCB
{
void *pxDummy1;
#if ( portUSING_MPU_WRAPPERS == 1 )
xMPU_SETTINGS xDummy2;
#endif
StaticListItem_t xDummy3[ 2 ];
UBaseType_t uxDummy5;
void *pxDummy6;
uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ];
UBaseType_t uxDummyCoreId;
#if ( portSTACK_GROWTH > 0 )
void *pxDummy8;
#endif
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
UBaseType_t uxDummy9;
uint32_t OldInterruptState;
#endif
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxDummy10[ 2 ];
#endif
#if ( configUSE_MUTEXES == 1 )
UBaseType_t uxDummy12[ 2 ];
#endif
#if ( configUSE_APPLICATION_TASK_TAG == 1 )
void *pxDummy14;
#endif
#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
void *pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
#if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS )
void *pvDummyLocalStorageCallBack[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
#endif
#endif
#if ( configGENERATE_RUN_TIME_STATS == 1 )
uint32_t ulDummy16;
#endif
#if ( configUSE_NEWLIB_REENTRANT == 1 )
struct _reent xDummy17;
#endif
#if ( configUSE_TASK_NOTIFICATIONS == 1 )
uint32_t ulDummy18;
uint32_t ucDummy19;
#endif
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
uint8_t uxDummy20;
#endif
} StaticTask_t;
/*
* In line with software engineering best practice, especially when supplying a
* library that is likely to change in future versions, FreeRTOS implements a
* strict data hiding policy. This means the Queue structure used internally by
* FreeRTOS is not accessible to application code. However, if the application
* writer wants to statically allocate the memory required to create a queue
* then the size of the queue object needs to be know. The StaticQueue_t
* structure below is provided for this purpose. Its sizes and alignment
* requirements are guaranteed to match those of the genuine structure, no
* matter which architecture is being used, and no matter how the values in
* FreeRTOSConfig.h are set. Its contents are somewhat obfuscated in the hope
* users will recognise that it would be unwise to make direct use of the
* structure members.
*/
typedef struct xSTATIC_QUEUE
{
void *pvDummy1[ 3 ];
union
{
void *pvDummy2;
UBaseType_t uxDummy2;
} u;
StaticList_t xDummy3[ 2 ];
UBaseType_t uxDummy4[ 3 ];
BaseType_t ucDummy5[ 2 ];
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
uint8_t ucDummy6;
#endif
#if ( configUSE_QUEUE_SETS == 1 )
void *pvDummy7;
#endif
#if ( configUSE_TRACE_FACILITY == 1 )
UBaseType_t uxDummy8;
uint8_t ucDummy9;
#endif
struct {
volatile uint32_t mux;
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
const char *lastLockedFn;
int lastLockedLine;
#endif
} mux;
} StaticQueue_t;
typedef StaticQueue_t StaticSemaphore_t;
#ifdef __cplusplus
}
#endif

View File

@ -152,9 +152,9 @@
*----------------------------------------------------------*/
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_IDLE_HOOK ( CONFIG_TASK_WDT_CHECK_IDLE_TASK )
#define configUSE_TICK_HOOK 0
#define configUSE_TICK_HOOK ( CONFIG_INT_WDT )
#define configTICK_RATE_HZ ( CONFIG_FREERTOS_HZ )
@ -231,6 +231,7 @@
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define INCLUDE_pcTaskGetTaskName 1
#if CONFIG_ENABLE_MEMORY_DEBUG
#define configENABLE_MEMORY_DEBUG 1
@ -251,6 +252,8 @@
#define configUSE_NEWLIB_REENTRANT 1
#define configSUPPORT_DYNAMIC_ALLOCATION 1
/* Test FreeRTOS timers (with timer task) and more. */
/* Some files don't compile if this flag is disabled */
#define configUSE_TIMERS 1

View File

@ -1,7 +0,0 @@
#ifndef PANIC_H
#define PANIC_H
void setBreakpointIfJtag(void *fn);
#endif

View File

@ -192,8 +192,14 @@ void vPortEndScheduler( void ) PRIVILEGED_FUNCTION;
#endif
/* Multi-core: get current core ID */
int xPortGetCoreID( void );
static inline uint32_t xPortGetCoreID() {
int id;
asm volatile(
"rsr.prid %0\n"
" extui %0,%0,13,1"
:"=r"(id));
return id;
}
#ifdef __cplusplus
}

View File

@ -225,6 +225,26 @@ static inline unsigned portENTER_CRITICAL_NESTED() { unsigned state = XTOS_SET_I
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(state) portEXIT_CRITICAL_NESTED(state)
/*
* Wrapper for the Xtensa compare-and-set instruction. This subroutine will atomically compare
* *mux to compare, and if it's the same, will set *mux to set. It will return the old value
* of *addr in *set.
*
* Warning: From the ISA docs: in some (unspecified) cases, the s32c1i instruction may return the
* *bitwise inverse* of the old mem if the mem wasn't written. This doesn't seem to happen on the
* ESP32, though. (Would show up directly if it did because the magic wouldn't match.)
*/
static inline void uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set) {
__asm__ __volatile__(
"WSR %2,SCOMPARE1 \n"
"ISYNC \n"
"S32C1I %0, %1, 0 \n"
:"=r"(*set)
:"r"(addr), "r"(compare), "0"(*set)
);
}
/*-----------------------------------------------------------*/
/* Architecture specifics. */

View File

@ -170,7 +170,95 @@ typedef void * QueueSetMemberHandle_t;
* \defgroup xQueueCreate xQueueCreate
* \ingroup QueueManagement
*/
#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( uxQueueLength, uxItemSize, queueQUEUE_TYPE_BASE )
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )
#endif
/**
* queue. h
* <pre>
QueueHandle_t xQueueCreateStatic(
UBaseType_t uxQueueLength,
UBaseType_t uxItemSize,
uint8_t *pucQueueStorageBuffer,
StaticQueue_t *pxQueueBuffer
);
* </pre>
*
* Creates a new queue instance, and returns a handle by which the new queue
* can be referenced.
*
* Internally, within the FreeRTOS implementation, queues use two blocks of
* memory. The first block is used to hold the queue's data structures. The
* second block is used to hold items placed into the queue. If a queue is
* created using xQueueCreate() then both blocks of memory are automatically
* dynamically allocated inside the xQueueCreate() function. (see
* http://www.freertos.org/a00111.html). If a queue is created using
* xQueueCreateStatic() then the application writer must provide the memory that
* will get used by the queue. xQueueCreateStatic() therefore allows a queue to
* be created without using any dynamic memory allocation.
*
* http://www.FreeRTOS.org/Embedded-RTOS-Queues.html
*
* @param uxQueueLength The maximum number of items that the queue can contain.
*
* @param uxItemSize The number of bytes each item in the queue will require.
* Items are queued by copy, not by reference, so this is the number of bytes
* that will be copied for each posted item. Each item on the queue must be
* the same size.
*
* @param pucQueueStorageBuffer If uxItemSize is not zero then
* pucQueueStorageBuffer must point to a uint8_t array that is at least large
* enough to hold the maximum number of items that can be in the queue at any
* one time - which is ( uxQueueLength * uxItemsSize ) bytes. If uxItemSize is
* zero then pucQueueStorageBuffer can be NULL.
*
* @param pxQueueBuffer Must point to a variable of type StaticQueue_t, which
* will be used to hold the queue's data structure.
*
* @return If the queue is created then a handle to the created queue is
* returned. If pxQueueBuffer is NULL then NULL is returned.
*
* Example usage:
<pre>
struct AMessage
{
char ucMessageID;
char ucData[ 20 ];
};
#define QUEUE_LENGTH 10
#define ITEM_SIZE sizeof( uint32_t )
// xQueueBuffer will hold the queue structure.
StaticQueue_t xQueueBuffer;
// ucQueueStorage will hold the items posted to the queue. Must be at least
// [(queue length) * ( queue item size)] bytes long.
uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ];
void vATask( void *pvParameters )
{
QueueHandle_t xQueue1;
// Create a queue capable of containing 10 uint32_t values.
xQueue1 = xQueueCreate( QUEUE_LENGTH, // The number of items the queue can hold.
ITEM_SIZE // The size of each item in the queue
&( ucQueueStorage[ 0 ] ), // The buffer that will hold the items in the queue.
&xQueueBuffer ); // The buffer that will hold the queue structure.
// The queue is guaranteed to be created successfully as no dynamic memory
// allocation is used. Therefore xQueue1 is now a handle to a valid queue.
// ... Rest of task code.
}
</pre>
* \defgroup xQueueCreateStatic xQueueCreateStatic
* \ingroup QueueManagement
*/
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
#define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer ) xQueueGenericCreateStatic( ( uxQueueLength ), ( uxItemSize ), ( pucQueueStorage ), ( pxQueueBuffer ), ( queueQUEUE_TYPE_BASE ) )
#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* queue. h
@ -1479,7 +1567,9 @@ BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTi
* these functions directly.
*/
QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION;
QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) PRIVILEGED_FUNCTION;
QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ) PRIVILEGED_FUNCTION;
void* xQueueGetMutexHolder( QueueHandle_t xSemaphore ) PRIVILEGED_FUNCTION;
/*
@ -1538,10 +1628,22 @@ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t pxMutex ) PRIVILEGED_FUNCTION
#endif
/*
* Generic version of the queue creation function, which is in turn called by
* any queue, semaphore or mutex creation function or macro.
* Generic version of the function used to creaet a queue using dynamic memory
* allocation. This is called by other functions and macros that create other
* RTOS objects that use the queue structure as their base.
*/
QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
#endif
/*
* Generic version of the function used to creaet a queue using dynamic memory
* allocation. This is called by other functions and macros that create other
* RTOS objects that use the queue structure as their base.
*/
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ) PRIVILEGED_FUNCTION;
#endif
/*
* Queue sets provide a mechanism to allow a task to block (pend) on a read

View File

@ -128,19 +128,37 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
* \ingroup Semaphores
*/
#define vSemaphoreCreateBinary( xSemaphore ) \
{ \
( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \
if( ( xSemaphore ) != NULL ) \
{ \
( void ) xSemaphoreGive( ( xSemaphore ) ); \
} \
}
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
#define vSemaphoreCreateBinary( xSemaphore ) \
{ \
( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \
if( ( xSemaphore ) != NULL ) \
{ \
( void ) xSemaphoreGive( ( xSemaphore ) ); \
} \
}
#endif
/**
* semphr. h
* <pre>SemaphoreHandle_t xSemaphoreCreateBinary( void )</pre>
*
* Creates a new binary semaphore instance, and returns a handle by which the
* new semaphore can be referenced.
*
* In many usage scenarios it is faster and more memory efficient to use a
* direct to task notification in place of a binary semaphore!
* http://www.freertos.org/RTOS-task-notifications.html
*
* Internally, within the FreeRTOS implementation, binary semaphores use a block
* of memory, in which the semaphore structure is stored. If a binary semaphore
* is created using xSemaphoreCreateBinary() then the required memory is
* automatically dynamically allocated inside the xSemaphoreCreateBinary()
* function. (see http://www.freertos.org/a00111.html). If a binary semaphore
* is created using xSemaphoreCreateBinaryStatic() then the application writer
* must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a
* binary semaphore to be created without using any dynamic memory allocation.
*
* The old vSemaphoreCreateBinary() macro is now deprecated in favour of this
* xSemaphoreCreateBinary() function. Note that binary semaphores created using
* the vSemaphoreCreateBinary() macro are created in a state such that the
@ -182,7 +200,68 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
* \ingroup Semaphores
*/
#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
#endif
/**
* semphr. h
* <pre>SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer )</pre>
*
* Creates a new binary semaphore instance, and returns a handle by which the
* new semaphore can be referenced.
*
* NOTE: In many usage scenarios it is faster and more memory efficient to use a
* direct to task notification in place of a binary semaphore!
* http://www.freertos.org/RTOS-task-notifications.html
*
* Internally, within the FreeRTOS implementation, binary semaphores use a block
* of memory, in which the semaphore structure is stored. If a binary semaphore
* is created using xSemaphoreCreateBinary() then the required memory is
* automatically dynamically allocated inside the xSemaphoreCreateBinary()
* function. (see http://www.freertos.org/a00111.html). If a binary semaphore
* is created using xSemaphoreCreateBinaryStatic() then the application writer
* must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a
* binary semaphore to be created without using any dynamic memory allocation.
*
* This type of semaphore can be used for pure synchronisation between tasks or
* between an interrupt and a task. The semaphore need not be given back once
* obtained, so one task/interrupt can continuously 'give' the semaphore while
* another continuously 'takes' the semaphore. For this reason this type of
* semaphore does not use a priority inheritance mechanism. For an alternative
* that does use priority inheritance see xSemaphoreCreateMutex().
*
* @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t,
* which will then be used to hold the semaphore's data structure, removing the
* need for the memory to be allocated dynamically.
*
* @return If the semaphore is created then a handle to the created semaphore is
* returned. If pxSemaphoreBuffer is NULL then NULL is returned.
*
* Example usage:
<pre>
SemaphoreHandle_t xSemaphore = NULL;
StaticSemaphore_t xSemaphoreBuffer;
void vATask( void * pvParameters )
{
// Semaphore cannot be used before a call to xSemaphoreCreateBinary().
// The semaphore's data structures will be placed in the xSemaphoreBuffer
// variable, the address of which is passed into the function. The
// function's parameter is not NULL, so the function will not attempt any
// dynamic memory allocation, and therefore the function will not return
// return NULL.
xSemaphore = xSemaphoreCreateBinary( &xSemaphoreBuffer );
// Rest of task code goes here.
}
</pre>
* \defgroup xSemaphoreCreateBinaryStatic xSemaphoreCreateBinaryStatic
* \ingroup Semaphores
*/
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
#define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticSemaphore, queueQUEUE_TYPE_BINARY_SEMAPHORE )
#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* semphr. h
@ -652,9 +731,18 @@ typedef QueueHandle_t SemaphoreHandle_t;
* <i>Macro</i> that implements a mutex semaphore by using the existing queue
* mechanism.
*
* Mutexes created using this macro can be accessed using the xSemaphoreTake()
* Internally, within the FreeRTOS implementation, mutex semaphores use a block
* of memory, in which the mutex structure is stored. If a mutex is created
* using xSemaphoreCreateMutex() then the required memory is automatically
* dynamically allocated inside the xSemaphoreCreateMutex() function. (see
* http://www.freertos.org/a00111.html). If a mutex is created using
* xSemaphoreCreateMutexStatic() then the application writer must provided the
* memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created
* without using any dynamic memory allocation.
*
* Mutexes created using this function can be accessed using the xSemaphoreTake()
* and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and
* xSemaphoreGiveRecursive() macros should not be used.
* xSemaphoreGiveRecursive() macros must not be used.
*
* This type of semaphore uses a priority inheritance mechanism so a task
* 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
@ -667,8 +755,9 @@ typedef QueueHandle_t SemaphoreHandle_t;
* semaphore and another always 'takes' the semaphore) and from within interrupt
* service routines.
*
* @return xSemaphore Handle to the created mutex semaphore. Should be of type
* SemaphoreHandle_t.
* @return If the mutex was successfully created then a handle to the created
* semaphore is returned. If there was not enough heap to allocate the mutex
* data structures then NULL is returned.
*
* Example usage:
<pre>
@ -690,19 +779,93 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex
* \ingroup Semaphores
*/
#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
#endif
/**
* semphr. h
* <pre>SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer )</pre>
*
* Creates a new mutex type semaphore instance, and returns a handle by which
* the new mutex can be referenced.
*
* Internally, within the FreeRTOS implementation, mutex semaphores use a block
* of memory, in which the mutex structure is stored. If a mutex is created
* using xSemaphoreCreateMutex() then the required memory is automatically
* dynamically allocated inside the xSemaphoreCreateMutex() function. (see
* http://www.freertos.org/a00111.html). If a mutex is created using
* xSemaphoreCreateMutexStatic() then the application writer must provided the
* memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created
* without using any dynamic memory allocation.
*
* Mutexes created using this function can be accessed using the xSemaphoreTake()
* and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and
* xSemaphoreGiveRecursive() macros must not be used.
*
* This type of semaphore uses a priority inheritance mechanism so a task
* 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
* semaphore it is no longer required.
*
* Mutex type semaphores cannot be used from within interrupt service routines.
*
* See xSemaphoreCreateBinary() for an alternative implementation that can be
* used for pure synchronisation (where one task or interrupt always 'gives' the
* semaphore and another always 'takes' the semaphore) and from within interrupt
* service routines.
*
* @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t,
* which will be used to hold the mutex's data structure, removing the need for
* the memory to be allocated dynamically.
*
* @return If the mutex was successfully created then a handle to the created
* mutex is returned. If pxMutexBuffer was NULL then NULL is returned.
*
* Example usage:
<pre>
SemaphoreHandle_t xSemaphore;
StaticSemaphore_t xMutexBuffer;
void vATask( void * pvParameters )
{
// A mutex cannot be used before it has been created. xMutexBuffer is
// into xSemaphoreCreateMutexStatic() so no dynamic memory allocation is
// attempted.
xSemaphore = xSemaphoreCreateMutexStatic( &xMutexBuffer );
// As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
// so there is no need to check it.
}
</pre>
* \defgroup xSemaphoreCreateMutexStatic xSemaphoreCreateMutexStatic
* \ingroup Semaphores
*/
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
#define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( pxMutexBuffer ) )
#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* semphr. h
* <pre>SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )</pre>
*
* <i>Macro</i> that implements a recursive mutex by using the existing queue
* mechanism.
* Creates a new recursive mutex type semaphore instance, and returns a handle
* by which the new recursive mutex can be referenced.
*
* Internally, within the FreeRTOS implementation, recursive mutexs use a block
* of memory, in which the mutex structure is stored. If a recursive mutex is
* created using xSemaphoreCreateRecursiveMutex() then the required memory is
* automatically dynamically allocated inside the
* xSemaphoreCreateRecursiveMutex() function. (see
* http://www.freertos.org/a00111.html). If a recursive mutex is created using
* xSemaphoreCreateRecursiveMutexStatic() then the application writer must
* provide the memory that will get used by the mutex.
* xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to
* be created without using any dynamic memory allocation.
*
* Mutexes created using this macro can be accessed using the
* xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The
* xSemaphoreTake() and xSemaphoreGive() macros should not be used.
* xSemaphoreTake() and xSemaphoreGive() macros must not be used.
*
* A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
* doesn't become available again until the owner has called
@ -745,14 +908,104 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex
* \ingroup Semaphores
*/
#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )
#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) )
#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )
#endif
/**
* semphr. h
* <pre>SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic( StaticSemaphore_t *pxMutexBuffer )</pre>
*
* Creates a new recursive mutex type semaphore instance, and returns a handle
* by which the new recursive mutex can be referenced.
*
* Internally, within the FreeRTOS implementation, recursive mutexs use a block
* of memory, in which the mutex structure is stored. If a recursive mutex is
* created using xSemaphoreCreateRecursiveMutex() then the required memory is
* automatically dynamically allocated inside the
* xSemaphoreCreateRecursiveMutex() function. (see
* http://www.freertos.org/a00111.html). If a recursive mutex is created using
* xSemaphoreCreateRecursiveMutexStatic() then the application writer must
* provide the memory that will get used by the mutex.
* xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to
* be created without using any dynamic memory allocation.
*
* Mutexes created using this macro can be accessed using the
* xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The
* xSemaphoreTake() and xSemaphoreGive() macros must not be used.
*
* A mutex used recursively can be 'taken' repeatedly by the owner. The mutex
* doesn't become available again until the owner has called
* xSemaphoreGiveRecursive() for each successful 'take' request. For example,
* if a task successfully 'takes' the same mutex 5 times then the mutex will
* not be available to any other task until it has also 'given' the mutex back
* exactly five times.
*
* This type of semaphore uses a priority inheritance mechanism so a task
* 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the
* semaphore it is no longer required.
*
* Mutex type semaphores cannot be used from within interrupt service routines.
*
* See xSemaphoreCreateBinary() for an alternative implementation that can be
* used for pure synchronisation (where one task or interrupt always 'gives' the
* semaphore and another always 'takes' the semaphore) and from within interrupt
* service routines.
*
* @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t,
* which will then be used to hold the recursive mutex's data structure,
* removing the need for the memory to be allocated dynamically.
*
* @return If the recursive mutex was successfully created then a handle to the
* created recursive mutex is returned. If pxMutexBuffer was NULL then NULL is
* returned.
*
* Example usage:
<pre>
SemaphoreHandle_t xSemaphore;
StaticSemaphore_t xMutexBuffer;
void vATask( void * pvParameters )
{
// A recursive semaphore cannot be used before it is created. Here a
// recursive mutex is created using xSemaphoreCreateRecursiveMutexStatic().
// The address of xMutexBuffer is passed into the function, and will hold
// the mutexes data structures - so no dynamic memory allocation will be
// attempted.
xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xMutexBuffer );
// As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
// so there is no need to check it.
}
</pre>
* \defgroup xSemaphoreCreateRecursiveMutexStatic xSemaphoreCreateRecursiveMutexStatic
* \ingroup Semaphores
*/
#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) )
#define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, pxStaticSemaphore )
#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* semphr. h
* <pre>SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount )</pre>
*
* <i>Macro</i> that creates a counting semaphore by using the existing
* queue mechanism.
* Creates a new counting semaphore instance, and returns a handle by which the
* new counting semaphore can be referenced.
*
* In many usage scenarios it is faster and more memory efficient to use a
* direct to task notification in place of a counting semaphore!
* http://www.freertos.org/RTOS-task-notifications.html
*
* Internally, within the FreeRTOS implementation, counting semaphores use a
* block of memory, in which the counting semaphore structure is stored. If a
* counting semaphore is created using xSemaphoreCreateCounting() then the
* required memory is automatically dynamically allocated inside the
* xSemaphoreCreateCounting() function. (see
* http://www.freertos.org/a00111.html). If a counting semaphore is created
* using xSemaphoreCreateCountingStatic() then the application writer can
* instead optionally provide the memory that will get used by the counting
* semaphore. xSemaphoreCreateCountingStatic() therefore allows a counting
* semaphore to be created without using any dynamic memory allocation.
*
* Counting semaphores are typically used for two things:
*
@ -808,7 +1061,94 @@ typedef QueueHandle_t SemaphoreHandle_t;
* \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting
* \ingroup Semaphores
*/
#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
#endif
/**
* semphr. h
* <pre>SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer )</pre>
*
* Creates a new counting semaphore instance, and returns a handle by which the
* new counting semaphore can be referenced.
*
* In many usage scenarios it is faster and more memory efficient to use a
* direct to task notification in place of a counting semaphore!
* http://www.freertos.org/RTOS-task-notifications.html
*
* Internally, within the FreeRTOS implementation, counting semaphores use a
* block of memory, in which the counting semaphore structure is stored. If a
* counting semaphore is created using xSemaphoreCreateCounting() then the
* required memory is automatically dynamically allocated inside the
* xSemaphoreCreateCounting() function. (see
* http://www.freertos.org/a00111.html). If a counting semaphore is created
* using xSemaphoreCreateCountingStatic() then the application writer must
* provide the memory. xSemaphoreCreateCountingStatic() therefore allows a
* counting semaphore to be created without using any dynamic memory allocation.
*
* Counting semaphores are typically used for two things:
*
* 1) Counting events.
*
* In this usage scenario an event handler will 'give' a semaphore each time
* an event occurs (incrementing the semaphore count value), and a handler
* task will 'take' a semaphore each time it processes an event
* (decrementing the semaphore count value). The count value is therefore
* the difference between the number of events that have occurred and the
* number that have been processed. In this case it is desirable for the
* initial count value to be zero.
*
* 2) Resource management.
*
* In this usage scenario the count value indicates the number of resources
* available. To obtain control of a resource a task must first obtain a
* semaphore - decrementing the semaphore count value. When the count value
* reaches zero there are no free resources. When a task finishes with the
* resource it 'gives' the semaphore back - incrementing the semaphore count
* value. In this case it is desirable for the initial count value to be
* equal to the maximum count value, indicating that all resources are free.
*
* @param uxMaxCount The maximum count value that can be reached. When the
* semaphore reaches this value it can no longer be 'given'.
*
* @param uxInitialCount The count value assigned to the semaphore when it is
* created.
*
* @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t,
* which will then be used to hold the semaphore's data structure, removing the
* need for the memory to be allocated dynamically.
*
* @return If the counting semaphore was successfully created then a handle to
* the created counting semaphore is returned. If pxSemaphoreBuffer was NULL
* then NULL is returned.
*
* Example usage:
<pre>
SemaphoreHandle_t xSemaphore;
StaticSemaphore_t xSemaphoreBuffer;
void vATask( void * pvParameters )
{
SemaphoreHandle_t xSemaphore = NULL;
// Counting semaphore cannot be used before they have been created. Create
// a counting semaphore using xSemaphoreCreateCountingStatic(). The max
// value to which the semaphore can count is 10, and the initial value
// assigned to the count will be 0. The address of xSemaphoreBuffer is
// passed in and will be used to hold the semaphore structure, so no dynamic
// memory allocation will be used.
xSemaphore = xSemaphoreCreateCounting( 10, 0, &xSemaphoreBuffer );
// No memory allocation was attempted so xSemaphore cannot be NULL, so there
// is no need to check its value.
}
</pre>
* \defgroup xSemaphoreCreateCountingStatic xSemaphoreCreateCountingStatic
* \ingroup Semaphores
*/
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
#define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxSemaphoreBuffer ) xQueueCreateCountingSemaphoreStatic( ( uxMaxCount ), ( uxInitialCount ), ( pxSemaphoreBuffer ) )
#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* semphr. h

View File

@ -177,6 +177,7 @@ typedef struct xTASK_STATUS
UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */
UBaseType_t uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */
uint32_t ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See http://www.freertos.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */
StackType_t *pxStackBase; /* Points to the lowest address of the task's stack area. */
uint16_t usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */
} TaskStatus_t;
@ -281,8 +282,19 @@ is used in assert() statements. */
);</pre>
*
* Create a new task and add it to the list of tasks that are ready to run.
* On multicore environments, this will give no specific affinity to the task.
* Use xTaskCreatePinnedToCore to give affinity.
*
* Internally, within the FreeRTOS implementation, tasks use two blocks of
* memory. The first block is used to hold the task's data structures. The
* second block is used by the task as its stack. If a task is created using
* xTaskCreate() then both blocks of memory are automatically dynamically
* allocated inside the xTaskCreate() function. (see
* http://www.freertos.org/a00111.html). If a task is created using
* xTaskCreateStatic() then the application writer must provide the required
* memory. xTaskCreateStatic() therefore allows a task to be created without
* using any dynamic memory allocation.
*
* See xTaskCreateStatic() for a version that does not use any dynamic memory
* allocation.
*
* xTaskCreate() can only be used to create a task that has unrestricted
* access to the entire microcontroller memory map. Systems that include MPU
@ -350,8 +362,139 @@ is used in assert() statements. */
* \defgroup xTaskCreate xTaskCreate
* \ingroup Tasks
*/
#define xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( NULL ), ( NULL ), tskNO_AFFINITY )
#define xTaskCreatePinnedToCore( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, xCoreID ) xTaskGenericCreate( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), ( NULL ), ( NULL ), xCoreID )
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask,
const BaseType_t xCoreID);
#define xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ) xTaskCreatePinnedToCore( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxCreatedTask ), tskNO_AFFINITY )
#endif
/**
* task. h
*<pre>
TaskHandle_t xTaskCreateStatic( TaskFunction_t pvTaskCode,
const char * const pcName,
uint32_t ulStackDepth,
void *pvParameters,
UBaseType_t uxPriority,
StackType_t *pxStackBuffer,
StaticTask_t *pxTaskBuffer,
const BaseType_t xCoreID );</pre>
*
* Create a new task and add it to the list of tasks that are ready to run.
*
* Internally, within the FreeRTOS implementation, tasks use two blocks of
* memory. The first block is used to hold the task's data structures. The
* second block is used by the task as its stack. If a task is created using
* xTaskCreate() then both blocks of memory are automatically dynamically
* allocated inside the xTaskCreate() function. (see
* http://www.freertos.org/a00111.html). If a task is created using
* xTaskCreateStatic() then the application writer must provide the required
* memory. xTaskCreateStatic() therefore allows a task to be created without
* using any dynamic memory allocation.
*
* @param pvTaskCode Pointer to the task entry function. Tasks
* must be implemented to never return (i.e. continuous loop).
*
* @param pcName A descriptive name for the task. This is mainly used to
* facilitate debugging. The maximum length of the string is defined by
* configMAX_TASK_NAME_LEN in FreeRTOSConfig.h.
*
* @param ulStackDepth The size of the task stack specified as the number of
* variables the stack can hold - not the number of bytes. For example, if
* the stack is 32-bits wide and ulStackDepth is defined as 100 then 400 bytes
* will be allocated for stack storage.
*
* @param pvParameters Pointer that will be used as the parameter for the task
* being created.
*
* @param uxPriority The priority at which the task will run.
*
* @param pxStackBuffer Must point to a StackType_t array that has at least
* ulStackDepth indexes - the array will then be used as the task's stack,
* removing the need for the stack to be allocated dynamically.
*
* @param pxTaskBuffer Must point to a variable of type StaticTask_t, which will
* then be used to hold the task's data structures, removing the need for the
* memory to be allocated dynamically.
*
* @return If neither pxStackBuffer or pxTaskBuffer are NULL, then the task will
* be created and pdPASS is returned. If either pxStackBuffer or pxTaskBuffer
* are NULL then the task will not be created and
* errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY is returned.
*
* Example usage:
<pre>
// Dimensions the buffer that the task being created will use as its stack.
// NOTE: This is the number of words the stack will hold, not the number of
// bytes. For example, if each stack item is 32-bits, and this is set to 100,
// then 400 bytes (100 * 32-bits) will be allocated.
#define STACK_SIZE 200
// Structure that will hold the TCB of the task being created.
StaticTask_t xTaskBuffer;
// Buffer that the task being created will use as its stack. Note this is
// an array of StackType_t variables. The size of StackType_t is dependent on
// the RTOS port.
StackType_t xStack[ STACK_SIZE ];
// Function that implements the task being created.
void vTaskCode( void * pvParameters )
{
// The parameter value is expected to be 1 as 1 is passed in the
// pvParameters value in the call to xTaskCreateStatic().
configASSERT( ( uint32_t ) pvParameters == 1UL );
for( ;; )
{
// Task code goes here.
}
}
// Function that creates a task.
void vOtherFunction( void )
{
TaskHandle_t xHandle = NULL;
// Create the task without using any dynamic memory allocation.
xHandle = xTaskCreateStatic(
vTaskCode, // Function that implements the task.
"NAME", // Text name for the task.
STACK_SIZE, // Stack size in words, not bytes.
( void * ) 1, // Parameter passed into the task.
tskIDLE_PRIORITY,// Priority at which the task is created.
xStack, // Array to use as the task's stack.
&xTaskBuffer ); // Variable to hold the task's data structure.
// puxStackBuffer and pxTaskBuffer were not NULL, so the task will have
// been created, and xHandle will be the task's handle. Use the handle
// to suspend the task.
vTaskSuspend( xHandle );
}
</pre>
* \defgroup xTaskCreateStatic xTaskCreateStatic
* \ingroup Tasks
*/
#if( configSUPPORT_STATIC_ALLOCATION == 1 )
TaskHandle_t xTaskCreateStaticPinnedToCore( 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,
const BaseType_t xCoreID );
#define xTaskCreateStatic( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxStackBuffer, pxTaskBuffer ) xTaskCreateStaticPinnedToCore( ( pvTaskCode ), ( pcName ), ( usStackDepth ), ( pvParameters ), ( uxPriority ), ( pxStackBuffer ), ( pxTaskBuffer ), tskNO_AFFINITY )
#endif /* configSUPPORT_STATIC_ALLOCATION */
/**
* task. h
@ -420,7 +563,9 @@ TaskHandle_t xHandle;
* \defgroup xTaskCreateRestricted xTaskCreateRestricted
* \ingroup Tasks
*/
#define xTaskCreateRestricted( x, pxCreatedTask ) xTaskGenericCreate( ((x)->pvTaskCode), ((x)->pcName), ((x)->usStackDepth), ((x)->pvParameters), ((x)->uxPriority), (pxCreatedTask), ((x)->puxStackBuffer), ((x)->xRegions) )
#if( portUSING_MPU_WRAPPERS == 1 )
BaseType_t xTaskCreateRestricted( const TaskParameters_t * const pxTaskDefinition, TaskHandle_t *pxCreatedTask ) PRIVILEGED_FUNCTION;
#endif
/**
* task. h
@ -1933,6 +2078,17 @@ TickType_t uxTaskResetEventItemValue( void ) PRIVILEGED_FUNCTION;
*/
TaskHandle_t xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION;
/*
* Return the handle of the task running on a certain CPU. Because of
* the nature of SMP processing, there is no guarantee that this
* value will still be valid on return and should only be used for
* debugging purposes.
*/
TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t cpuid );
/*
* Capture the current time status for future reference.
*/
@ -1968,12 +2124,6 @@ void vTaskPriorityInherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTIO
*/
BaseType_t xTaskPriorityDisinherit( TaskHandle_t const pxMutexHolder ) PRIVILEGED_FUNCTION;
/*
* Generic version of the task creation function which is in turn called by the
* xTaskCreate() and xTaskCreateRestricted() macros.
*/
BaseType_t xTaskGenericCreate( TaskFunction_t pxTaskCode, const char * const pcName, const uint16_t usStackDepth, void * const pvParameters, UBaseType_t uxPriority, TaskHandle_t * const pxCreatedTask, StackType_t * const puxStackBuffer, const MemoryRegion_t * const xRegions, const BaseType_t xCoreID) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
/*
* Get the uxTCBNumber assigned to the task referenced by the xTask parameter.
*/

View File

@ -322,12 +322,7 @@ STRUCT_END(XtSolFrame)
#ifdef __ASSEMBLER__
.macro getcoreid reg
rsr.prid \reg
bbci \reg,1,1f
movi \reg,1
j 2f
1:
movi \reg,0
2:
extui \reg,\reg,13,1
.endm
#endif