Files
2025-11-07 20:19:23 +08:00

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");
}