Files
test/middleware/usb/uC-USBH/OS/FreeRTOS/usbh_os.c
2025-11-07 20:19:23 +08:00

1189 lines
38 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
*********************************************************************************************************
* uC/USB-Host
* The Embedded USB Host Stack
*
* Copyright (c) 2021 Semidrive Semiconductor
*
* All rights reserved.
*
*********************************************************************************************************
*/
/*
*********************************************************************************************************
*
* USB HOST OPERATING SYSTEM LAYER
* For CMSIS OS2
*
* Filename : usbh_os.c
* Version : V1.00.00
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
#include <stdlib.h>
#include <FreeRTOS.h>
#include <udelay/udelay.h>
#include "task.h"
#include "event_groups.h"
#include "semphr.h"
#include <usbh_cfg.h>
#include "../../Source/usbh_os.h"
#include <board.h>
/*
*********************************************************************************************************
* LOCAL DEFINES
*********************************************************************************************************
*/
#define USBH_OS_MUTEX_REQUIRED ((((USBH_CFG_MAX_NBR_EPS * USBH_CFG_MAX_NBR_IFS) + 1u) * USBH_CFG_MAX_NBR_DEVS) + \
USBH_CFG_MAX_NBR_DEVS + USBH_CFG_MAX_NBR_HC + \
USBH_CDC_CFG_MAX_DEV + USBH_HID_CFG_MAX_DEV + USBH_MSC_CFG_MAX_DEV)
#define USBH_OS_SEM_REQUIRED (3u + (((USBH_CFG_MAX_NBR_EPS * USBH_CFG_MAX_NBR_IFS) + 1u) * USBH_CFG_MAX_NBR_DEVS))
#define USBH_OS_TCB_REQUIRED 4u
#define USBH_OS_Q_REQUIRED 1u
#define USBH_SEM_EVENT_POST (1u<<0)
#define USBH_SEM_EVENT_ABORT (1u<<1)
#define USBH_SEM_EVENT_DEL (1u<<2)
#define USBH_SEM_EVENT_ALL (USBH_SEM_EVENT_POST | USBH_SEM_EVENT_ABORT | USBH_SEM_EVENT_DEL)
/*
*********************************************************************************************************
* LOCAL CONSTANTS
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL DATA TYPES
*********************************************************************************************************
*/
typedef struct usbh_semaphore {
EventGroupHandle_t evt;
volatile CPU_INT32U cnt;
} USBH_SIGNAL;
/*
*********************************************************************************************************
* LOCAL TABLES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/
#define usbh_os_err(...) ssdk_printf(SSDK_CRIT, __VA_ARGS__)
#define IS_IRQ_MASKED arch_irq_is_masked
#define IS_IRQ_MODE arch_in_irq_mode
/*
*********************************************************************************************************
* IRQ_Context()
*
* Description : Determine if CPU executes from interrupt context or if interrupts are masked.
*
* Argument(s) : None.
*
* Return(s) : 0, thread context.
* 1, IRQ context.
*
* Note(s) : None.
*********************************************************************************************************
*/
__STATIC_INLINE uint32_t IRQ_Context (void)
{
uint32_t irq;
BaseType_t state;
irq = 0U;
if (IS_IRQ_MODE()) {
/* Called from interrupt context */
irq = 1U;
} else {
/* Get FreeRTOS scheduler state */
state = xTaskGetSchedulerState();
if (state != taskSCHEDULER_NOT_STARTED) {
/* Scheduler was started */
if (IS_IRQ_MASKED()) {
/* Interrupts are masked */
irq = 1U;
}
}
}
/* Return context, 0: thread context, 1: IRQ context */
return (irq);
}
/*
*********************************************************************************************************
* sdQueueCreate()
*
* Description : Creates a new queue and returns a handle by which the queue can be referenced.
*
* Argument(s) : queue_count, The maximum number of items that the queue being created can hold at
* any one time.
* queue_size, The size, in bytes, of each data item that can be stored in the queue.
*
* Return(s) : NULL, The queue cannot be created because there is insufficient heap memory
* available for FreeRTOS to allocate the queue data structures and storage
* area.
* Any other value, The queue was created successfully. The returned value is a handle by
* which the created queue can be referenced.
*
* Note(s) : None.
*********************************************************************************************************
*/
static QueueHandle_t sdQueueCreate(UBaseType_t queue_count, UBaseType_t queue_size)
{
QueueHandle_t msg_q = xQueueCreate(queue_count, queue_size);
/* Return msg */
return (msg_q);
}
/*
*********************************************************************************************************
* sdQueueReceive()
*
* Description : Receive (read) an item from a queue.
*
* Argument(s) : hQueue, The handle of the queue from which the data is being received (read).
* msg_ptr, A pointer to the memory into which the received data will be copied.
* timeout, The maximum amount of time the task should remain in the Blocked state to
* wait for data to become available on the queue, should the queue already be
* empty.
*
* Return(s) : pdPASS, Returned if data was successfully read from the queue.
* errQUEUE_EMPTY, Returned if data cannot be read from the queue because the queue is
* already empty.
*
* Note(s) : None.
*********************************************************************************************************
*/
static BaseType_t sdQueueReceive(QueueHandle_t hQueue, void *msg_ptr, uint32_t timeout)
{
BaseType_t ret = pdTRUE;
BaseType_t yield;
if (IRQ_Context() != 0U) {
yield = pdFALSE;
if (xQueueReceiveFromISR(hQueue, msg_ptr, &yield) != pdPASS) {
ret = pdFALSE;
} else {
portYIELD_FROM_ISR(yield);
}
} else {
if (xQueueReceive(hQueue, msg_ptr, (TickType_t)timeout) != pdPASS) {
ret = pdFALSE;
}
}
/* Return execution status */
return (ret);
}
/*
*********************************************************************************************************
* sdQueueSend()
*
* Description : Sends (writes) an item to the front or the back of a queue.
*
* Argument(s) : hQueue, The handle of the queue to which the data is being sent (written).
* msg_ptr, A pointer to the data to be copied into the queue.
* timeout, The maximum amount of time the task should remain in the Blocked state to
* wait for space to become available on the queue, should the queue already
* be full.
*
* Return(s) : pdPASS, Returned if data was successfully sent to the queue.
* errQUEUE_FULL, Returned if data could not be written to the queue because the queue was
* already full.
*
* Note(s) : None.
*********************************************************************************************************
*/
static BaseType_t sdQueueSend(QueueHandle_t hQueue, const void *msg_ptr, uint32_t timeout)
{
BaseType_t ret = pdTRUE;
BaseType_t yield;
if (IRQ_Context() != 0U) {
yield = pdFALSE;
if (xQueueSendToBackFromISR(hQueue, msg_ptr, &yield) != pdTRUE) {
ret = pdFALSE;
} else {
portYIELD_FROM_ISR(yield);
}
} else {
ret = xQueueSendToBack(hQueue, msg_ptr, (TickType_t)timeout);
}
/* Return execution status */
return (ret);
}
/*
*********************************************************************************************************
* sdSemaphoreTake()
*
* Description : Takes (or obtains) a semaphore.
*
* Argument(s) : hSemaphore, The Semaphore being taken.
* timeout, The maximum amount of time the task should remain in the Blocked state to
* wait for the semaphore to become available, if the semaphore is not
* available immediately.
*
* Return(s) : pdPASS, Returned only if the call to sdSemaphoreTake() was successful in obtaining
* the semaphore.
* pdFAIL, Returned if the call to sdSemaphoreTake() did not successfully obtain the
* semaphore.
*
* Note(s) : None.
*********************************************************************************************************
*/
static BaseType_t sdSemaphoreTake(SemaphoreHandle_t hSemaphore, uint32_t timeout)
{
BaseType_t ret = pdTRUE;
BaseType_t yield;
if(IRQ_Context() != 0U) {
yield = pdFALSE;
if (xSemaphoreTakeFromISR(hSemaphore, &yield) != pdPASS) {
ret = pdFALSE;
} else {
portYIELD_FROM_ISR (yield);
}
} else {
ret = xSemaphoreTake(hSemaphore, (TickType_t)timeout);
}
/* Return execution status */
return (ret);
}
/*
*********************************************************************************************************
* sdSemaphoreGive()
*
* Description : Gives (or releases) a semaphore.
*
* Argument(s) : hSemaphore, The Semaphore being given.
*
* Return(s) : pdPASS, The semaphore give operation was successful.
* pdFAIL, The semaphore give operation was not successful.
*
* Note(s) : None.
*********************************************************************************************************
*/
static BaseType_t sdSemaphoreGive(SemaphoreHandle_t hSemaphore)
{
BaseType_t ret = pdFALSE;
if (IRQ_Context() == 0U) {
ret = xSemaphoreGive(hSemaphore);
}
/* Return ret */
return (ret);
}
/*
*********************************************************************************************************
* sdSemaphoreCreateMutex()
*
* Description : Creates a mutex type semaphore, and returns a handle by which the mutex can be
* referenced.
*
* Argument(s) : None.
*
* Return(s) : NULL, Returned if the semaphore cannot be created because there is insufficient
* heap memory available for FreeRTOS to allocate the semaphore data
* structures.
* Any other value, The semaphore was created successfully. The returned value is a handle
* by which the created semaphore can be referenced.
*
* Note(s) : None.
*********************************************************************************************************
*/
static SemaphoreHandle_t sdSemaphoreCreateMutex(void)
{
SemaphoreHandle_t hMutex = 0;
if (IRQ_Context() == 0U) {
hMutex = xSemaphoreCreateMutex();
}
/* Return mutex ID */
return (hMutex);
}
/*
*********************************************************************************************************
* sdSemaphoreDelete()
*
* Description : Deletes a semaphore.
*
* Argument(s) : hSemaphore, The handle of the semaphore being deleted.
*
* Return(s) : None.
*
* Note(s) : None.
*********************************************************************************************************
*/
static BaseType_t sdSemaphoreDelete(SemaphoreHandle_t hSemaphore)
{
BaseType_t ret = pdFALSE;
if (IRQ_Context() == 0U) {
vSemaphoreDelete(hSemaphore);
ret = pdTRUE;
}
/* Return ret */
return (ret);
}
/*
*********************************************************************************************************
* sdEventGroupCreate()
*
* Description : Creates a new event group and returns a handle by which the created event group can be
* referenced.
*
* Argument(s) : None.
*
* Return(s) : NULL, The event group could not be created because there was insufficient
* FreeRTOS heap available.
* Any other value, The event group was created and the value returned is the handle of the
* created event group
*
* Note(s) : None.
*********************************************************************************************************
*/
static EventGroupHandle_t sdEventGroupCreate(void)
{
EventGroupHandle_t evt = NULL;
if (IRQ_Context() == 0U) {
evt = xEventGroupCreate();
}
/* Return evt */
return (evt);
}
/*
*********************************************************************************************************
* sdEventGroupDelete()
*
* Description : Deletes a group.
*
* Argument(s) : hEventGroup, The event group to delete.
*
* Return(s) : None.
*
* Note(s) : None.
*********************************************************************************************************
*/
static BaseType_t sdEventGroupDelete(EventGroupHandle_t hEventGroup)
{
BaseType_t ret = pdFALSE;
if (IRQ_Context() == 0U) {
vEventGroupDelete(hEventGroup);
ret = pdTRUE;
}
/* Return ret */
return (ret);
}
/*
*********************************************************************************************************
* sdEventGroupSetBits()
*
* Description : Sets bits (flags) within an RTOS event group.
*
* Argument(s) : hEventGroup, The event group in which the bits are to be set.
* flags, A bitwise value that indicates the bit or bits to set in the event group.
*
* Return(s) : Any Value, The value of the bits in the event group at the time to returned.
*
* Note(s) : None.
*********************************************************************************************************
*/
static EventBits_t sdEventGroupSetBits(EventGroupHandle_t hEventGroup, uint32_t flags)
{
EventBits_t rflags;
BaseType_t yield;
if (IRQ_Context() != 0U) {
yield = pdFALSE;
if (xEventGroupSetBitsFromISR(hEventGroup, (EventBits_t)flags, &yield) == pdFAIL) {
rflags = pdFAIL;
} else {
rflags = flags;
portYIELD_FROM_ISR (yield);
}
}
else {
rflags = xEventGroupSetBits(hEventGroup, (EventBits_t)flags);
}
/* Return event flags after setting */
return (rflags);
}
/*
*********************************************************************************************************
* sdEventGroupWaitBits()
*
* Description : Read bits within an RTOS event group.
*
* Argument(s) : hEventGroup, The event group in which the bits are being tested.
* timeout, The maximum amount of time (specified in 'ticks') to wait.
*
* Return(s) : Any Value, The value of the event group at the time either the event bits being waited
* for became set, or the block time expired.
*
* Note(s) : None.
*********************************************************************************************************
*/
static EventBits_t sdEventGroupWaitBits(EventGroupHandle_t hEventGroup, uint32_t timeout)
{
EventBits_t rflags = 0;
if (IRQ_Context() == 0U) {
rflags = xEventGroupWaitBits(hEventGroup, USBH_SEM_EVENT_ALL, pdTRUE, pdFALSE, timeout);
}
/* Return event flags after setting */
return (rflags);
}
/*
*********************************************************************************************************
* USBH_OS_LayerInit()
*
* Description : Initialize OS layer.
*
* Argument(s) : none.
*
* Return(s) : USBH_ERR_NONE, if successful.
*
* Note(s) : none.
*********************************************************************************************************
*/
USBH_ERR USBH_OS_LayerInit (void)
{
return (USBH_ERR_NONE);
}
/*
**************************************************************************************************************
* USBH_OS_VirToBus()
*
* Description : Convert from virtual address to physical address if the operating system uses
* virtual memory
*
* Arguments : x Virtual address to convert
*
* Returns : The corresponding physical address
*
* Note(s) : None.
**************************************************************************************************************
*/
void *USBH_OS_VirToBus (void *x)
{
return (x);
}
/*
**************************************************************************************************************
* USBH_OS_BusToVir()
*
* Description : Convert from physical address to virtual address if the operating system uses
* virtual memory
*
* Arguments : x Physical address to convert
*
* Returns : The corresponding virtual address
*
* Note(s) : None.
**************************************************************************************************************
*/
void *USBH_OS_BusToVir (void *x)
{
return (x);
}
/*
*********************************************************************************************************
*********************************************************************************************************
* DELAY FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* USBH_OS_DlyMS()
*
* Description : Delay the current task by specified delay.
*
* Argument(s) : dly Delay, in milliseconds.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
void USBH_OS_DlyMS (CPU_INT32U dly)
{
if (dly < 3)
udelay(dly * 1000);
else
vTaskDelay(dly);
}
/*
*********************************************************************************************************
* USBH_OS_DlyUS()
*
* Description : Delay the current task by specified delay.
*
* Argument(s) : dly Delay, in microseconds.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
void USBH_OS_DlyUS (CPU_INT32U dly)
{
udelay(dly);
}
/*
*********************************************************************************************************
*********************************************************************************************************
* MUTEX FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* USBH_OS_MutexCreate()
*
* Description : Create a mutex.
*
* Argument(s) : p_mutex Pointer to variable that will receive handle of the mutex.
*
* Return(s) : USBH_ERR_NONE, if successful.
* USBH_ERR_ALLOC,
* USBH_ERR_OS_SIGNAL_CREATE,
*
* Note(s) : none.
*********************************************************************************************************
*/
USBH_ERR USBH_OS_MutexCreate (USBH_HMUTEX *p_mutex)
{
SemaphoreHandle_t ret;
ret = sdSemaphoreCreateMutex();
if (!ret) {
usbh_os_err("Creat Mutex failed\r\n");
return USBH_ERR_OS_SIGNAL_CREATE;
} else {
*p_mutex = (USBH_HMUTEX)ret;
return USBH_ERR_NONE;
}
}
/*
*********************************************************************************************************
* USBH_OS_MutexLock()
*
* Description : Acquire a mutex.
*
* Argument(s) : mutex Mutex handle.
*
* Return(s) : USBH_ERR_NONE, if successful.
* USBH_ERR_OS_TIMEOUT, if timeout.
* USBH_ERR_OS_FAIL, otherwise.
*
* Note(s) : none.
*********************************************************************************************************
*/
USBH_ERR USBH_OS_MutexLock (USBH_HMUTEX mutex)
{
BaseType_t ret;
ret = sdSemaphoreTake((SemaphoreHandle_t)mutex, portMAX_DELAY);
switch (ret) {
case pdPASS:
return USBH_ERR_NONE;
break;
case pdFAIL:
default:
usbh_os_err("Get Mutex %X ret %d\r\n", mutex, ret);
return USBH_ERR_OS_FAIL;
break;
}
}
/*
*********************************************************************************************************
* USBH_OS_MutexUnlock()
*
* Description : Releases a mutex.
*
* Argument(s) : mutex Mutex handle.
*
* Return(s) : USBH_ERR_NONE, if successful.
* USBH_ERR_OS_FAIL, otherwise.
*
* Note(s) : none.
*********************************************************************************************************
*/
USBH_ERR USBH_OS_MutexUnlock (USBH_HMUTEX mutex)
{
if (sdSemaphoreGive((SemaphoreHandle_t)mutex) != pdPASS) {
usbh_os_err("Mutex %X Release ret %d\r\n", mutex);
return USBH_ERR_OS_FAIL;
}
return USBH_ERR_NONE;
}
/*
*********************************************************************************************************
* USBH_OS_MutexDestroy()
*
* Description : Destroys a mutex only when no task is pending on the mutex.
*
* Argument(s) : mutex Mutex handle.
*
* Return(s) : USBH_ERR_NONE, if successful.
* USBH_ERR_OS_FAIL, if mutex delete failed.
* USBH_ERR_FREE, if mutex free failed.
*
* Note(s) : none.
*********************************************************************************************************
*/
USBH_ERR USBH_OS_MutexDestroy (USBH_HMUTEX mutex)
{
sdSemaphoreDelete((SemaphoreHandle_t)mutex);
return USBH_ERR_NONE;
}
/*
*********************************************************************************************************
*********************************************************************************************************
* SEMAPHORE FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* USBH_OS_SemCreate()
*
* Description : Create semaphore with given count.
*
* Argument(s) : p_sem Pointer that will receive handle for managing semaphore.
* cnt Value with which the semaphore will be initialized.
*
* Return(s) : USBH_ERR_NONE, if successful.
* USBH_ERR_OS_SIGNAL_CREATE,
* USBH_ERR_ALLOC,
*
* Note(s) : none.
*********************************************************************************************************
*/
USBH_ERR USBH_OS_SemCreate (USBH_HSEM *p_sem,
CPU_INT32U cnt)
{
EventGroupHandle_t evt;
USBH_SIGNAL *hsig;
hsig = pvPortMallocAligned(sizeof(*hsig), sizeof(void *));
if (!hsig)
return USBH_ERR_ALLOC;
evt = sdEventGroupCreate();
if (!evt) {
usbh_os_err("Creat Semaphore failed\r\n");
free(hsig);
return USBH_ERR_OS_SIGNAL_CREATE;
}
hsig->evt = evt;
hsig->cnt = cnt;
if (cnt > 0) {
sdEventGroupSetBits(hsig->evt, USBH_SEM_EVENT_POST);
}
*p_sem = (USBH_HSEM)hsig;
return USBH_ERR_NONE;
}
/*
*********************************************************************************************************
* USBH_OS_SemDestroy()
*
* Description : Destroy a semphore if no tasks are waiting on it.
*
* Argument(s) : sem Semaphore handle.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
USBH_ERR USBH_OS_SemDestroy (USBH_HSEM sem)
{
USBH_SIGNAL *hsig;
hsig = (USBH_SIGNAL *)sem;
if (!hsig || !hsig->evt)
return USBH_ERR_INVALID_ARG;
sdEventGroupSetBits(hsig->evt, USBH_SEM_EVENT_DEL);
sdEventGroupDelete(hsig->evt);
free(hsig);
return USBH_ERR_NONE;
}
/*
*********************************************************************************************************
* USBH_OS_SemWait()
*
* Description : Wait on a semaphore to become available.
*
* Argument(s) : sem Semaphore handle.
*
* timeout Timeout.
*
* Return(s) : USBH_ERR_NONE, if successful.
* USBH_ERR_OS_TIMEOUT, if timeout error.
* USBH_ERR_OS_ABORT,
* USBH_ERR_OS_FAIL,
*
* Note(s) : none.
*********************************************************************************************************
*/
USBH_ERR USBH_OS_SemWait (USBH_HSEM sem,
CPU_INT32U timeout)
{
USBH_SIGNAL *hsig;
uint32_t rflags;
uint32_t tmo;
uint32_t tk_start, tk_current;
CPU_INT32U cnt;
CPU_SR_ALLOC();
hsig = (USBH_SIGNAL *)sem;
if (!hsig || !hsig->evt)
return USBH_ERR_INVALID_ARG;
tk_start = xTaskGetTickCount();
tk_current = tk_start;
do {
tmo = timeout ? (tk_start + timeout - tk_current): portMAX_DELAY;
rflags = sdEventGroupWaitBits(hsig->evt, tmo);
if ((rflags & USBH_SEM_EVENT_ALL) == 0U) {
if (tmo > 0U) {
return USBH_ERR_OS_TIMEOUT;
} else {
usbh_os_err("Get Signal %p rflags %d\r\n", hsig->evt, rflags);
return USBH_ERR_OS_FAIL;
}
} else if (rflags & USBH_SEM_EVENT_DEL) {
usbh_os_err("Get Multi Signal %p ret Del\r\n", hsig->evt);
return USBH_ERR_OS_FAIL;
} else if (rflags & USBH_SEM_EVENT_ABORT) {
return USBH_ERR_OS_ABORT;
}
CPU_CRITICAL_ENTER();
cnt = hsig->cnt;
if (cnt)
hsig->cnt = cnt - 1;
CPU_CRITICAL_EXIT();
if (cnt > 1) {
sdEventGroupSetBits(hsig->evt, USBH_SEM_EVENT_POST);
}
if (cnt) {
return USBH_ERR_NONE;
}
tk_current = xTaskGetTickCount();
} while (!timeout || (tk_current - tk_start <= timeout));
return USBH_ERR_OS_TIMEOUT;
}
/*
*********************************************************************************************************
* USBH_OS_SemWaitAbort()
*
* Description : Resume all tasks waiting on specified semaphore.
*
* Argument(s) : sem Semaphore handle.
*
* Return(s) : USBH_ERR_NONE, if successful.
* USBH_ERR_OS_TIMEOUT, if timeout error.
* USBH_ERR_OS_ABORT,
* USBH_ERR_OS_FAIL,
*
* Note(s) : none.
*********************************************************************************************************
*/
USBH_ERR USBH_OS_SemWaitAbort (USBH_HSEM sem)
{
int32_t ret;
USBH_SIGNAL *hsig;
hsig = (USBH_SIGNAL *)sem;
if (!hsig || !hsig->evt)
return USBH_ERR_INVALID_ARG;
ret = sdEventGroupSetBits(hsig->evt, USBH_SEM_EVENT_ABORT);
if (ret < 0) {
return USBH_ERR_OS_FAIL;
}
return USBH_ERR_NONE;
}
/*
*********************************************************************************************************
* USBH_OS_SemPost()
*
* Description : Post a semaphore.
*
* Argument(s) : sem Semaphore handle.
*
* Return(s) : USBH_ERR_NONE, if successful.
* USBH_ERR_OS_FAIL, otherwise.
*
* Note(s) : none.
*********************************************************************************************************
*/
USBH_ERR USBH_OS_SemPost (USBH_HSEM sem)
{
int32_t ret;
USBH_SIGNAL *hsig;
CPU_SR_ALLOC();
hsig = (USBH_SIGNAL *)sem;
if (!hsig || !hsig->evt)
return USBH_ERR_INVALID_ARG;
CPU_CRITICAL_ENTER();
hsig->cnt++;
CPU_CRITICAL_EXIT();
ret = sdEventGroupSetBits(hsig->evt, USBH_SEM_EVENT_POST);
if (ret < 0) {
return USBH_ERR_OS_FAIL;
}
return USBH_ERR_NONE;
}
/*
*********************************************************************************************************
*********************************************************************************************************
* THREAD FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* USBH_OS_ThreadCreate()
*
* Description : Create a thread (or task).
*
* Argument(s) : p_name Pointer to name to assign to thread.
*
* prio Priority of the thread to be created.
*
* thread_fnct Pointer to the function that will be executed in this thread.
*
* p_data Pointer to the data that is passed to the thread function.
*
* p_stk Pointer to the beginning of the stack used by the thread.
*
* stk_size Size of the stack.
*
* p_thread Pointer that will receive handle for managing thread.
*
* Return(s) : USBH_ERR_NONE, if successful.
* USBH_ERR_ALLOC,
* USBH_ERR_OS_TASK_CREATE,
*
* Note(s) : none.
*********************************************************************************************************
*/
USBH_ERR USBH_OS_TaskCreate (CPU_CHAR *p_name,
CPU_INT32U prio,
USBH_TASK_FNCT task_fnct,
void *p_data,
CPU_INT32U *p_stk,
CPU_INT32U stk_size,
USBH_HTASK *p_task)
{
TaskHandle_t thread;
if (p_stk != NULL) {
thread = xTaskCreateStatic(task_fnct, p_name, stk_size, p_data, prio,
(StackType_t *)p_stk, (StaticTask_t *)p_task);
if (!thread) {
p_task = NULL;
return USBH_ERR_OS_TASK_CREATE;
}
} else {
if (xTaskCreate(task_fnct, p_name, stk_size, p_data, prio, &thread) != pdPASS) {
return USBH_ERR_OS_TASK_CREATE;
}
}
*p_task = (USBH_HTASK)thread;
return USBH_ERR_NONE;
}
/*
*********************************************************************************************************
*********************************************************************************************************
* MESSAGE QUEUE
*********************************************************************************************************
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* USBH_OS_MsgQueueCreate()
*
* Description : Create a message queue.
*
* Argument(s) : p_start Pointer to the base address of the message queue storage area.
*
* size Number of elements in the storage area.
*
* p_err Pointer to variable that will receive the return error code from this function:
*
* USBH_ERR_NONE Message queue created.
* USBH_ERR_ALLOC Message queue creation failed.
* USBH_ERR_OS_SIGNAL_CREATE
*
* Return(s) : The handle of the message queue.
*
* Note(s) : none.
*********************************************************************************************************
*/
USBH_HQUEUE USBH_OS_MsgQueueCreate (void **p_start,
CPU_INT16U size,
USBH_ERR *p_err)
{
QueueHandle_t msg_q;
if (p_err == NULL) {
return (USBH_ERR_INVALID_ARG);
}
msg_q = sdQueueCreate(size, sizeof(void *));
if (!msg_q) {
usbh_os_err("Creat Queue failed\r\n");
*p_err = USBH_ERR_OS_SIGNAL_CREATE;
return ((USBH_HQUEUE )0);
}
*p_err = USBH_ERR_NONE;
return ((USBH_HQUEUE)msg_q);
}
/*
*********************************************************************************************************
* USBH_OS_MsgQueuePut()
*
* Description : Post a message to a message queue.
*
* Argument(s) : msg_q Message queue handle.
*
* p_msg Pointer to the message to send.
*
* Return(s) : USBH_ERR_NONE, if successful.
* USBH_ERR_OS_FAIL, otherwise.
*
* Note(s) : none.
*********************************************************************************************************
*/
USBH_ERR USBH_OS_MsgQueuePut (USBH_HQUEUE msg_q,
void *p_msg)
{
void *p;
if (p_msg == NULL) {
return (USBH_ERR_INVALID_ARG);
}
p = p_msg;
if (sdQueueSend((QueueHandle_t)msg_q, &p, 0) != pdPASS) {
usbh_os_err("MsgQ Put failed\r\n");
return USBH_ERR_OS_FAIL;
}
return (USBH_ERR_NONE);
}
/*
*********************************************************************************************************
* USBH_OS_MsgQueueGet()
*
* Description : Get a message from a message queue and blocks forever until a message is posted in the
* queue.
*
* Argument(s) : msg_q Message queue handle.
*
* timeout Time to wait for a message, in milliseconds.
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBH_ERR_NONE, if successful.
* USBH_ERR_OS_TIMEOUT,
* USBH_ERR_OS_ABORT,
* USBH_ERR_OS_FAIL,
*
* Return(s) : Pointer to message, if successful.
* Pointer to null, otherwise.
*
* Note(s) : none.
*********************************************************************************************************
*/
void *USBH_OS_MsgQueueGet (USBH_HQUEUE msg_q,
CPU_INT32U timeout,
USBH_ERR *p_err)
{
void *p_msg;
BaseType_t ret;
uint32_t tmo;
if (p_err == NULL) {
return NULL;
}
tmo = timeout ? timeout : portMAX_DELAY;
ret = sdQueueReceive((QueueHandle_t)msg_q, &p_msg, tmo);
switch (ret) {
case pdPASS:
*p_err = USBH_ERR_NONE;
break;
case pdFAIL:
default:
if (tmo) {
usbh_os_err("USBH_OS_MsgQueueGet timeout 1\r\n");
*p_err = USBH_ERR_OS_TIMEOUT;
} else {
*p_err = USBH_ERR_OS_FAIL;
}
usbh_os_err("MsgQ Get failed\r\n");
break;
}
return (*p_err == USBH_ERR_NONE ? p_msg : NULL);
}