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

1086 lines
36 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-Device
* The Embedded USB Device Stack
*
* Copyright (c) 2021 Semidrive Semiconductor
*
* All rights reserved.
*
*********************************************************************************************************
*/
/*
*********************************************************************************************************
*
* USB DEVICE OPERATING SYSTEM LAYER
* For CMSIS OS2
*
* Filename : usbd_os.c
* Version : V1.00.00
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
#include <stdio.h>
#include <FreeRTOS.h>
#include <udelay/udelay.h>
#include "task.h"
#include "event_groups.h"
#include "semphr.h"
#include "../../Source/usbd_core.h"
#include "../../Source/usbd_internal.h"
#include <irq.h>
#include <board.h>
/*
*********************************************************************************************************
* CONFIGURATION ERRORS
*********************************************************************************************************
*/
#if (USBD_CFG_DBG_TRACE_EN == DEF_ENABLED)
#error "USBD_CFG_DBG_TRACE is not supported yet."
#endif
/*
*********************************************************************************************************
* LOCAL DEFINES
*********************************************************************************************************
*/
#define EP_SIG_EVENT_POST (1u<<0)
#define EP_SIG_EVENT_ABORT (1u<<1)
#define EP_SIG_EVENT_DEL (1u<<2)
#define EP_SIG_EVENT_ALL (EP_SIG_EVENT_POST | EP_SIG_EVENT_ABORT | EP_SIG_EVENT_DEL)
/*
*********************************************************************************************************
* LOCAL CONSTANTS
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL DATA TYPES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL TABLES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/
static TaskHandle_t USBD_OS_CoreTaskID;
static QueueHandle_t USBD_OS_CoreMsgID;
static EventGroupHandle_t USBD_OS_EP_SemTbl[USBD_CFG_MAX_NBR_DEV][USBD_CFG_MAX_NBR_EP_OPEN];
static volatile CPU_INT32U USBD_OS_EP_SemCntTbl[USBD_CFG_MAX_NBR_DEV][USBD_CFG_MAX_NBR_EP_OPEN];
static SemaphoreHandle_t USBD_OS_EP_MutexTbl[USBD_CFG_MAX_NBR_DEV][USBD_CFG_MAX_NBR_EP_OPEN];
/*
*********************************************************************************************************
* LOCAL MACRO'S
*********************************************************************************************************
*/
#define usbd_os_err(...) ssdk_printf(SSDK_CRIT, __VA_ARGS__)
#define IS_IRQ_MASKED arch_irq_is_masked
#define IS_IRQ_MODE arch_in_irq_mode
/*
*********************************************************************************************************
* LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/
static void USBD_OS_CoreTask (void *p_arg);
/*
*********************************************************************************************************
* 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);
}
/*
*********************************************************************************************************
* sdQueueDelet()
*
* Description : Deletes a queue.
*
* Argument(s) : hQueue, The handle of the queue being deleted. Semaphore handles can also be
* used.
*
* Return(s) : None.
*
* Note(s) : None.
*********************************************************************************************************
*/
static BaseType_t sdQueueDelet(QueueHandle_t hQueue)
{
vQueueDelete(hQueue);
/* Return msg */
return (pdTRUE);
}
/*
*********************************************************************************************************
* 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, EP_SIG_EVENT_ALL, pdTRUE, pdFALSE, timeout);
}
/* Return event flags after setting */
return (rflags);
}
/*
*********************************************************************************************************
* USBD_OS_Init()
*
* Description : Initialize OS interface.
*
* Argument(s) : p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE OS initialization successful.
* USBD_ERR_OS_INIT_FAIL OS objects NOT successfully initialized.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
void USBD_OS_Init (USBD_ERR *p_err)
{
QueueHandle_t msg_q;
TaskHandle_t thread;
msg_q = sdQueueCreate(USBD_CORE_EVENT_NBR_TOTAL, sizeof(void *));
if (!msg_q) {
*p_err = USBD_ERR_OS_INIT_FAIL;
return;
}
USBD_OS_CoreMsgID = msg_q;
if (xTaskCreate(USBD_OS_CoreTask, "USBD_Core", 1024u, NULL, (configMAX_PRIORITIES - 3), &thread) != pdPASS) {
*p_err = USBD_ERR_OS_INIT_FAIL;
sdQueueDelet(msg_q);
return;
}
*p_err = USBD_ERR_NONE;
(void)USBD_OS_CoreTaskID;
USBD_OS_CoreTaskID = thread;
return;
}
/*
*********************************************************************************************************
* USBD_OS_CoreTask()
*
* Description : OS-dependent shell task to process USB core events.
*
* Argument(s) : p_arg Pointer to task initialization argument.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
static void USBD_OS_CoreTask (void *p_arg)
{
(void)p_arg;
while (DEF_ON) {
USBD_CoreTaskHandler();
}
}
/*
*********************************************************************************************************
* USBD_OS_SignalCreate()
*
* Description : Create an OS signal.
*
* Argument(s) : dev_nbr Device number.
* ------- Argument validated by the caller(s).
*
* ep_ix Endpoint index.
* ----- Argument validated by the caller(s).
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE OS signal successfully created.
* USBD_ERR_OS_SIGNAL_CREATE OS signal NOT successfully created.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
void USBD_OS_EP_SignalCreate (CPU_INT08U dev_nbr,
CPU_INT08U ep_ix,
USBD_ERR *p_err)
{
EventGroupHandle_t hEventGroup;
hEventGroup = sdEventGroupCreate();
if (!hEventGroup) {
*p_err = USBD_ERR_OS_SIGNAL_CREATE;
} else {
*p_err = USBD_ERR_NONE;
USBD_OS_EP_SemTbl[dev_nbr][ep_ix] = hEventGroup;
USBD_OS_EP_SemCntTbl[dev_nbr][ep_ix] = 0;
}
}
/*
*********************************************************************************************************
* USBD_OS_SignalDel()
*
* Description : Delete an OS signal.
*
* Argument(s) : dev_nbr Device number.
* ------- Argument validated by the caller(s).
*
* ep_ix Endpoint index.
* ----- Argument validated by the caller(s).
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
void USBD_OS_EP_SignalDel (CPU_INT08U dev_nbr,
CPU_INT08U ep_ix)
{
sdEventGroupSetBits(USBD_OS_EP_SemTbl[dev_nbr][ep_ix], EP_SIG_EVENT_DEL);
sdEventGroupDelete(USBD_OS_EP_SemTbl[dev_nbr][ep_ix]);
USBD_OS_EP_SemTbl[dev_nbr][ep_ix] = NULL;
}
/*
*********************************************************************************************************
* USBD_OS_SignalPend()
*
* Description : Wait for a signal to become available.
*
* Argument(s) : dev_nbr Device number.
* ------- Argument validated by the caller(s).
*
* ep_ix Endpoint index.
* ----- Argument validated by the caller(s).
*
* timeout_ms Signal wait timeout in milliseconds.
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE OS signal successfully acquired.
* USBD_ERR_OS_TIMEOUT OS signal NOT successfully acquired in the time
* specified by 'timeout_ms'.
* USBD_ERR_OS_ABORT OS signal aborted.
* USBD_ERR_OS_FAIL OS signal not acquired because another error.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
void USBD_OS_EP_SignalPend (CPU_INT08U dev_nbr,
CPU_INT08U ep_ix,
CPU_INT16U timeout_ms,
USBD_ERR *p_err)
{
uint32_t rflags;
uint32_t tmo;
uint32_t tk_start, tk_current;
CPU_INT32U cnt;
CPU_SR_ALLOC();
tk_start = xTaskGetTickCount();
tk_current = tk_start;
do {
tmo = timeout_ms ? (tk_start + timeout_ms - tk_current): portMAX_DELAY;
rflags = sdEventGroupWaitBits(USBD_OS_EP_SemTbl[dev_nbr][ep_ix], tmo);
if ((rflags & EP_SIG_EVENT_ALL) == 0U) {
if (tmo > 0U) {
*p_err = USBD_ERR_OS_TIMEOUT;
return;
} else {
*p_err = USBD_ERR_OS_FAIL;
usbd_os_err("Get Signal %d-%d rflags %d\r\n", dev_nbr, ep_ix, rflags);
return;
}
} else if (rflags & EP_SIG_EVENT_DEL) {
*p_err = USBD_ERR_OS_FAIL;
usbd_os_err("Get Multi Signal %d-%d rflags Del\r\n", dev_nbr, ep_ix);
return;
} else if (rflags & EP_SIG_EVENT_ABORT) {
*p_err = USBD_ERR_OS_ABORT;
return;
}
CPU_CRITICAL_ENTER();
cnt = USBD_OS_EP_SemCntTbl[dev_nbr][ep_ix];
if (cnt)
USBD_OS_EP_SemCntTbl[dev_nbr][ep_ix] = cnt - 1;
CPU_CRITICAL_EXIT();
if (cnt > 1) {
sdEventGroupSetBits(USBD_OS_EP_SemTbl[dev_nbr][ep_ix], EP_SIG_EVENT_POST);
}
if (cnt) {
*p_err = USBD_ERR_NONE;
return;
}
tk_current = xTaskGetTickCount();
} while (!timeout_ms || (tk_current - tk_start <= timeout_ms));
*p_err = USBD_ERR_OS_TIMEOUT;
return;
}
/*
*********************************************************************************************************
* USBD_OS_SignalAbort()
*
* Description : Abort any wait operation on signal.
*
* Argument(s) : dev_nbr Device number.
* ------- Argument validated by the caller(s).
*
* ep_ix Endpoint index.
* ----- Argument validated by the caller(s).
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE OS signal successfully aborted.
* USBD_ERR_OS_FAIL OS signal NOT successfully aborted.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
void USBD_OS_EP_SignalAbort (CPU_INT08U dev_nbr,
CPU_INT08U ep_ix,
USBD_ERR *p_err)
{
int32_t ret;
ret = sdEventGroupSetBits(USBD_OS_EP_SemTbl[dev_nbr][ep_ix], EP_SIG_EVENT_ABORT);
if (ret < 0) {
*p_err = USBD_ERR_OS_FAIL;
} else {
*p_err = USBD_ERR_NONE;
}
}
/*
*********************************************************************************************************
* USBD_OS_SignalPost()
*
* Description : Make a signal available.
*
* Argument(s) : dev_nbr Device number.
* ------- Argument validated by the caller(s).
*
* ep_ix Endpoint index.
* ----- Argument validated by the caller(s).
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE OS signal successfully readied.
* USBD_ERR_OS_FAIL OS signal NOT successfully readied.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
void USBD_OS_EP_SignalPost (CPU_INT08U dev_nbr,
CPU_INT08U ep_ix,
USBD_ERR *p_err)
{
int32_t ret;
CPU_SR_ALLOC();
CPU_CRITICAL_ENTER();
USBD_OS_EP_SemCntTbl[dev_nbr][ep_ix]++;
CPU_CRITICAL_EXIT();
ret = sdEventGroupSetBits(USBD_OS_EP_SemTbl[dev_nbr][ep_ix], EP_SIG_EVENT_POST);
if (ret < 0) {
*p_err = USBD_ERR_OS_FAIL;
} else {
*p_err = USBD_ERR_NONE;
}
}
/*
*********************************************************************************************************
* USBD_OS_EP_LockCreate()
*
* Description : Create an OS resource to use as an endpoint lock.
*
* Argument(s) : dev_nbr Device number.
* ------- Argument validated by the caller(s).
*
* ep_ix Endpoint index.
* ----- Argument validated by the caller(s).
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE OS lock successfully created.
* USBD_ERR_OS_SIGNAL_CREATE OS lock NOT successfully created.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
void USBD_OS_EP_LockCreate (CPU_INT08U dev_nbr,
CPU_INT08U ep_ix,
USBD_ERR *p_err)
{
SemaphoreHandle_t hMutex;
hMutex = sdSemaphoreCreateMutex();
if (!hMutex) {
*p_err = USBD_ERR_OS_SIGNAL_CREATE;
} else {
*p_err = USBD_ERR_NONE;
USBD_OS_EP_MutexTbl[dev_nbr][ep_ix] = hMutex;
}
}
/*
*********************************************************************************************************
* USBD_OS_EP_LockDel()
*
* Description : Delete the OS resource used as an endpoint lock.
*
* Argument(s) : dev_nbr Device number.
* ------- Argument validated by the caller(s).
*
* ep_ix Endpoint index.
* ----- Argument validated by the caller(s).
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
void USBD_OS_EP_LockDel (CPU_INT08U dev_nbr,
CPU_INT08U ep_ix)
{
sdSemaphoreDelete(USBD_OS_EP_MutexTbl[dev_nbr][ep_ix]);
}
/*
*********************************************************************************************************
* USBD_OS_EP_LockAcquire()
*
* Description : Wait for an endpoint to become available and acquire its lock.
*
* Argument(s) : dev_nbr Device number.
* ------- Argument validated by the caller(s).
*
* ep_ix Endpoint index.
* ----- Argument validated by the caller(s).
*
* timeout_ms Lock wait timeout in milliseconds.
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE OS lock successfully acquired.
* USBD_ERR_OS_TIMEOUT OS lock NOT successfully acquired in the time
* specified by 'timeout_ms'.
* USBD_ERR_OS_ABORT OS lock aborted.
* USBD_ERR_OS_FAIL OS lock not acquired because another error.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
void USBD_OS_EP_LockAcquire (CPU_INT08U dev_nbr,
CPU_INT08U ep_ix,
CPU_INT16U timeout_ms,
USBD_ERR *p_err)
{
BaseType_t ret;
uint32_t tmo;
tmo = timeout_ms ? timeout_ms : portMAX_DELAY;
ret = sdSemaphoreTake(USBD_OS_EP_MutexTbl[dev_nbr][ep_ix], tmo);
switch (ret) {
case pdPASS:
*p_err = USBD_ERR_NONE;
break;
case pdFAIL:
default:
if (tmo > 0) {
*p_err = USBD_ERR_OS_TIMEOUT;
} else {
*p_err = USBD_ERR_OS_FAIL;
usbd_os_err("Get Mutex %d-%d ret %d\r\n", dev_nbr, ep_ix, ret);
}
break;
}
}
/*
*********************************************************************************************************
* USBD_OS_EP_LockRelease()
*
* Description : Release an endpoint lock.
*
* Argument(s) : dev_nbr Device number.
* ------- Argument validated by the caller(s).
*
* ep_ix Endpoint index.
* ----- Argument validated by the caller(s).
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
void USBD_OS_EP_LockRelease (CPU_INT08U dev_nbr,
CPU_INT08U ep_ix)
{
if (sdSemaphoreGive(USBD_OS_EP_MutexTbl[dev_nbr][ep_ix]) != pdPASS) {
usbd_os_err("Mutex %d-%d Release failed\r\n", dev_nbr, ep_ix);
}
}
/*
*********************************************************************************************************
* USBD_OS_DlyMs()
*
* Description : Delay a task for a certain time.
*
* Argument(s) : ms Delay in milliseconds.
*
* Return(s) : None.
*
* Note(s) : None.
*********************************************************************************************************
*/
void USBD_OS_DlyMs (CPU_INT32U ms)
{
if (ms < 3)
udelay(ms * 1000);
else
vTaskDelay(ms);
}
/*
*********************************************************************************************************
* USBD_OS_CoreEventGet()
*
* Description : Wait until a core event is ready.
*
* Argument(s) : timeout_ms Timeout in milliseconds.
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE Core event successfully obtained.
* USBD_ERR_OS_TIMEOUT Core event NOT ready and a timeout occurred.
* USBD_ERR_OS_ABORT Core event was aborted.
* USBD_ERR_OS_FAIL Core event NOT ready because of another error.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
void *USBD_OS_CoreEventGet (CPU_INT32U timeout_ms,
USBD_ERR *p_err)
{
void *p_msg;
BaseType_t ret;
uint32_t tmo;
tmo = timeout_ms ? timeout_ms : portMAX_DELAY;
ret = sdQueueReceive(USBD_OS_CoreMsgID, &p_msg, tmo);
switch (ret) {
case pdPASS:
*p_err = USBD_ERR_NONE;
break;
case pdFAIL:
default:
if (tmo) {
*p_err = USBD_ERR_OS_TIMEOUT;
} else {
*p_err = USBD_ERR_OS_FAIL;
}
usbd_os_err("MsgQ Get failed\r\n");
break;
}
return (*p_err == USBD_ERR_NONE ? p_msg : NULL);
}
/*
*********************************************************************************************************
* USBD_OS_CoreEventPut()
*
* Description : Queues core event.
*
* Argument(s) : p_event Pointer to core event.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
void USBD_OS_CoreEventPut (void *p_event)
{
void *p_msg;
p_msg = p_event;
if (sdQueueSend(USBD_OS_CoreMsgID, &p_msg, 0) != pdPASS) {
usbd_os_err("MsgQ Put failed\r\n");
}
}