2024-01-29 13:51:15 +08:00
|
|
|
/***************************************************************************
|
|
|
|
* Copyright (c) 2024 Microsoft Corporation
|
|
|
|
*
|
|
|
|
* This program and the accompanying materials are made available under the
|
|
|
|
* terms of the MIT License which is available at
|
|
|
|
* https://opensource.org/licenses/MIT.
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
**************************************************************************/
|
2020-10-01 13:46:52 -07:00
|
|
|
|
|
|
|
/**************************************************************************/
|
|
|
|
/**************************************************************************/
|
|
|
|
/** */
|
|
|
|
/** ThreadX Component */
|
|
|
|
/** */
|
|
|
|
/** FreeRTOS compatibility Kit */
|
|
|
|
/** */
|
|
|
|
/**************************************************************************/
|
|
|
|
/**************************************************************************/
|
|
|
|
/* RELEASE HISTORY */
|
|
|
|
/* */
|
|
|
|
/* DATE NAME DESCRIPTION */
|
|
|
|
/* */
|
|
|
|
/* 09-30-2020 William E. Lamie Initial Version 6.1 */
|
2021-10-14 00:51:26 +00:00
|
|
|
/* 10-15-2021 William E. Lamie Modified comment(s), and */
|
|
|
|
/* fixed compiler warnings, */
|
|
|
|
/* resulting in version 6.1.7 */
|
2022-01-29 00:24:03 +00:00
|
|
|
/* 01-31-2022 William E. Lamie Modified comment(s), and */
|
|
|
|
/* fixed compiler warnings, */
|
|
|
|
/* resulting in version 6.1.10 */
|
2022-07-26 02:04:40 +00:00
|
|
|
/* 07-29-2022 Cindy Deng Added simple static scheduler */
|
|
|
|
/* start flag, corrected stack */
|
|
|
|
/* allocation size, */
|
|
|
|
/* resulting in version 6.1.12 */
|
2023-12-28 13:17:40 +08:00
|
|
|
/* 12-31-2023 Xiuwen Cai Modified comment(s), and */
|
|
|
|
/* added check for overflow in */
|
|
|
|
/* queue size calculation, */
|
|
|
|
/* resulting in version 6.4.0 */
|
2020-10-01 13:46:52 -07:00
|
|
|
/* */
|
|
|
|
/**************************************************************************/
|
|
|
|
|
|
|
|
#include <stdint.h>
|
2022-07-26 02:04:40 +00:00
|
|
|
#include <limits.h>
|
2020-10-01 13:46:52 -07:00
|
|
|
|
|
|
|
#include <tx_api.h>
|
|
|
|
#include <tx_thread.h>
|
|
|
|
#include <tx_semaphore.h>
|
|
|
|
#include <tx_queue.h>
|
|
|
|
|
|
|
|
#include "FreeRTOS.h"
|
|
|
|
|
|
|
|
#if (INCLUDE_vTaskDelete == 1)
|
|
|
|
static TX_THREAD txfr_idle_task;
|
|
|
|
#ifdef TX_FREERTOS_IDLE_STACK
|
|
|
|
static UINT txfr_idle_stack[TX_FREERTOS_IDLE_STACK];
|
|
|
|
#else
|
|
|
|
static UINT txfr_idle_stack[configMINIMAL_STACK_SIZE];
|
|
|
|
#endif
|
|
|
|
static TX_SEMAPHORE txfr_idle_sem;
|
|
|
|
|
|
|
|
static txfr_task_t *p_delete_task_head;
|
|
|
|
#endif // #if (INCLUDE_vTaskDelete == 1)
|
|
|
|
|
|
|
|
UBaseType_t g_txfr_task_count;
|
|
|
|
|
|
|
|
#ifdef configTOTAL_HEAP_SIZE
|
|
|
|
static uint8_t txfr_heap_mem[configTOTAL_HEAP_SIZE];
|
|
|
|
static TX_BYTE_POOL txfr_heap;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static UINT txfr_heap_initialized;
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
static UINT txfr_initialized;
|
2022-07-26 02:04:40 +00:00
|
|
|
static UINT txfr_scheduler_started;
|
2020-10-01 13:46:52 -07:00
|
|
|
#endif // #if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
|
|
|
|
// TODO - do something with malloc.
|
|
|
|
void *txfr_malloc(size_t len)
|
|
|
|
{
|
|
|
|
void *p;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
if(txfr_heap_initialized == 1u) {
|
|
|
|
ret = tx_byte_allocate(&txfr_heap, &p, len, 0u);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
void txfr_free(void *p)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
if(txfr_heap_initialized == 1u) {
|
|
|
|
ret = tx_byte_release(p);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if (INCLUDE_vTaskDelete == 1)
|
|
|
|
static void txfr_idle_task_entry(ULONG id)
|
|
|
|
{
|
|
|
|
txfr_task_t *p_task;
|
|
|
|
UINT ret;
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
|
|
|
|
|
|
|
|
for(;;) {
|
|
|
|
ret = tx_semaphore_get(&txfr_idle_sem, TX_WAIT_FOREVER);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
p_task = p_delete_task_head;
|
|
|
|
|
|
|
|
if(p_task != NULL) {
|
|
|
|
p_delete_task_head = p_task->p_next;
|
|
|
|
}
|
|
|
|
g_txfr_task_count--;
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
if(p_task != NULL) {
|
|
|
|
|
|
|
|
// Make sure the task is terminated, which may return an error if that's already the case so the return value is ignored.
|
|
|
|
(void)tx_thread_terminate(&p_task->thread);
|
|
|
|
|
|
|
|
ret = tx_thread_delete(&p_task->thread);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_semaphore_delete(&p_task->notification_sem);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(p_task->allocated == 1u) {
|
|
|
|
txfr_free(p_task);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // #if (INCLUDE_vTaskDelete == 1)
|
|
|
|
|
|
|
|
static uint32_t txfr_prio_fr_to_tx(uint32_t prio)
|
|
|
|
{
|
|
|
|
return TX_MAX_PRIORITIES - 1u - prio;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static uint32_t txfr_prio_tx_to_fr(uint32_t prio)
|
|
|
|
{
|
|
|
|
return TX_MAX_PRIORITIES - 1u - prio;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
static void tx_freertos_auto_init(void)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
tx_kernel_enter();
|
|
|
|
|
|
|
|
ret = tx_freertos_init();
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
txfr_initialized = 1u;
|
|
|
|
}
|
|
|
|
#endif // #if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
VOID tx_application_define(VOID * first_unused_memory)
|
|
|
|
{
|
|
|
|
// Empty tx_application_define() to support auto initialization.
|
|
|
|
}
|
|
|
|
#endif // #if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
|
|
|
|
UINT tx_freertos_init(void)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
#ifdef configTOTAL_HEAP_SIZE
|
|
|
|
if(configTOTAL_HEAP_SIZE > 0u) {
|
|
|
|
ret = tx_byte_pool_create(&txfr_heap, "txfr_byte_pool", txfr_heap_mem, configTOTAL_HEAP_SIZE);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
txfr_heap_initialized = 1u;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if (INCLUDE_vTaskDelete == 1)
|
|
|
|
ret = tx_semaphore_create(&txfr_idle_sem, "txfr_idle_semaphore", 0u);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_thread_create(&txfr_idle_task, "txfr_idle_task", txfr_idle_task_entry, 0u,
|
|
|
|
txfr_idle_stack, sizeof(txfr_idle_stack), TX_MAX_PRIORITIES - 1u, TX_MAX_PRIORITIES - 1u, 0u, TX_AUTO_START);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif // #if (INCLUDE_vTaskDelete == 1)
|
|
|
|
|
|
|
|
return TX_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void txfr_thread_wrapper(ULONG id)
|
|
|
|
{
|
|
|
|
TX_THREAD *p_thread;
|
|
|
|
txfr_task_t *p_txfr_task;
|
|
|
|
|
|
|
|
p_thread = tx_thread_identify();
|
|
|
|
|
|
|
|
p_txfr_task = p_thread->txfr_thread_ptr;
|
|
|
|
|
|
|
|
p_txfr_task->p_task_func(p_txfr_task->p_task_arg);
|
|
|
|
|
|
|
|
#if (INCLUDE_vTaskDelete == 1)
|
|
|
|
vTaskDelete(NULL);
|
|
|
|
#else
|
|
|
|
// Returning from a task is not allowed when vTaskDelete is disabled.
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
#endif // #if (INCLUDE_vTaskDelete == 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void *pvPortMalloc(size_t xWantedSize)
|
|
|
|
{
|
|
|
|
return txfr_malloc(xWantedSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
void vPortFree(void *pv)
|
|
|
|
{
|
|
|
|
txfr_free(pv);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vPortEnterCritical(void)
|
|
|
|
{
|
|
|
|
portDISABLE_INTERRUPTS();
|
|
|
|
_tx_thread_preempt_disable++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vPortExitCritical(void)
|
|
|
|
{
|
|
|
|
if(_tx_thread_preempt_disable == 0u) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
}
|
|
|
|
|
|
|
|
_tx_thread_preempt_disable--;
|
|
|
|
|
|
|
|
if(_tx_thread_preempt_disable == 0u) {
|
|
|
|
portENABLE_INTERRUPTS();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void vTaskStartScheduler(void)
|
|
|
|
{
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
2022-07-26 02:04:40 +00:00
|
|
|
txfr_scheduler_started = 1u;
|
2020-10-01 13:46:52 -07:00
|
|
|
_tx_thread_schedule();
|
|
|
|
#else
|
|
|
|
// Nothing to do, THREADX scheduler is already started.
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTaskGetSchedulerState(void)
|
|
|
|
{
|
2022-07-26 02:04:40 +00:00
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
if(txfr_scheduler_started == 0u) {
|
|
|
|
return taskSCHEDULER_NOT_STARTED;
|
|
|
|
}
|
|
|
|
#endif
|
2020-10-01 13:46:52 -07:00
|
|
|
if(_tx_thread_preempt_disable > 0u) {
|
|
|
|
return taskSCHEDULER_SUSPENDED;
|
|
|
|
} else {
|
|
|
|
return taskSCHEDULER_RUNNING;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void vTaskSuspendAll(void)
|
|
|
|
{
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
_tx_thread_preempt_disable++;
|
|
|
|
TX_RESTORE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xTaskResumeAll(void)
|
|
|
|
{
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
_tx_thread_preempt_disable--;
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vTaskDelay(const TickType_t xTicksToDelay)
|
|
|
|
{
|
|
|
|
tx_thread_sleep(xTicksToDelay);
|
|
|
|
}
|
|
|
|
|
|
|
|
TaskHandle_t xTaskCreateStatic(TaskFunction_t pxTaskCode,
|
|
|
|
const char *const pcName,
|
|
|
|
const configSTACK_DEPTH_TYPE ulStackDepth,
|
|
|
|
void *const pvParameters,
|
|
|
|
UBaseType_t uxPriority,
|
|
|
|
StackType_t *const puxStackBuffer,
|
|
|
|
StaticTask_t *const pxTaskBuffer)
|
|
|
|
{
|
|
|
|
UINT prio;
|
|
|
|
UINT ret;
|
2022-07-26 02:04:40 +00:00
|
|
|
ULONG stack_depth_bytes;
|
2020-10-01 13:46:52 -07:00
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
|
|
|
|
configASSERT(pxTaskCode != NULL);
|
|
|
|
configASSERT(ulStackDepth >= configMINIMAL_STACK_SIZE);
|
|
|
|
configASSERT(uxPriority < configMAX_PRIORITIES);
|
|
|
|
configASSERT(puxStackBuffer != NULL);
|
|
|
|
configASSERT(pxTaskBuffer != NULL);
|
|
|
|
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
if(txfr_initialized != 1u) {
|
|
|
|
tx_freertos_auto_init();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-07-26 02:04:40 +00:00
|
|
|
if(ulStackDepth > (ULONG_MAX / sizeof(StackType_t))) {
|
|
|
|
/* Integer overflow in stack depth */
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
stack_depth_bytes = ulStackDepth * sizeof(StackType_t);
|
|
|
|
|
2020-10-01 13:46:52 -07:00
|
|
|
TX_MEMSET(pxTaskBuffer, 0, sizeof(*pxTaskBuffer));
|
|
|
|
pxTaskBuffer->p_task_arg = pvParameters;
|
|
|
|
pxTaskBuffer->p_task_func = pxTaskCode;
|
|
|
|
|
|
|
|
ret = tx_semaphore_create(&pxTaskBuffer->notification_sem, "", 0u);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
prio = txfr_prio_fr_to_tx(uxPriority);
|
|
|
|
|
|
|
|
ret = tx_thread_create(&pxTaskBuffer->thread, (CHAR *)pcName, txfr_thread_wrapper, (ULONG)pvParameters,
|
2022-07-26 02:04:40 +00:00
|
|
|
puxStackBuffer, stack_depth_bytes, prio, prio, 0u, TX_DONT_START);
|
2020-10-01 13:46:52 -07:00
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pxTaskBuffer->thread.txfr_thread_ptr = pxTaskBuffer;
|
|
|
|
|
|
|
|
ret = tx_thread_resume(&pxTaskBuffer->thread);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
g_txfr_task_count++;
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return pxTaskBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTaskCreate(TaskFunction_t pvTaskCode,
|
|
|
|
const char * const pcName,
|
|
|
|
const configSTACK_DEPTH_TYPE usStackDepth,
|
|
|
|
void *pvParameters,
|
|
|
|
UBaseType_t uxPriority,
|
|
|
|
TaskHandle_t * const pxCreatedTask)
|
|
|
|
{
|
|
|
|
void *p_stack;
|
|
|
|
txfr_task_t *p_task;
|
|
|
|
UINT ret;
|
|
|
|
UINT prio;
|
2022-07-26 02:04:40 +00:00
|
|
|
ULONG stack_depth_bytes;
|
2020-10-01 13:46:52 -07:00
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
|
|
|
|
configASSERT(pvTaskCode != NULL);
|
|
|
|
configASSERT(usStackDepth >= configMINIMAL_STACK_SIZE);
|
|
|
|
configASSERT(uxPriority < configMAX_PRIORITIES);
|
|
|
|
configASSERT(pxCreatedTask != NULL);
|
|
|
|
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
if(txfr_initialized != 1u) {
|
|
|
|
tx_freertos_auto_init();
|
|
|
|
}
|
|
|
|
#endif
|
2022-07-26 02:04:40 +00:00
|
|
|
if((usStackDepth > (SIZE_MAX / sizeof(StackType_t)))
|
|
|
|
|| (usStackDepth > (ULONG_MAX / sizeof(StackType_t)))) {
|
|
|
|
/* Integer overflow in stack depth */
|
|
|
|
return errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
|
|
|
|
}
|
|
|
|
stack_depth_bytes = usStackDepth * sizeof(StackType_t);
|
2020-10-01 13:46:52 -07:00
|
|
|
|
2022-07-26 02:04:40 +00:00
|
|
|
p_stack = txfr_malloc((size_t)stack_depth_bytes);
|
2020-10-01 13:46:52 -07:00
|
|
|
if(p_stack == NULL) {
|
|
|
|
return errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
p_task = txfr_malloc(sizeof(txfr_task_t));
|
|
|
|
if(p_task == NULL) {
|
|
|
|
txfr_free(p_stack);
|
|
|
|
return errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
*pxCreatedTask = p_task;
|
|
|
|
|
|
|
|
TX_MEMSET(p_task, 0, sizeof(*p_task));
|
|
|
|
p_task->allocated = 1u;
|
|
|
|
p_task->p_task_arg = pvParameters;
|
|
|
|
p_task->p_task_func = pvTaskCode;
|
|
|
|
|
|
|
|
ret = tx_semaphore_create(&p_task->notification_sem, "", 0u);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
txfr_free(p_stack);
|
|
|
|
txfr_free(p_task);
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
2021-10-14 00:51:26 +00:00
|
|
|
return (BaseType_t)NULL;
|
2020-10-01 13:46:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
prio = txfr_prio_fr_to_tx(uxPriority);
|
|
|
|
|
|
|
|
ret = tx_thread_create(&p_task->thread, (CHAR *)pcName, txfr_thread_wrapper, (ULONG)pvParameters,
|
2022-07-26 02:04:40 +00:00
|
|
|
p_stack, stack_depth_bytes, prio, prio, 0u, TX_DONT_START);
|
2020-10-01 13:46:52 -07:00
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
(void)tx_semaphore_delete(&p_task->notification_sem);
|
|
|
|
txfr_free(p_stack);
|
|
|
|
txfr_free(p_task);
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
2021-10-14 00:51:26 +00:00
|
|
|
return (BaseType_t)NULL;
|
2020-10-01 13:46:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
p_task->thread.txfr_thread_ptr = p_task;
|
|
|
|
|
|
|
|
ret = tx_thread_resume(&p_task->thread);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
g_txfr_task_count++;
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return pdPASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
UBaseType_t uxTaskGetNumberOfTasks(void)
|
|
|
|
{
|
|
|
|
UBaseType_t count;
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
count = g_txfr_task_count;
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if (INCLUDE_vTaskDelete == 1)
|
|
|
|
void vTaskDelete(TaskHandle_t xTask)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
TX_THREAD *p_thread;
|
|
|
|
txfr_task_t *p_txfr_thread;
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
|
|
|
|
if(xTask == NULL) {
|
|
|
|
TX_THREAD_GET_CURRENT(p_thread);
|
|
|
|
p_txfr_thread = (txfr_task_t *)p_thread->txfr_thread_ptr;
|
|
|
|
} else {
|
|
|
|
p_txfr_thread = xTask;
|
|
|
|
p_thread = &xTask->thread;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
|
|
|
|
p_txfr_thread->p_next = p_delete_task_head;
|
|
|
|
p_delete_task_head = p_txfr_thread;
|
|
|
|
|
|
|
|
_tx_thread_preempt_disable++;
|
|
|
|
|
|
|
|
ret = tx_semaphore_put(&txfr_idle_sem);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
_tx_thread_preempt_disable--;
|
|
|
|
TX_RESTORE;
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_tx_thread_preempt_disable--;
|
|
|
|
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
ret = tx_thread_terminate(p_thread);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_RESTORE;
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
TaskHandle_t xTaskGetCurrentTaskHandle(void)
|
|
|
|
{
|
|
|
|
TX_THREAD *p_thread;
|
|
|
|
|
|
|
|
p_thread = tx_thread_identify();
|
|
|
|
|
|
|
|
return p_thread->txfr_thread_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void vTaskSuspend(TaskHandle_t xTaskToSuspend)
|
|
|
|
{
|
|
|
|
TX_THREAD *p_thread;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
if(xTaskToSuspend == NULL) {
|
|
|
|
p_thread = tx_thread_identify();
|
|
|
|
} else {
|
|
|
|
p_thread = &xTaskToSuspend->thread;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_thread_suspend(p_thread);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void vTaskResume(TaskHandle_t xTaskToResume)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xTaskToResume != NULL);
|
|
|
|
|
|
|
|
ret = tx_thread_resume(&xTaskToResume->thread);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume)
|
|
|
|
{
|
|
|
|
configASSERT(xTaskToResume != NULL);
|
|
|
|
|
|
|
|
vTaskResume(xTaskToResume);
|
|
|
|
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTaskAbortDelay(TaskHandle_t xTask)
|
|
|
|
{
|
|
|
|
TX_THREAD *p_thread;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xTask != NULL);
|
|
|
|
|
|
|
|
p_thread = &xTask->thread;
|
|
|
|
|
|
|
|
ret = tx_thread_wait_abort(p_thread);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return pdFAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pdPASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
UBaseType_t uxTaskPriorityGet(const TaskHandle_t xTask)
|
|
|
|
{
|
|
|
|
TX_THREAD *p_thread;
|
|
|
|
UINT priority;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
if(xTask == NULL) {
|
|
|
|
p_thread = tx_thread_identify();
|
|
|
|
} else {
|
|
|
|
p_thread = &xTask->thread;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_thread_info_get(p_thread, NULL, NULL, NULL, &priority, NULL, NULL, NULL, NULL);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
priority = txfr_prio_tx_to_fr(priority);
|
|
|
|
|
|
|
|
return priority;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
UBaseType_t uxTaskPriorityGetFromISR(const TaskHandle_t xTask)
|
|
|
|
{
|
|
|
|
return uxTaskPriorityGet(xTask);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void vTaskPrioritySet(TaskHandle_t xTask,
|
|
|
|
UBaseType_t uxNewPriority)
|
|
|
|
{
|
|
|
|
TX_THREAD *p_thread;
|
|
|
|
UINT priority;
|
|
|
|
UINT old_priority;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(uxNewPriority < configMAX_PRIORITIES);
|
|
|
|
|
|
|
|
if(xTask == NULL) {
|
|
|
|
p_thread = tx_thread_identify();
|
|
|
|
} else {
|
|
|
|
p_thread = &xTask->thread;
|
|
|
|
}
|
|
|
|
|
|
|
|
priority = uxNewPriority;
|
|
|
|
priority = txfr_prio_fr_to_tx(priority);
|
|
|
|
|
|
|
|
ret = tx_thread_priority_change(p_thread, priority, &old_priority);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char *pcTaskGetName(TaskHandle_t xTaskToQuery)
|
|
|
|
{
|
|
|
|
TX_THREAD *p_thread;
|
|
|
|
char *p_task_name;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
if(xTaskToQuery == NULL) {
|
|
|
|
p_thread = tx_thread_identify();
|
|
|
|
} else {
|
|
|
|
p_thread = &xTaskToQuery->thread;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_thread_info_get(p_thread, &p_task_name, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return p_task_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
eTaskState eTaskGetState(TaskHandle_t xTask)
|
|
|
|
{
|
|
|
|
UINT thread_state;
|
|
|
|
eTaskState ret_state;
|
|
|
|
TX_THREAD *p_thread;
|
|
|
|
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
|
|
|
|
if(xTask == NULL) {
|
|
|
|
return eInvalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
thread_state = xTask->thread.tx_thread_state;
|
|
|
|
p_thread = &xTask->thread;
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
if(p_thread == tx_thread_identify()) {
|
|
|
|
return eRunning;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(thread_state) {
|
|
|
|
case TX_READY:
|
|
|
|
ret_state = eReady;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TX_COMPLETED:
|
|
|
|
case TX_TERMINATED:
|
|
|
|
ret_state = eDeleted;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TX_SUSPENDED:
|
|
|
|
case TX_SLEEP:
|
|
|
|
ret_state = eSuspended;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TX_QUEUE_SUSP:
|
|
|
|
case TX_SEMAPHORE_SUSP:
|
|
|
|
case TX_EVENT_FLAG:
|
|
|
|
case TX_BLOCK_MEMORY:
|
|
|
|
case TX_BYTE_MEMORY:
|
|
|
|
case TX_IO_DRIVER:
|
|
|
|
case TX_FILE:
|
|
|
|
case TX_TCP_IP:
|
|
|
|
case TX_MUTEX_SUSP:
|
|
|
|
ret_state = eBlocked;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ret_state = eInvalid;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret_state;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void vTaskDelayUntil(TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement)
|
|
|
|
{
|
|
|
|
TickType_t tick_cur;
|
|
|
|
|
|
|
|
tick_cur = (uint16_t)tx_time_get();
|
|
|
|
|
|
|
|
tx_thread_sleep(xTimeIncrement - (tick_cur - *pxPreviousWakeTime));
|
|
|
|
|
|
|
|
*pxPreviousWakeTime = *pxPreviousWakeTime + xTimeIncrement;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTaskNotifyGive(TaskHandle_t xTaskToNotify)
|
|
|
|
{
|
|
|
|
configASSERT(xTaskToNotify != NULL);
|
|
|
|
|
|
|
|
return xTaskNotify(xTaskToNotify, 0u, eIncrement);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void vTaskNotifyGiveFromISR(TaskHandle_t xTaskToNotify,
|
|
|
|
BaseType_t *pxHigherPriorityTaskWoken)
|
|
|
|
{
|
|
|
|
configASSERT(xTaskToNotify != NULL);
|
|
|
|
|
|
|
|
(void)xTaskNotify(xTaskToNotify, 0u, eIncrement);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t ulTaskNotifyTake(BaseType_t xClearCountOnExit,
|
|
|
|
TickType_t xTicksToWait)
|
|
|
|
{
|
|
|
|
TX_THREAD *p_thread;
|
|
|
|
uint32_t val;
|
|
|
|
UINT ret;
|
|
|
|
UCHAR pend;
|
|
|
|
txfr_task_t *p_task;
|
|
|
|
UINT timeout;
|
|
|
|
|
|
|
|
if(xTicksToWait == portMAX_DELAY) {
|
|
|
|
timeout = TX_WAIT_FOREVER;
|
|
|
|
} else {
|
|
|
|
timeout = (UINT)xTicksToWait;
|
|
|
|
}
|
|
|
|
|
|
|
|
pend = TX_FALSE;
|
|
|
|
p_thread = tx_thread_identify();
|
|
|
|
p_task = p_thread->txfr_thread_ptr;
|
|
|
|
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
|
|
|
|
ret = tx_semaphore_get(&p_task->notification_sem, 0u);
|
|
|
|
if(ret == TX_SUCCESS) {
|
|
|
|
val = p_task->task_notify_val;
|
|
|
|
p_task->p_notify_val_ret = NULL;
|
|
|
|
if(xClearCountOnExit != pdFALSE) {
|
|
|
|
p_task->task_notify_val = 0u;
|
|
|
|
} else {
|
|
|
|
p_task->task_notify_val--;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
pend = TX_TRUE;
|
|
|
|
p_task->p_notify_val_ret = &val;
|
|
|
|
p_task->clear_on_pend = xClearCountOnExit;
|
|
|
|
p_task->clear_mask = (uint32_t)-1;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
if(pend == TX_TRUE) {
|
|
|
|
ret = tx_semaphore_get(&p_task->notification_sem, timeout);
|
|
|
|
p_task->p_notify_val_ret = NULL;
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return 0u;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xTaskNotifyWait(uint32_t ulBitsToClearOnEntry,
|
|
|
|
uint32_t ulBitsToClearOnExit,
|
|
|
|
uint32_t *pulNotificationValue,
|
|
|
|
TickType_t xTicksToWait)
|
|
|
|
{
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
TX_THREAD *p_thread;
|
|
|
|
uint32_t val;
|
|
|
|
BaseType_t ret_val;
|
|
|
|
UINT ret;
|
|
|
|
UCHAR pend;
|
|
|
|
txfr_task_t *p_task;
|
|
|
|
UINT timeout;
|
|
|
|
|
|
|
|
ret_val = pdPASS;
|
|
|
|
|
|
|
|
if(xTicksToWait == portMAX_DELAY) {
|
|
|
|
timeout = TX_WAIT_FOREVER;
|
|
|
|
} else {
|
|
|
|
timeout = (UINT)xTicksToWait;
|
|
|
|
}
|
|
|
|
|
|
|
|
pend = TX_FALSE;
|
|
|
|
p_thread = tx_thread_identify();
|
|
|
|
p_task = p_thread->txfr_thread_ptr;
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
|
|
|
|
ret = tx_semaphore_get(&p_task->notification_sem, 0u);
|
|
|
|
if(ret == TX_SUCCESS) {
|
|
|
|
val = p_task->task_notify_val;
|
|
|
|
p_task->p_notify_val_ret = NULL;
|
|
|
|
if(ulBitsToClearOnExit != 0u) {
|
|
|
|
p_task->task_notify_val &= ~ulBitsToClearOnExit;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
pend = TX_TRUE;
|
|
|
|
p_task->p_notify_val_ret = &val;
|
|
|
|
p_task->clear_on_pend = 1u;
|
|
|
|
p_task->clear_mask = ulBitsToClearOnExit;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
if(pend == TX_TRUE) {
|
|
|
|
ret = tx_semaphore_get(&p_task->notification_sem, timeout);
|
|
|
|
p_task->p_notify_val_ret = NULL;
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return 0u;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*pulNotificationValue = val;
|
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTaskNotify(TaskHandle_t xTaskToNotify,
|
|
|
|
uint32_t ulValue,
|
|
|
|
eNotifyAction eAction)
|
|
|
|
{
|
|
|
|
|
|
|
|
configASSERT(TXFR_NOTIFYACTION_VALID(eAction));
|
|
|
|
|
|
|
|
return xTaskNotifyAndQuery(xTaskToNotify, ulValue, eAction, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xTaskNotifyFromISR(TaskHandle_t xTaskToNotify,
|
|
|
|
uint32_t ulValue,
|
|
|
|
eNotifyAction eAction,
|
|
|
|
BaseType_t *pxHigherPriorityTaskWoken)
|
|
|
|
{
|
|
|
|
|
|
|
|
configASSERT(xTaskToNotify != NULL);
|
|
|
|
configASSERT(TXFR_NOTIFYACTION_VALID(eAction));
|
|
|
|
|
|
|
|
return xTaskNotify(xTaskToNotify, ulValue, eAction);
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xTaskNotifyAndQuery(TaskHandle_t xTaskToNotify,
|
|
|
|
uint32_t ulValue,
|
|
|
|
eNotifyAction eAction,
|
|
|
|
uint32_t *pulPreviousNotifyValue)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
UCHAR notified;
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
BaseType_t ret_val;
|
|
|
|
UCHAR waiting;
|
|
|
|
|
|
|
|
configASSERT(xTaskToNotify != NULL);
|
|
|
|
configASSERT(TXFR_NOTIFYACTION_VALID(eAction));
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
|
|
|
|
if(pulPreviousNotifyValue != NULL) {
|
|
|
|
*pulPreviousNotifyValue = xTaskToNotify->task_notify_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
waiting = TX_FALSE;
|
|
|
|
notified = TX_FALSE;
|
|
|
|
ret_val = pdPASS;
|
|
|
|
|
|
|
|
if(xTaskToNotify->notification_sem.tx_semaphore_suspended_count != 0u) {
|
|
|
|
waiting = TX_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(xTaskToNotify->notification_sem.tx_semaphore_count == 0u) {
|
|
|
|
_tx_thread_preempt_disable++;
|
|
|
|
|
|
|
|
ret = tx_semaphore_put(&xTaskToNotify->notification_sem);
|
|
|
|
|
|
|
|
_tx_thread_preempt_disable--;
|
|
|
|
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_RESTORE;
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return pdFAIL;
|
|
|
|
}
|
|
|
|
xTaskToNotify->task_notify_val_pend = xTaskToNotify->task_notify_val;
|
|
|
|
|
|
|
|
notified = TX_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (eAction) {
|
|
|
|
case eNoAction:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eSetBits:
|
|
|
|
xTaskToNotify->task_notify_val |= ulValue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eIncrement:
|
|
|
|
xTaskToNotify->task_notify_val++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eSetValueWithOverwrite:
|
|
|
|
xTaskToNotify->task_notify_val = ulValue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eSetValueWithoutOverwrite:
|
|
|
|
if(notified == TX_TRUE) {
|
|
|
|
xTaskToNotify->task_notify_val = ulValue;
|
|
|
|
} else {
|
|
|
|
ret_val = pdFALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
TX_RESTORE;
|
|
|
|
return pdFAIL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(waiting == TX_TRUE) {
|
|
|
|
*xTaskToNotify->p_notify_val_ret = xTaskToNotify->task_notify_val;
|
|
|
|
|
|
|
|
if(xTaskToNotify->clear_on_pend == TX_TRUE) {
|
|
|
|
xTaskToNotify->task_notify_val &= ~xTaskToNotify->clear_mask;
|
|
|
|
} else {
|
|
|
|
xTaskToNotify->task_notify_val--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
_tx_thread_system_preempt_check();
|
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTaskNotifyAndQueryFromISR(TaskHandle_t xTaskToNotify,
|
|
|
|
uint32_t ulValue,
|
|
|
|
eNotifyAction eAction,
|
|
|
|
uint32_t *pulPreviousNotifyValue,
|
|
|
|
BaseType_t *pxHigherPriorityTaskWoken)
|
|
|
|
{
|
|
|
|
configASSERT(xTaskToNotify != NULL);
|
|
|
|
configASSERT(TXFR_NOTIFYACTION_VALID(eAction));
|
|
|
|
|
|
|
|
|
|
|
|
return xTaskNotifyAndQuery(xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTaskNotifyStateClear(TaskHandle_t xTask)
|
|
|
|
{
|
|
|
|
BaseType_t ret_val;
|
|
|
|
UINT ret;
|
|
|
|
TX_THREAD *p_thread;
|
|
|
|
txfr_task_t *p_task;
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
|
|
|
|
if(xTask == NULL) {
|
|
|
|
p_thread = tx_thread_identify();
|
|
|
|
p_task = p_thread->txfr_thread_ptr;
|
|
|
|
} else {
|
|
|
|
p_thread = &xTask->thread;
|
|
|
|
p_task = xTask;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
|
|
|
|
if(p_task->notification_sem.tx_semaphore_suspended_count != 0u) {
|
|
|
|
ret_val = pdTRUE;
|
|
|
|
} else {
|
|
|
|
ret_val = pdFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_semaphore_get(&p_task->notification_sem, 0u);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_RESTORE;
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t ulTaskNotifyValueClear(TaskHandle_t xTask,
|
|
|
|
uint32_t ulBitsToClear)
|
|
|
|
{
|
|
|
|
BaseType_t ret_val;
|
|
|
|
TX_THREAD *p_thread;
|
|
|
|
txfr_task_t *p_task;
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
|
|
|
|
if(xTask == NULL) {
|
|
|
|
p_thread = tx_thread_identify();
|
|
|
|
p_task = p_thread->txfr_thread_ptr;
|
|
|
|
} else {
|
|
|
|
p_thread = &xTask->thread;
|
|
|
|
p_task = xTask;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
|
|
|
|
ret_val = p_task->task_notify_val;
|
|
|
|
|
|
|
|
p_task->task_notify_val &= ~ulBitsToClear;
|
|
|
|
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount,
|
|
|
|
UBaseType_t uxInitialCount)
|
|
|
|
{
|
|
|
|
txfr_sem_t *p_sem;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(uxMaxCount != 0u);
|
|
|
|
configASSERT(uxInitialCount <= uxMaxCount);
|
|
|
|
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
if(txfr_initialized != 1u) {
|
|
|
|
tx_freertos_auto_init();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
p_sem = txfr_malloc(sizeof(txfr_sem_t));
|
|
|
|
if(p_sem == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_MEMSET(p_sem, 0, sizeof(*p_sem));
|
|
|
|
p_sem->max_count = uxMaxCount;
|
|
|
|
p_sem->allocated = 1u;
|
|
|
|
p_sem->is_mutex = 0u;
|
|
|
|
|
|
|
|
ret = tx_semaphore_create(&p_sem->sem, "", uxInitialCount);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
txfr_free(p_sem);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return p_sem;
|
|
|
|
}
|
|
|
|
|
|
|
|
SemaphoreHandle_t xSemaphoreCreateCountingStatic(UBaseType_t uxMaxCount,
|
|
|
|
UBaseType_t uxInitialCount,
|
|
|
|
StaticSemaphore_t *pxSemaphoreBuffer)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(uxMaxCount != 0u);
|
|
|
|
configASSERT(uxInitialCount <= uxMaxCount);
|
|
|
|
configASSERT(pxSemaphoreBuffer != NULL);
|
|
|
|
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
if(txfr_initialized != 1u) {
|
|
|
|
tx_freertos_auto_init();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
TX_MEMSET(pxSemaphoreBuffer, 0, sizeof(*pxSemaphoreBuffer));
|
|
|
|
pxSemaphoreBuffer->max_count = uxMaxCount;
|
|
|
|
pxSemaphoreBuffer->allocated = 0u;
|
|
|
|
pxSemaphoreBuffer->is_mutex = 0u;
|
|
|
|
|
|
|
|
ret = tx_semaphore_create(&pxSemaphoreBuffer->sem, "", uxInitialCount);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pxSemaphoreBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SemaphoreHandle_t xSemaphoreCreateBinary(void)
|
|
|
|
{
|
|
|
|
return xSemaphoreCreateCounting(1u, 0u);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SemaphoreHandle_t xSemaphoreCreateBinaryStatic(StaticSemaphore_t *pxSemaphoreBuffer)
|
|
|
|
{
|
|
|
|
configASSERT(pxSemaphoreBuffer != NULL);
|
|
|
|
|
|
|
|
return xSemaphoreCreateCountingStatic(1u, 0u, pxSemaphoreBuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SemaphoreHandle_t xSemaphoreCreateMutex(void)
|
|
|
|
{
|
|
|
|
txfr_sem_t *p_sem;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
if(txfr_initialized != 1u) {
|
|
|
|
tx_freertos_auto_init();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
p_sem = txfr_malloc(sizeof(txfr_sem_t));
|
|
|
|
if(p_sem == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_MEMSET(p_sem, 0, sizeof(*p_sem));
|
|
|
|
p_sem->max_count = 1u;
|
|
|
|
p_sem->allocated = 1u;
|
|
|
|
p_sem->is_mutex = 1u;
|
|
|
|
|
|
|
|
ret = tx_mutex_create(&p_sem->mutex, "", TX_NO_INHERIT);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
txfr_free(p_sem);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return p_sem;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SemaphoreHandle_t xSemaphoreCreateMutexStatic(StaticSemaphore_t *pxMutexBuffer)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(pxMutexBuffer != NULL);
|
|
|
|
|
|
|
|
TX_MEMSET(pxMutexBuffer, 0, sizeof(*pxMutexBuffer));
|
|
|
|
pxMutexBuffer->max_count = 1u;
|
|
|
|
pxMutexBuffer->allocated = 0u;
|
|
|
|
pxMutexBuffer->is_mutex = 1u;
|
|
|
|
|
|
|
|
ret = tx_mutex_create(&pxMutexBuffer->mutex, "", TX_NO_INHERIT);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pxMutexBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex(void)
|
|
|
|
{
|
|
|
|
txfr_sem_t *p_sem;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
if(txfr_initialized != 1u) {
|
|
|
|
tx_freertos_auto_init();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
p_sem = txfr_malloc(sizeof(txfr_sem_t));
|
|
|
|
if(p_sem == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_MEMSET(p_sem, 0, sizeof(*p_sem));
|
|
|
|
p_sem->max_count = 1u;
|
|
|
|
p_sem->allocated = 1u;
|
|
|
|
p_sem->is_mutex = 1u;
|
|
|
|
|
|
|
|
ret = tx_mutex_create(&p_sem->mutex, "", TX_INHERIT);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
txfr_free(p_sem);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return p_sem;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic(StaticSemaphore_t *pxMutexBuffer)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(pxMutexBuffer != NULL);
|
|
|
|
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
if(txfr_initialized != 1u) {
|
|
|
|
tx_freertos_auto_init();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
TX_MEMSET(pxMutexBuffer, 0, sizeof(*pxMutexBuffer));
|
|
|
|
pxMutexBuffer->max_count = 1u;
|
|
|
|
pxMutexBuffer->allocated = 0u;
|
|
|
|
pxMutexBuffer->is_mutex = 1u;
|
|
|
|
|
|
|
|
ret = tx_mutex_create(&pxMutexBuffer->mutex, "", TX_INHERIT);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pxMutexBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vSemaphoreDelete(SemaphoreHandle_t xSemaphore)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xSemaphore != NULL);
|
|
|
|
|
|
|
|
if(xSemaphore->is_mutex == 0u) {
|
|
|
|
ret = tx_semaphore_delete(&xSemaphore->sem);
|
|
|
|
} else {
|
|
|
|
ret = tx_mutex_delete(&xSemaphore->mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(xSemaphore->allocated == 1u) {
|
|
|
|
vPortFree(xSemaphore);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait)
|
|
|
|
{
|
|
|
|
UINT timeout;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xSemaphore != NULL);
|
|
|
|
|
|
|
|
if(xTicksToWait == portMAX_DELAY) {
|
|
|
|
timeout = TX_WAIT_FOREVER;
|
|
|
|
} else {
|
|
|
|
timeout = (UINT)xTicksToWait;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(xSemaphore->is_mutex == 1u) {
|
|
|
|
if(xSemaphore->mutex.tx_mutex_owner == tx_thread_identify()) {
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
ret = tx_mutex_get(&xSemaphore->mutex, timeout);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ret = tx_semaphore_get(&xSemaphore->sem, timeout);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pdTRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xSemaphoreTakeFromISR(SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xSemaphore != NULL);
|
|
|
|
|
|
|
|
if(xSemaphore->is_mutex == 1u) {
|
|
|
|
return pdFALSE;
|
|
|
|
} else {
|
|
|
|
ret = tx_semaphore_get(&xSemaphore->sem, 0u);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pdTRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xSemaphoreTakeRecursive(SemaphoreHandle_t xMutex, TickType_t xTicksToWait)
|
|
|
|
{
|
|
|
|
UINT timeout;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xMutex != NULL);
|
|
|
|
|
|
|
|
if(xTicksToWait == portMAX_DELAY) {
|
|
|
|
timeout = TX_WAIT_FOREVER;
|
|
|
|
} else {
|
|
|
|
timeout = (UINT)xTicksToWait;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(xMutex->is_mutex == 1u) {
|
|
|
|
ret = tx_mutex_get(&xMutex->mutex, timeout);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ret = tx_semaphore_get(&xMutex->sem, timeout);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pdTRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore)
|
|
|
|
{
|
|
|
|
TX_INTERRUPT_SAVE_AREA
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xSemaphore != NULL);
|
|
|
|
|
|
|
|
if(xSemaphore->is_mutex == 1u) {
|
|
|
|
ret = tx_mutex_put(&xSemaphore->mutex);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
|
2022-01-29 00:24:03 +00:00
|
|
|
return pdTRUE;
|
|
|
|
}
|
2020-10-01 13:46:52 -07:00
|
|
|
|
2022-01-29 00:24:03 +00:00
|
|
|
TX_DISABLE;
|
|
|
|
_tx_thread_preempt_disable++;
|
2020-10-01 13:46:52 -07:00
|
|
|
|
2022-01-29 00:24:03 +00:00
|
|
|
if(xSemaphore->sem.tx_semaphore_count >= xSemaphore->max_count) {
|
|
|
|
/* Maximum semaphore count reached return failure. */
|
|
|
|
_tx_thread_preempt_disable--;
|
|
|
|
TX_RESTORE
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
2020-10-01 13:46:52 -07:00
|
|
|
|
2022-01-29 00:24:03 +00:00
|
|
|
ret = tx_semaphore_put(&xSemaphore->sem);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
_tx_thread_preempt_disable--;
|
|
|
|
TX_RESTORE;
|
|
|
|
return pdFALSE;
|
2020-10-01 13:46:52 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if(xSemaphore->p_set != NULL) {
|
|
|
|
// To prevent deadlocks don't wait when posting on a queue set.
|
|
|
|
ret = tx_queue_send(&xSemaphore->p_set->queue, &xSemaphore, TX_NO_WAIT);
|
|
|
|
if((ret != TX_SUCCESS) && (ret != TX_QUEUE_FULL)) {
|
|
|
|
// Fatal error, queue full errors are ignored on purpose to match the original behaviour.
|
|
|
|
_tx_thread_preempt_disable--;
|
|
|
|
TX_RESTORE;
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
2022-01-29 00:24:03 +00:00
|
|
|
}
|
2020-10-01 13:46:52 -07:00
|
|
|
|
2022-01-29 00:24:03 +00:00
|
|
|
_tx_thread_preempt_disable--;
|
|
|
|
TX_RESTORE;
|
2020-10-01 13:46:52 -07:00
|
|
|
|
2022-01-29 00:24:03 +00:00
|
|
|
_tx_thread_system_preempt_check();
|
2020-10-01 13:46:52 -07:00
|
|
|
|
|
|
|
return pdTRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xSemaphoreGiveFromISR(SemaphoreHandle_t xSemaphore, BaseType_t *pxHigherPriorityTaskWoken)
|
|
|
|
{
|
|
|
|
|
|
|
|
configASSERT(xSemaphore != NULL);
|
|
|
|
|
|
|
|
return xSemaphoreGive(xSemaphore);
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xSemaphoreGiveRecursive(SemaphoreHandle_t xMutex)
|
|
|
|
{
|
|
|
|
|
|
|
|
configASSERT(xMutex != NULL);
|
|
|
|
|
|
|
|
return xSemaphoreGive(xMutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
UBaseType_t uxSemaphoreGetCount(SemaphoreHandle_t xSemaphore)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
ULONG count;
|
|
|
|
|
|
|
|
configASSERT(xSemaphore != NULL);
|
|
|
|
|
|
|
|
ret = tx_semaphore_info_get(&xSemaphore->sem, NULL, &count, NULL, NULL, NULL);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
TaskHandle_t xSemaphoreGetMutexHolder(SemaphoreHandle_t xMutex)
|
|
|
|
{
|
|
|
|
configASSERT(xMutex != NULL);
|
|
|
|
|
|
|
|
return xMutex->mutex.tx_mutex_owner->txfr_thread_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TaskHandle_t xSemaphoreGetMutexHolderFromISR(SemaphoreHandle_t xMutex)
|
|
|
|
{
|
|
|
|
return xSemaphoreGetMutexHolder(xMutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TickType_t xTaskGetTickCount(void)
|
|
|
|
{
|
|
|
|
return tx_time_get();
|
|
|
|
}
|
|
|
|
|
|
|
|
TickType_t xTaskGetTickCountFromISR(void)
|
|
|
|
{
|
|
|
|
return tx_time_get();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QueueHandle_t xQueueCreateStatic(UBaseType_t uxQueueLength,
|
|
|
|
UBaseType_t uxItemSize,
|
|
|
|
uint8_t *pucQueueStorageBuffer,
|
|
|
|
StaticQueue_t *pxQueueBuffer)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(uxQueueLength != 0u);
|
|
|
|
configASSERT(uxItemSize >= sizeof(UINT));
|
|
|
|
configASSERT(pucQueueStorageBuffer != NULL);
|
|
|
|
configASSERT(pxQueueBuffer != NULL);
|
|
|
|
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
if(txfr_initialized != 1u) {
|
|
|
|
tx_freertos_auto_init();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
TX_MEMSET(pucQueueStorageBuffer, 0, uxQueueLength * uxItemSize);
|
|
|
|
TX_MEMSET(pxQueueBuffer, 0, sizeof(*pxQueueBuffer));
|
|
|
|
pxQueueBuffer->allocated = 0u;
|
|
|
|
pxQueueBuffer->p_mem = pucQueueStorageBuffer;
|
|
|
|
pxQueueBuffer->id = TX_QUEUE_ID;
|
|
|
|
|
|
|
|
pxQueueBuffer->p_write = (uint8_t *)pucQueueStorageBuffer;
|
|
|
|
pxQueueBuffer->p_read = (uint8_t *)pucQueueStorageBuffer;
|
|
|
|
pxQueueBuffer->msg_size = uxItemSize;
|
|
|
|
pxQueueBuffer->queue_length = uxQueueLength;
|
|
|
|
|
|
|
|
ret = tx_semaphore_create(&pxQueueBuffer->read_sem, "", 0u);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_semaphore_create(&pxQueueBuffer->write_sem, "", uxQueueLength);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pxQueueBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize)
|
|
|
|
{
|
|
|
|
txfr_queue_t *p_queue;
|
|
|
|
void *p_mem;
|
|
|
|
size_t mem_size;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(uxQueueLength != 0u);
|
|
|
|
configASSERT(uxItemSize >= sizeof(UINT));
|
|
|
|
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
if(txfr_initialized != 1u) {
|
|
|
|
tx_freertos_auto_init();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-12-28 13:17:40 +08:00
|
|
|
if ((uxQueueLength > (SIZE_MAX / uxItemSize)) ||
|
|
|
|
(uxQueueLength > (ULONG_MAX / uxItemSize))) {
|
|
|
|
|
|
|
|
/* Integer overflow in queue size */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-10-01 13:46:52 -07:00
|
|
|
p_queue = txfr_malloc(sizeof(txfr_queue_t));
|
|
|
|
if(p_queue == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
mem_size = uxQueueLength*(uxItemSize);
|
|
|
|
|
|
|
|
p_mem = txfr_malloc(mem_size);
|
|
|
|
if(p_mem == NULL) {
|
|
|
|
txfr_free(p_queue);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_MEMSET(p_mem, 0, mem_size);
|
|
|
|
TX_MEMSET(p_queue, 0, sizeof(*p_queue));
|
|
|
|
p_queue->allocated = 1u;
|
|
|
|
p_queue->p_mem = p_mem;
|
|
|
|
p_queue->id = TX_QUEUE_ID;
|
|
|
|
|
|
|
|
p_queue->p_write = (uint8_t *)p_mem;
|
|
|
|
p_queue->p_read = (uint8_t *)p_mem;
|
|
|
|
p_queue->msg_size = uxItemSize;
|
|
|
|
p_queue->queue_length = uxQueueLength;
|
|
|
|
|
|
|
|
ret = tx_semaphore_create(&p_queue->read_sem, "", 0u);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_semaphore_create(&p_queue->write_sem, "", uxQueueLength);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return p_queue;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vQueueDelete(QueueHandle_t xQueue)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
|
|
|
|
ret = tx_semaphore_delete(&xQueue->read_sem);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_semaphore_delete(&xQueue->write_sem);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(xQueue->allocated == 1u) {
|
|
|
|
vPortFree(xQueue->p_mem);
|
|
|
|
vPortFree(xQueue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xQueueSend(QueueHandle_t xQueue,
|
|
|
|
const void *pvItemToQueue,
|
|
|
|
TickType_t xTicksToWait)
|
|
|
|
{
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
UINT timeout;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
configASSERT(pvItemToQueue != NULL);
|
|
|
|
|
|
|
|
if(xTicksToWait == portMAX_DELAY) {
|
|
|
|
timeout = TX_WAIT_FOREVER;
|
|
|
|
} else {
|
|
|
|
timeout = (UINT)xTicksToWait;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for space to be available on the queue.
|
|
|
|
ret = tx_semaphore_get(&xQueue->write_sem, timeout);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enqueue the message.
|
|
|
|
TX_DISABLE;
|
|
|
|
memcpy(xQueue->p_write, pvItemToQueue, xQueue->msg_size);
|
|
|
|
if(xQueue->p_write >= (xQueue->p_mem + (xQueue->msg_size * (xQueue->queue_length - 1u)))) {
|
|
|
|
xQueue->p_write = xQueue->p_mem;
|
|
|
|
} else {
|
|
|
|
xQueue->p_write += xQueue->msg_size;
|
|
|
|
}
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
// Signal that there is an additional message available on the queue.
|
|
|
|
ret = tx_semaphore_put(&xQueue->read_sem);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(xQueue->p_set != NULL) {
|
|
|
|
// To prevent deadlocks don't wait when posting on a queue set.
|
|
|
|
ret = tx_queue_send(&xQueue->p_set->queue, &xQueue, TX_NO_WAIT);
|
|
|
|
if((ret != TX_SUCCESS) && (ret != TX_QUEUE_FULL)) {
|
|
|
|
// Fatal error, queue full errors are ignored on purpose to match the original behaviour.
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return pdPASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xQueueSendFromISR(QueueHandle_t xQueue,
|
|
|
|
const void * pvItemToQueue,
|
|
|
|
BaseType_t *pxHigherPriorityTaskWoken)
|
|
|
|
{
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
configASSERT(pvItemToQueue != NULL);
|
|
|
|
|
|
|
|
return xQueueSend(xQueue, pvItemToQueue, 0u);
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xQueueSendToBack(QueueHandle_t xQueue,
|
|
|
|
const void * pvItemToQueue,
|
|
|
|
TickType_t xTicksToWait)
|
|
|
|
{
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
configASSERT(pvItemToQueue != NULL);
|
|
|
|
|
|
|
|
return xQueueSend(xQueue, pvItemToQueue, xTicksToWait);
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xQueueSendToBackFromISR(QueueHandle_t xQueue,
|
|
|
|
const void * pvItemToQueue,
|
|
|
|
BaseType_t *pxHigherPriorityTaskWoken)
|
|
|
|
{
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
configASSERT(pvItemToQueue != NULL);
|
|
|
|
|
|
|
|
return xQueueSend(xQueue, pvItemToQueue, 0u);
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xQueueSendToFront(QueueHandle_t xQueue,
|
|
|
|
const void *pvItemToQueue,
|
|
|
|
TickType_t xTicksToWait)
|
|
|
|
{
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
UINT timeout;
|
|
|
|
UINT ret;
|
|
|
|
// TODO-
|
|
|
|
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
configASSERT(pvItemToQueue != NULL);
|
|
|
|
|
|
|
|
if(xTicksToWait == portMAX_DELAY) {
|
|
|
|
timeout = TX_WAIT_FOREVER;
|
|
|
|
} else {
|
|
|
|
timeout = (UINT)xTicksToWait;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(xQueue->p_set != NULL) {
|
|
|
|
TX_DISABLE;
|
|
|
|
_tx_thread_preempt_disable++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for space to be available on the queue.
|
|
|
|
ret = tx_semaphore_get(&xQueue->write_sem, timeout);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enqueue the message at the front.
|
|
|
|
TX_DISABLE;
|
|
|
|
// Push back the read pointer.
|
|
|
|
if(xQueue->p_read == xQueue->p_mem) {
|
|
|
|
xQueue->p_read = xQueue->p_mem + (xQueue->msg_size * (xQueue->queue_length - 1u));
|
|
|
|
} else {
|
|
|
|
xQueue->p_read -= xQueue->msg_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(xQueue->p_read, pvItemToQueue, xQueue->msg_size);
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
// Signal that there is an additional message available on the queue.
|
|
|
|
ret = tx_semaphore_put(&xQueue->read_sem);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
if(xQueue->p_set != NULL) {
|
|
|
|
_tx_thread_preempt_disable--;
|
|
|
|
TX_RESTORE;
|
|
|
|
}
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(xQueue->p_set != NULL) {
|
|
|
|
// To prevent deadlocks don't wait when posting on a queue set.
|
|
|
|
ret = tx_queue_send(&xQueue->p_set->queue, &xQueue, TX_NO_WAIT);
|
|
|
|
if((ret != TX_SUCCESS) && (ret != TX_QUEUE_FULL)) {
|
|
|
|
// Fatal error, queue full errors are ignored on purpose to match the original behaviour.
|
|
|
|
_tx_thread_preempt_disable--;
|
|
|
|
TX_RESTORE;
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_RESTORE;
|
|
|
|
_tx_thread_preempt_disable--;
|
|
|
|
|
|
|
|
_tx_thread_system_preempt_check();
|
|
|
|
}
|
|
|
|
|
|
|
|
return pdPASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xQueueSendToFrontFromISR(QueueHandle_t xQueue,
|
|
|
|
const void * pvItemToQueue,
|
|
|
|
BaseType_t *pxHigherPriorityTaskWoken)
|
|
|
|
{
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
configASSERT(pvItemToQueue != NULL);
|
|
|
|
|
|
|
|
return xQueueSendToFront(xQueue, pvItemToQueue, 0u);
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xQueueReceive(QueueHandle_t xQueue,
|
|
|
|
void *pvBuffer,
|
|
|
|
TickType_t xTicksToWait)
|
|
|
|
{
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
UINT timeout;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
configASSERT(pvBuffer != NULL);
|
|
|
|
|
|
|
|
if(xTicksToWait == portMAX_DELAY) {
|
|
|
|
timeout = TX_WAIT_FOREVER;
|
|
|
|
} else {
|
|
|
|
timeout = (UINT)xTicksToWait;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for a message to be available on the queue.
|
|
|
|
ret = tx_semaphore_get(&xQueue->read_sem, timeout);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return pdFAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retrieve the message.
|
|
|
|
TX_DISABLE
|
|
|
|
memcpy(pvBuffer, xQueue->p_read, xQueue->msg_size);
|
|
|
|
if(xQueue->p_read >= (xQueue->p_mem + (xQueue->msg_size * (xQueue->queue_length - 1u)))) {
|
|
|
|
xQueue->p_read = xQueue->p_mem;
|
|
|
|
} else {
|
|
|
|
xQueue->p_read += xQueue->msg_size;
|
|
|
|
}
|
|
|
|
TX_RESTORE
|
|
|
|
|
|
|
|
// Signal that there's additional space available on the queue.
|
|
|
|
ret = tx_semaphore_put(&xQueue->write_sem);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pdPASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xQueueReceiveFromISR(QueueHandle_t xQueue,
|
|
|
|
void *pvBuffer,
|
|
|
|
BaseType_t *pxHigherPriorityTaskWoken)
|
|
|
|
{
|
|
|
|
BaseType_t ret;
|
|
|
|
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
configASSERT(pvBuffer != NULL);
|
|
|
|
|
|
|
|
ret = xQueueReceive(xQueue, pvBuffer, 0u);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xQueuePeek(QueueHandle_t xQueue,
|
|
|
|
void *pvBuffer,
|
|
|
|
TickType_t xTicksToWait)
|
|
|
|
{
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
UINT timeout;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
configASSERT(pvBuffer != NULL);
|
|
|
|
|
|
|
|
if(xTicksToWait == portMAX_DELAY) {
|
|
|
|
timeout = TX_WAIT_FOREVER;
|
|
|
|
} else {
|
|
|
|
timeout = (UINT)xTicksToWait;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait for a message to be available on the queue.
|
|
|
|
ret = tx_semaphore_get(&xQueue->read_sem, timeout);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return pdFAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retrieve the message.
|
|
|
|
TX_DISABLE;
|
|
|
|
_tx_thread_preempt_disable++;
|
|
|
|
|
|
|
|
memcpy(pvBuffer, xQueue->p_read, xQueue->msg_size);
|
|
|
|
|
|
|
|
// Restore the original space on the queue.
|
|
|
|
ret = tx_semaphore_put(&xQueue->read_sem);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
_tx_thread_preempt_disable--;
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return pdPASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xQueuePeekFromISR(QueueHandle_t xQueue,
|
|
|
|
void *pvBuffer)
|
|
|
|
{
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
configASSERT(pvBuffer != NULL);
|
|
|
|
|
|
|
|
return xQueuePeek(xQueue, pvBuffer, 0u);
|
|
|
|
}
|
|
|
|
|
|
|
|
UBaseType_t uxQueueMessagesWaiting(QueueHandle_t xQueue)
|
|
|
|
{
|
|
|
|
ULONG count;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
|
|
|
|
ret = tx_semaphore_info_get(&xQueue->read_sem, NULL, &count, NULL, NULL, NULL);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
UBaseType_t uxQueueMessagesWaitingFromISR(QueueHandle_t xQueue)
|
|
|
|
{
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
|
|
|
|
return uxQueueMessagesWaiting(xQueue);
|
|
|
|
}
|
|
|
|
|
|
|
|
UBaseType_t uxQueueSpacesAvailable(QueueHandle_t xQueue)
|
|
|
|
{
|
|
|
|
ULONG count;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
|
|
|
|
ret = tx_semaphore_info_get(&xQueue->write_sem, NULL, &count, NULL, NULL, NULL);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xQueueIsQueueEmptyFromISR(const QueueHandle_t xQueue)
|
|
|
|
{
|
|
|
|
ULONG count;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
|
|
|
|
ret = tx_semaphore_info_get(&xQueue->read_sem, NULL, &count, NULL, NULL, NULL);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(count == 0u) {
|
|
|
|
return pdTRUE;
|
|
|
|
} else {
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xQueueIsQueueFullFromISR(const QueueHandle_t xQueue)
|
|
|
|
{
|
|
|
|
ULONG count;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
|
|
|
|
ret = tx_semaphore_info_get(&xQueue->write_sem, NULL, &count, NULL, NULL, NULL);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(count == 0u) {
|
|
|
|
return pdTRUE;
|
|
|
|
} else {
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xQueueReset(QueueHandle_t xQueue)
|
|
|
|
{
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
UINT ret;
|
|
|
|
UINT write_post;
|
|
|
|
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
|
|
|
|
write_post = 0u;
|
|
|
|
TX_DISABLE;
|
|
|
|
_tx_thread_preempt_disable++;
|
|
|
|
|
|
|
|
// Reset pointers.
|
|
|
|
xQueue->p_write = xQueue->p_mem;
|
|
|
|
xQueue->p_read = xQueue->p_mem;
|
|
|
|
|
|
|
|
// Reset read semaphore.
|
|
|
|
xQueue->read_sem.tx_semaphore_count = 0u;
|
|
|
|
|
|
|
|
// Reset write semaphore.
|
|
|
|
if(xQueue->write_sem.tx_semaphore_count != xQueue->queue_length) {
|
|
|
|
write_post = 1u;
|
|
|
|
xQueue->write_sem.tx_semaphore_count = xQueue->queue_length - 1u;
|
|
|
|
}
|
|
|
|
|
|
|
|
_tx_thread_preempt_disable--;
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
if(write_post == 1u) {
|
|
|
|
// Signal that there's space available on the queue in case a writer was waiting before the reset.
|
|
|
|
ret = tx_semaphore_put(&xQueue->write_sem);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
_tx_thread_system_preempt_check();
|
|
|
|
}
|
|
|
|
|
|
|
|
return pdPASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xQueueOverwrite(QueueHandle_t xQueue,
|
|
|
|
const void * pvItemToQueue)
|
|
|
|
{
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
UINT ret;
|
|
|
|
UINT read_post;
|
|
|
|
uint8_t *p_write_temp;
|
|
|
|
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
configASSERT(pvItemToQueue != NULL);
|
|
|
|
|
|
|
|
read_post = 0u;
|
|
|
|
TX_DISABLE;
|
|
|
|
|
|
|
|
if(xQueue->read_sem.tx_semaphore_count != 0u) {
|
|
|
|
// Go back one message.
|
|
|
|
p_write_temp = xQueue->p_write;
|
|
|
|
if(p_write_temp == xQueue->p_mem) {
|
|
|
|
p_write_temp = (xQueue->p_mem + (xQueue->msg_size * (xQueue->queue_length - 1u)));
|
|
|
|
} else {
|
|
|
|
p_write_temp -= xQueue->msg_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(p_write_temp, pvItemToQueue, xQueue->msg_size);
|
|
|
|
} else {
|
|
|
|
memcpy(xQueue->p_write, pvItemToQueue, xQueue->msg_size);
|
|
|
|
if(xQueue->p_write >= (xQueue->p_mem + (xQueue->msg_size * (xQueue->queue_length - 1u)))) {
|
|
|
|
xQueue->p_write = xQueue->p_mem;
|
|
|
|
} else {
|
|
|
|
xQueue->p_write += xQueue->msg_size;
|
|
|
|
}
|
|
|
|
read_post = 1u;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
if(read_post == 1u) {
|
|
|
|
// Signal that there is an additional message available on the queue.
|
|
|
|
ret = tx_semaphore_put(&xQueue->read_sem);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pdPASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xQueueOverwriteFromISR(QueueHandle_t xQueue,
|
|
|
|
const void * pvItemToQueue,
|
|
|
|
BaseType_t *pxHigherPriorityTaskWoken)
|
|
|
|
{
|
|
|
|
configASSERT(xQueue != NULL);
|
|
|
|
configASSERT(pvItemToQueue != NULL);
|
|
|
|
|
|
|
|
return xQueueOverwrite(xQueue, pvItemToQueue);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EventGroupHandle_t xEventGroupCreate(void)
|
|
|
|
{
|
|
|
|
txfr_event_t *p_event;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
if(txfr_initialized != 1u) {
|
|
|
|
tx_freertos_auto_init();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
p_event = txfr_malloc(sizeof(txfr_event_t));
|
|
|
|
if(p_event == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_MEMSET(p_event, 0, sizeof(*p_event));
|
|
|
|
p_event->allocated = 1u;
|
|
|
|
|
|
|
|
ret = tx_event_flags_create(&p_event->event, "");
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
txfr_free(p_event);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return p_event;
|
|
|
|
}
|
|
|
|
|
|
|
|
EventGroupHandle_t xEventGroupCreateStatic(StaticEventGroup_t *pxEventGroupBuffer)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(pxEventGroupBuffer != NULL);
|
|
|
|
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
if(txfr_initialized != 1u) {
|
|
|
|
tx_freertos_auto_init();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
TX_MEMSET(pxEventGroupBuffer, 0, sizeof(*pxEventGroupBuffer));
|
|
|
|
pxEventGroupBuffer->allocated = 0u;
|
|
|
|
|
|
|
|
ret = tx_event_flags_create(&pxEventGroupBuffer->event, "");
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pxEventGroupBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vEventGroupDelete(EventGroupHandle_t xEventGroup)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xEventGroup != NULL);
|
|
|
|
|
|
|
|
ret = tx_event_flags_delete(&xEventGroup->event);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(xEventGroup->allocated == 1u) {
|
|
|
|
vPortFree(xEventGroup);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EventBits_t xEventGroupWaitBits(const EventGroupHandle_t xEventGroup,
|
|
|
|
const EventBits_t uxBitsToWaitFor,
|
|
|
|
const BaseType_t xClearOnExit,
|
|
|
|
const BaseType_t xWaitForAllBits,
|
|
|
|
TickType_t xTicksToWait)
|
|
|
|
{
|
|
|
|
ULONG bits;
|
|
|
|
UINT timeout;
|
|
|
|
UINT ret;
|
|
|
|
UINT get_option;
|
|
|
|
|
|
|
|
configASSERT(xEventGroup != NULL);
|
|
|
|
|
|
|
|
if(xTicksToWait == portMAX_DELAY) {
|
|
|
|
timeout = TX_WAIT_FOREVER;
|
|
|
|
} else {
|
|
|
|
timeout = (UINT)xTicksToWait;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(xWaitForAllBits == pdFALSE) {
|
|
|
|
if(xClearOnExit == pdFALSE) {
|
|
|
|
get_option = TX_OR;
|
|
|
|
} else {
|
|
|
|
get_option = TX_OR_CLEAR;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(xClearOnExit == pdFALSE) {
|
|
|
|
get_option = TX_AND;
|
|
|
|
} else {
|
|
|
|
get_option = TX_AND_CLEAR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_event_flags_get(&xEventGroup->event, uxBitsToWaitFor, get_option, &bits, timeout);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bits;
|
|
|
|
}
|
|
|
|
|
|
|
|
EventBits_t xEventGroupSetBits(EventGroupHandle_t xEventGroup,
|
|
|
|
const EventBits_t uxBitsToSet)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
ULONG bits;
|
|
|
|
|
|
|
|
configASSERT(xEventGroup != NULL);
|
|
|
|
|
|
|
|
ret = tx_event_flags_set(&xEventGroup->event, uxBitsToSet, TX_OR);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return 0u;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_event_flags_info_get(&xEventGroup->event, NULL, &bits, NULL, NULL, NULL);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return 0u;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bits;
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xEventGroupSetBitsFromISR(EventGroupHandle_t xEventGroup,
|
|
|
|
const EventBits_t uxBitsToSet,
|
|
|
|
BaseType_t *pxHigherPriorityTaskWoken)
|
|
|
|
{
|
|
|
|
configASSERT(xEventGroup != NULL);
|
|
|
|
|
|
|
|
return xEventGroupSetBits(xEventGroup, uxBitsToSet);
|
|
|
|
}
|
|
|
|
|
|
|
|
EventBits_t xEventGroupClearBits(EventGroupHandle_t xEventGroup,
|
|
|
|
const EventBits_t uxBitsToClear)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
ULONG bits;
|
|
|
|
ULONG bits_before;
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
|
|
|
|
configASSERT(xEventGroup != NULL);
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
|
|
|
|
ret = tx_event_flags_info_get(&xEventGroup->event, NULL, &bits_before, NULL, NULL, NULL);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_RESTORE;
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return 0u;
|
|
|
|
}
|
|
|
|
|
|
|
|
bits = uxBitsToClear;
|
|
|
|
ret = tx_event_flags_set(&xEventGroup->event, ~bits, TX_AND);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_RESTORE;
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return 0u;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return bits_before;
|
|
|
|
}
|
|
|
|
|
|
|
|
BaseType_t xEventGroupClearBitsFromISR(EventGroupHandle_t xEventGroup,
|
|
|
|
const EventBits_t uxBitsToClear)
|
|
|
|
{
|
|
|
|
configASSERT(xEventGroup != NULL);
|
|
|
|
|
|
|
|
return xEventGroupClearBits(xEventGroup, uxBitsToClear);
|
|
|
|
}
|
|
|
|
|
|
|
|
EventBits_t xEventGroupGetBits(EventGroupHandle_t xEventGroup)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
ULONG bits;
|
|
|
|
|
|
|
|
configASSERT(xEventGroup != NULL);
|
|
|
|
|
|
|
|
ret = tx_event_flags_info_get(&xEventGroup->event, NULL, &bits, NULL, NULL, NULL);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return 0u;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bits;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EventBits_t xEventGroupGetBitsFromISR(EventGroupHandle_t xEventGroup)
|
|
|
|
{
|
|
|
|
configASSERT(xEventGroup != NULL);
|
|
|
|
|
|
|
|
return xEventGroupGetBits(xEventGroup);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void txfr_timer_callback_wrapper(ULONG id)
|
|
|
|
{
|
|
|
|
txfr_timer_t *p_timer;
|
|
|
|
|
|
|
|
p_timer = (txfr_timer_t *)id;
|
|
|
|
|
|
|
|
if(p_timer == NULL) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
}
|
|
|
|
|
|
|
|
p_timer->callback(p_timer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TimerHandle_t xTimerCreate(const char * const pcTimerName,
|
|
|
|
const TickType_t xTimerPeriod,
|
|
|
|
const UBaseType_t uxAutoReload,
|
|
|
|
void * const pvTimerID,
|
|
|
|
TimerCallbackFunction_t pxCallbackFunction)
|
|
|
|
{
|
|
|
|
txfr_timer_t *p_timer;
|
|
|
|
UINT ret;
|
|
|
|
ULONG resch_ticks;
|
|
|
|
|
|
|
|
configASSERT(xTimerPeriod != 0u);
|
|
|
|
configASSERT(pxCallbackFunction != NULL);
|
|
|
|
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
if(txfr_initialized != 1u) {
|
|
|
|
tx_freertos_auto_init();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
p_timer = txfr_malloc(sizeof(txfr_timer_t));
|
|
|
|
if(p_timer == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_MEMSET(p_timer, 0, sizeof(*p_timer));
|
|
|
|
p_timer->allocated = 1u;
|
|
|
|
p_timer->period = xTimerPeriod;
|
|
|
|
p_timer->id = pvTimerID;
|
|
|
|
p_timer->callback = pxCallbackFunction;
|
|
|
|
|
|
|
|
if(uxAutoReload != pdFALSE) {
|
|
|
|
resch_ticks = xTimerPeriod;
|
|
|
|
p_timer->one_shot = 1u;
|
|
|
|
} else {
|
|
|
|
p_timer->one_shot = 0u;
|
|
|
|
resch_ticks = 0u;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_timer_create(&p_timer->timer, (char *)pcTimerName, txfr_timer_callback_wrapper, (ULONG)p_timer, xTimerPeriod, resch_ticks, TX_NO_ACTIVATE);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
txfr_free(p_timer);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return p_timer;
|
|
|
|
}
|
|
|
|
|
|
|
|
TimerHandle_t xTimerCreateStatic(const char * const pcTimerName,
|
|
|
|
const TickType_t xTimerPeriod,
|
|
|
|
const UBaseType_t uxAutoReload,
|
|
|
|
void * const pvTimerID,
|
|
|
|
TimerCallbackFunction_t pxCallbackFunction,
|
|
|
|
StaticTimer_t *pxTimerBuffer)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
ULONG resch_ticks;
|
|
|
|
|
|
|
|
configASSERT(xTimerPeriod != 0u);
|
|
|
|
configASSERT(pxCallbackFunction != NULL);
|
|
|
|
configASSERT(pxTimerBuffer != NULL);
|
|
|
|
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
if(txfr_initialized != 1u) {
|
|
|
|
tx_freertos_auto_init();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
TX_MEMSET(pxTimerBuffer, 0, sizeof(*pxTimerBuffer));
|
|
|
|
pxTimerBuffer->allocated = 0u;
|
|
|
|
pxTimerBuffer->period = xTimerPeriod;
|
|
|
|
pxTimerBuffer->id = pvTimerID;
|
|
|
|
pxTimerBuffer->callback = pxCallbackFunction;
|
|
|
|
|
|
|
|
if(uxAutoReload != pdFALSE) {
|
|
|
|
resch_ticks = xTimerPeriod;
|
|
|
|
} else {
|
|
|
|
resch_ticks = 0u;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_timer_create(&pxTimerBuffer->timer, (char *)pcTimerName, txfr_timer_callback_wrapper, (ULONG)pxTimerBuffer, xTimerPeriod, resch_ticks, TX_NO_ACTIVATE);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pxTimerBuffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTimerDelete(TimerHandle_t xTimer, TickType_t xBlockTime)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xTimer != NULL);
|
|
|
|
|
|
|
|
ret = tx_timer_delete(&xTimer->timer);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return pdFAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(xTimer->allocated == 1u) {
|
|
|
|
vPortFree(xTimer);
|
|
|
|
}
|
|
|
|
|
|
|
|
return pdPASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTimerIsTimerActive(TimerHandle_t xTimer)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
UINT is_active;
|
|
|
|
|
|
|
|
configASSERT(xTimer != NULL);
|
|
|
|
|
|
|
|
ret = tx_timer_info_get(&xTimer->timer, NULL, &is_active, NULL, NULL, NULL);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(is_active == TX_TRUE) {
|
|
|
|
return pdTRUE;
|
|
|
|
} else {
|
|
|
|
return pdFALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTimerStart(TimerHandle_t xTimer,
|
|
|
|
TickType_t xBlockTime)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xTimer != NULL);
|
|
|
|
|
|
|
|
ret = tx_timer_activate(&xTimer->timer);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return pdFAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pdPASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTimerStop(TimerHandle_t xTimer,
|
|
|
|
TickType_t xBlockTime)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xTimer != NULL);
|
|
|
|
|
|
|
|
ret = tx_timer_deactivate(&xTimer->timer);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return pdFAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pdPASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTimerChangePeriod(TimerHandle_t xTimer,
|
|
|
|
TickType_t xNewPeriod,
|
|
|
|
TickType_t xBlockTime)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
|
|
|
|
configASSERT(xTimer != NULL);
|
|
|
|
configASSERT(xNewPeriod != 0u);
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
|
|
|
|
ret = tx_timer_deactivate(&xTimer->timer);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_RESTORE;
|
|
|
|
return pdFAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(xTimer->one_shot != 0u) {
|
|
|
|
ret = tx_timer_change(&xTimer->timer, xNewPeriod, xNewPeriod);
|
|
|
|
} else {
|
|
|
|
ret = tx_timer_change(&xTimer->timer, xNewPeriod, 0u);
|
|
|
|
}
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_RESTORE;
|
|
|
|
return pdFAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_timer_activate(&xTimer->timer);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_RESTORE;
|
|
|
|
return pdFAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return pdPASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTimerReset(TimerHandle_t xTimer,
|
|
|
|
TickType_t xBlockTime)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
|
|
|
|
configASSERT(xTimer != NULL);
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
|
|
|
|
ret = tx_timer_deactivate(&xTimer->timer);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_RESTORE;
|
|
|
|
return pdFAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(xTimer->one_shot != 0u) {
|
|
|
|
ret = tx_timer_change(&xTimer->timer, xTimer->period, xTimer->period);
|
|
|
|
} else {
|
|
|
|
ret = tx_timer_change(&xTimer->timer, xTimer->period, 0u);
|
|
|
|
}
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_RESTORE;
|
|
|
|
return pdFAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_timer_activate(&xTimer->timer);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_RESTORE;
|
|
|
|
return pdFAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return pdPASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTimerStartFromISR(TimerHandle_t xTimer,
|
|
|
|
BaseType_t *pxHigherPriorityTaskWoken)
|
|
|
|
{
|
|
|
|
configASSERT(xTimer != NULL);
|
|
|
|
|
|
|
|
return xTimerStart(xTimer, 0u);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTimerStopFromISR(TimerHandle_t xTimer,
|
|
|
|
BaseType_t *pxHigherPriorityTaskWoken)
|
|
|
|
{
|
|
|
|
configASSERT(xTimer != NULL);
|
|
|
|
|
|
|
|
return xTimerStop(xTimer, 0u);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTimerChangePeriodFromISR(TimerHandle_t xTimer,
|
|
|
|
TickType_t xNewPeriod,
|
|
|
|
BaseType_t *pxHigherPriorityTaskWoken)
|
|
|
|
{
|
|
|
|
configASSERT(xTimer != NULL);
|
|
|
|
configASSERT(xNewPeriod != 0u);
|
|
|
|
|
|
|
|
return xTimerChangePeriod(xTimer, xNewPeriod, 0u);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xTimerResetFromISR(TimerHandle_t xTimer,
|
|
|
|
BaseType_t *pxHigherPriorityTaskWoken)
|
|
|
|
{
|
|
|
|
configASSERT(xTimer != NULL);
|
|
|
|
|
|
|
|
return xTimerReset(xTimer, 0u);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void *pvTimerGetTimerID(TimerHandle_t xTimer)
|
|
|
|
{
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
void *p_id;
|
|
|
|
|
|
|
|
configASSERT(xTimer != NULL);
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
p_id = xTimer->id;
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return p_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vTimerSetTimerID(TimerHandle_t xTimer, void *pvNewID)
|
|
|
|
{
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
|
|
|
|
configASSERT(xTimer != NULL);
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
xTimer->id = pvNewID;
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void vTimerSetReloadMode(TimerHandle_t xTimer,
|
|
|
|
const UBaseType_t uxAutoReload)
|
|
|
|
{
|
|
|
|
UINT ret;
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
ULONG left;
|
|
|
|
|
|
|
|
configASSERT(xTimer != NULL);
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
|
|
|
|
ret = tx_timer_deactivate(&xTimer->timer);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_RESTORE;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
left = xTimer->timer.tx_timer_internal.tx_timer_internal_remaining_ticks;
|
|
|
|
|
|
|
|
if(uxAutoReload != pdFALSE) {
|
|
|
|
ret = tx_timer_change(&xTimer->timer, left, xTimer->period);
|
|
|
|
} else {
|
|
|
|
ret = tx_timer_change(&xTimer->timer, left, 0u);
|
|
|
|
}
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_RESTORE;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_timer_activate(&xTimer->timer);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_RESTORE;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char * pcTimerGetName(TimerHandle_t xTimer)
|
|
|
|
{
|
|
|
|
configASSERT(xTimer != NULL);
|
|
|
|
|
|
|
|
return (const char *)xTimer->timer.tx_timer_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TickType_t xTimerGetPeriod(TimerHandle_t xTimer)
|
|
|
|
{
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
TickType_t period;
|
|
|
|
|
|
|
|
configASSERT(xTimer != NULL);
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
|
|
|
|
period = xTimer->period;
|
|
|
|
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return period;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TickType_t xTimerGetExpiryTime(TimerHandle_t xTimer)
|
|
|
|
{
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
ULONG time_tx;
|
|
|
|
TickType_t time;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(xTimer != NULL);
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
|
|
|
|
ret = tx_timer_info_get(&xTimer->timer, NULL, NULL, &time_tx, NULL, NULL);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return 0u;
|
|
|
|
}
|
|
|
|
|
|
|
|
time = (TickType_t)(tx_time_get() + time_tx);
|
|
|
|
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return time;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
UBaseType_t uxTimerGetReloadMode(TimerHandle_t xTimer)
|
|
|
|
{
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
UBaseType_t type;
|
|
|
|
|
|
|
|
configASSERT(xTimer != NULL);
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
|
|
|
|
if(xTimer->one_shot == 0u) {
|
|
|
|
type = pdTRUE;
|
|
|
|
} else {
|
|
|
|
type = pdFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QueueSetHandle_t xQueueCreateSet(const UBaseType_t uxEventQueueLength)
|
|
|
|
{
|
|
|
|
txfr_queueset_t *p_set;
|
|
|
|
void *p_mem;
|
|
|
|
ULONG queue_size;
|
|
|
|
UINT ret;
|
|
|
|
|
|
|
|
configASSERT(uxEventQueueLength != 0u);
|
|
|
|
|
|
|
|
#if (TX_FREERTOS_AUTO_INIT == 1)
|
|
|
|
if(txfr_initialized != 1u) {
|
|
|
|
tx_freertos_auto_init();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-12-28 13:17:40 +08:00
|
|
|
if ((uxEventQueueLength > (SIZE_MAX / sizeof(void *))) ||
|
|
|
|
(uxEventQueueLength > (ULONG_MAX / sizeof(void *)))) {
|
|
|
|
|
|
|
|
/* Integer overflow in queue size */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-10-01 13:46:52 -07:00
|
|
|
p_set = txfr_malloc(sizeof(txfr_queueset_t));
|
|
|
|
if(p_set == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
queue_size = sizeof(void *) * uxEventQueueLength;
|
|
|
|
p_mem = txfr_malloc(queue_size);
|
|
|
|
if(p_mem == NULL) {
|
|
|
|
txfr_free(p_set);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_queue_create(&p_set->queue, "", sizeof(void *) / sizeof(UINT), p_mem, queue_size);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
TX_FREERTOS_ASSERT_FAIL();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return p_set;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xQueueAddToSet(QueueSetMemberHandle_t xQueueOrSemaphore,
|
|
|
|
QueueSetHandle_t xQueueSet)
|
|
|
|
{
|
|
|
|
txfr_sem_t *p_sem;
|
|
|
|
txfr_queue_t *p_queue;
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
|
|
|
|
configASSERT(xQueueOrSemaphore != NULL);
|
|
|
|
configASSERT(xQueueSet != NULL);
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
if(*((ULONG *)(xQueueOrSemaphore)) == TX_SEMAPHORE_ID) {
|
|
|
|
p_sem = (txfr_sem_t *)xQueueOrSemaphore;
|
|
|
|
if(p_sem->p_set != NULL) {
|
|
|
|
TX_RESTORE;
|
|
|
|
return pdFAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
p_sem->p_set = xQueueSet;
|
|
|
|
|
|
|
|
} else if(*((ULONG *)(xQueueOrSemaphore)) == TX_QUEUE_ID) {
|
|
|
|
p_queue = (txfr_queue_t *)xQueueOrSemaphore;
|
|
|
|
if(p_queue->p_set != NULL) {
|
|
|
|
TX_RESTORE;
|
|
|
|
return pdFAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
p_queue->p_set = xQueueSet;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
TX_RESTORE;
|
|
|
|
configASSERT(0u);
|
|
|
|
return pdFAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return pdPASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BaseType_t xQueueRemoveFromSet(QueueSetMemberHandle_t xQueueOrSemaphore,
|
|
|
|
QueueSetHandle_t xQueueSet)
|
|
|
|
{
|
|
|
|
txfr_sem_t *p_sem;
|
|
|
|
txfr_queue_t *p_queue;
|
|
|
|
TX_INTERRUPT_SAVE_AREA;
|
|
|
|
|
|
|
|
configASSERT(xQueueOrSemaphore != NULL);
|
|
|
|
configASSERT(xQueueSet != NULL);
|
|
|
|
|
|
|
|
TX_DISABLE;
|
|
|
|
|
|
|
|
if(*((ULONG *)(xQueueOrSemaphore)) == TX_SEMAPHORE_ID) {
|
|
|
|
p_sem = (txfr_sem_t *)xQueueOrSemaphore;
|
|
|
|
|
|
|
|
if(p_sem->p_set != xQueueSet) {
|
|
|
|
TX_RESTORE;
|
|
|
|
return pdFAIL;
|
|
|
|
} else {
|
|
|
|
p_sem->p_set = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if(*((ULONG *)(xQueueOrSemaphore)) == TX_QUEUE_ID) {
|
|
|
|
p_queue = (txfr_queue_t *)xQueueOrSemaphore;
|
|
|
|
|
|
|
|
if(p_queue->p_set != xQueueSet) {
|
|
|
|
TX_RESTORE;
|
|
|
|
return pdFAIL;
|
|
|
|
} else {
|
|
|
|
p_queue->p_set = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
TX_RESTORE;
|
|
|
|
configASSERT(0u);
|
|
|
|
return pdFAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TX_RESTORE;
|
|
|
|
|
|
|
|
return pdPASS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QueueSetMemberHandle_t xQueueSelectFromSet(QueueSetHandle_t xQueueSet,
|
|
|
|
const TickType_t xTicksToWait)
|
|
|
|
{
|
|
|
|
void *p_ptr;
|
|
|
|
UINT ret;
|
|
|
|
UINT timeout;
|
|
|
|
|
|
|
|
configASSERT(xQueueSet != NULL);
|
|
|
|
|
|
|
|
if(xTicksToWait == portMAX_DELAY) {
|
|
|
|
timeout = TX_WAIT_FOREVER;
|
|
|
|
} else {
|
|
|
|
timeout = (UINT)xTicksToWait;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = tx_queue_receive(&xQueueSet->queue, &p_ptr, timeout);
|
|
|
|
if(ret != TX_SUCCESS) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return p_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QueueSetMemberHandle_t xQueueSelectFromSetFromISR(QueueSetHandle_t xQueueSet)
|
|
|
|
{
|
|
|
|
return xQueueSelectFromSet(xQueueSet, 0u);
|
|
|
|
}
|