/* ********************************************************************************************************* * 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 #include "../../Source/usbd_core.h" #include "../../Source/usbd_internal.h" #include #include #include /* ********************************************************************************************************* * CONFIGURATION ERRORS ********************************************************************************************************* */ #if (USBD_CFG_DBG_TRACE_EN == DEF_ENABLED) #error "USBD_CFG_DBG_TRACE is not supported yet." #endif /* ********************************************************************************************************* * LOCAL DEFINES ********************************************************************************************************* */ #define EP_SIG_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"); }