/* ********************************************************************************************************* * 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 #include #include #include "task.h" #include "event_groups.h" #include "semphr.h" #include "../../Source/usbd_core.h" #include "../../Source/usbd_internal.h" #include #include /* ********************************************************************************************************* * 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"); } }