582 lines
19 KiB
C
582 lines
19 KiB
C
/*
|
|
*********************************************************************************************************
|
|
* uC/USB-Device
|
|
* The Embedded USB Device Stack
|
|
*
|
|
* Copyright (c) 2021 Semidrive Semiconductor
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*
|
|
* USB DEVICE OPERATING SYSTEM LAYER
|
|
* For no OS
|
|
*
|
|
* Filename : usbd_os.c
|
|
* Version : V1.00.00
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* INCLUDE FILES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include "../../Source/usbd_core.h"
|
|
#include "../../Source/usbd_internal.h"
|
|
#include <irq.h>
|
|
#include <udelay/udelay.h>
|
|
#include <usb_bsp_e3.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_ABORT (1u<<30)
|
|
#define EP_SIG_DEL (1u<<31)
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL CONSTANTS
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL DATA TYPES
|
|
*********************************************************************************************************
|
|
*/
|
|
struct usb_msg_queue {
|
|
void **q;
|
|
uint16_t length; /* total length */
|
|
uint16_t count; /* valid message count */
|
|
uint16_t head;
|
|
uint16_t tail;
|
|
};
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL TABLES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL GLOBAL VARIABLES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void *usb_message[USBD_CORE_EVENT_NBR_TOTAL];
|
|
static struct usb_msg_queue usb_msg_q;
|
|
|
|
static uint32_t USBD_OS_EP_SemTbl[USBD_CFG_MAX_NBR_DEV][USBD_CFG_MAX_NBR_EP_OPEN];
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL MACRO'S
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define usbd_os_err(...) ssdk_printf(SSDK_CRIT, __VA_ARGS__)
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL FUNCTION PROTOTYPES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* 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)
|
|
{
|
|
usb_msg_q.count = 0;
|
|
usb_msg_q.head = 0;
|
|
usb_msg_q.tail = 0;
|
|
usb_msg_q.q = usb_message;
|
|
usb_msg_q.length = USBD_CORE_EVENT_NBR_TOTAL;
|
|
|
|
*p_err = USBD_ERR_NONE;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* 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)
|
|
{
|
|
USBD_OS_EP_SemTbl[dev_nbr][ep_ix] = 0;
|
|
*p_err = USBD_ERR_NONE;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* 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)
|
|
{
|
|
CPU_SR_ALLOC();
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
USBD_OS_EP_SemTbl[dev_nbr][ep_ix] |= EP_SIG_DEL;
|
|
CPU_CRITICAL_EXIT();
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* 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 temp;
|
|
uint32_t tk_start;
|
|
CPU_SR_ALLOC();
|
|
|
|
tk_start = usb_tick_get_us();
|
|
while (!timeout_ms || (usb_tick_get_us() - tk_start < timeout_ms * 1000)) {
|
|
CPU_CRITICAL_ENTER();
|
|
temp = USBD_OS_EP_SemTbl[dev_nbr][ep_ix];
|
|
if (temp & EP_SIG_DEL) {
|
|
*p_err = USBD_ERR_OS_DEL;
|
|
} else if (temp & EP_SIG_ABORT) {
|
|
USBD_OS_EP_SemTbl[dev_nbr][ep_ix] &= ~EP_SIG_ABORT;
|
|
*p_err = USBD_ERR_OS_ABORT;
|
|
} else if (temp & 0xFFFFu) {
|
|
USBD_OS_EP_SemTbl[dev_nbr][ep_ix]--;
|
|
*p_err = USBD_ERR_NONE;
|
|
}
|
|
CPU_CRITICAL_EXIT();
|
|
if (temp)
|
|
break;
|
|
}
|
|
|
|
if (!temp) {
|
|
*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)
|
|
{
|
|
CPU_SR_ALLOC();
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
USBD_OS_EP_SemTbl[dev_nbr][ep_ix] |= EP_SIG_ABORT;
|
|
CPU_CRITICAL_EXIT();
|
|
*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)
|
|
{
|
|
CPU_SR_ALLOC();
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
if (USBD_OS_EP_SemTbl[dev_nbr][ep_ix] & EP_SIG_DEL) {
|
|
*p_err = USBD_ERR_OS_DEL;
|
|
} else if ((USBD_OS_EP_SemTbl[dev_nbr][ep_ix] & 0xFFFFu) < 10000u) {
|
|
USBD_OS_EP_SemTbl[dev_nbr][ep_ix]++;
|
|
*p_err = USBD_ERR_NONE;
|
|
} else {
|
|
*p_err = USBD_ERR_OS_FAIL;
|
|
}
|
|
CPU_CRITICAL_EXIT();
|
|
|
|
if (*p_err == USBD_ERR_OS_DEL)
|
|
usbd_os_err("post deleted signal\r\n");
|
|
else if (*p_err == USBD_ERR_OS_FAIL)
|
|
usbd_os_err("post signal overflow\r\n");
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* 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)
|
|
{
|
|
*p_err = USBD_ERR_NONE;
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* 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)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* 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)
|
|
{
|
|
*p_err = USBD_ERR_NONE;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* 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)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* 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)
|
|
{
|
|
udelay(ms * 1000);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBD_OS_CoreEventGet()
|
|
*
|
|
* Description : Get a core event.
|
|
*
|
|
* 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) : The next core event.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void *USBD_OS_CoreEventGet (CPU_INT32U timeout_ms,
|
|
USBD_ERR *p_err)
|
|
{
|
|
void *p_msg;
|
|
CPU_SR_ALLOC();
|
|
|
|
(void)timeout_ms; /* always return */
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
if (usb_msg_q.count) {
|
|
p_msg = usb_msg_q.q[usb_msg_q.tail];
|
|
usb_msg_q.tail++;
|
|
if (usb_msg_q.tail >= usb_msg_q.length) {
|
|
usb_msg_q.tail -= usb_msg_q.length;
|
|
}
|
|
usb_msg_q.count--;
|
|
|
|
*p_err = USBD_ERR_NONE;
|
|
} else {
|
|
p_msg = NULL;
|
|
|
|
*p_err = USBD_ERR_OS_TIMEOUT;
|
|
}
|
|
CPU_CRITICAL_EXIT();
|
|
|
|
return p_msg;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* 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)
|
|
{
|
|
int ret = 0;
|
|
CPU_SR_ALLOC();
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
if (usb_msg_q.count < usb_msg_q.length) {
|
|
usb_msg_q.q[usb_msg_q.head] = p_event;
|
|
usb_msg_q.head++;
|
|
if (usb_msg_q.head >= usb_msg_q.length) {
|
|
usb_msg_q.head -= usb_msg_q.length;
|
|
}
|
|
usb_msg_q.count++;
|
|
} else {
|
|
ret = -1;
|
|
}
|
|
CPU_CRITICAL_EXIT();
|
|
|
|
if (ret < 0)
|
|
usbd_os_err("No space to put new event message\r\n");
|
|
}
|
|
|