1086 lines
36 KiB
C
1086 lines
36 KiB
C
/*
|
||
*********************************************************************************************************
|
||
* 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");
|
||
}
|
||
}
|