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