#include <drv/timer.h>
#include <drv/usb.h>
+#include <mware/event.h>
+
#include <string.h> /* memcpy() */
#include "usb_stm32.h"
-/* XXX: consider to move this to cfg/compiler.h */
-#define ALIGNED(x) __attribute__ ((__aligned__(x)))
-
/* XXX: consider to move this to cfg/macros.h */
-#define ALIGN_UP(value, align) (((value) & ((align) - 1)) ? \
- (((value) + ((align) - 1)) & ~((align) - 1)) : \
- (value))
/* XXX: redefine this to make it usable within C expression */
#define _MIN(a,b) (((a) < (b)) ? (a) : (b))
/* Endpoint descriptors: used for handling requests to use with endpoints */
static stm32_UsbEp ep_cnfg[EP_MAX_NUM];
+STATIC_ASSERT(EP_MAX_NUM <= EP_MAX_HW_NUM);
/* USB EP0 control descriptor */
static const UsbEndpointDesc USB_CtrlEpDescr0 =
static stm32_UsbMemSlot *mem_use;
/* USB packet memory management: memory buffer metadata */
-static stm32_UsbMemSlot memory_buffer[EP_MAX_HW_NUM >> 1];
+static stm32_UsbMemSlot memory_buffer[EP_MAX_NUM];
/* Endpoint TX and RX buffers */
/// \cond
/* XXX: use the empty cond section to silent a buggy doxygen warning */
-static bool rx_done, tx_done;
static size_t rx_size, tx_size;
-static uint8_t ep_buffer[_MIN(CONFIG_USB_BUFSIZE, USB_XFER_MAX_SIZE)] ALIGNED(4);
+
+#define EP_BUFFER_SIZE _MIN(CONFIG_USB_BUFSIZE, USB_XFER_MAX_SIZE)
+STATIC_ASSERT(!(EP_BUFFER_SIZE & 0x03));
+
+static uint8_t ep_buffer[EP_MAX_NUM][EP_BUFFER_SIZE] ALIGNED(4);
/// \endcond
+static Event usb_event_done[EP_MAX_SLOTS];
+
/* Allocate a free block of the packet memory */
static stm32_UsbMemSlot *usb_malloc(void)
{
mem = mem->next;
}
/* Check for out-of-memory condition */
- if ((*pOffset + max_size) >= USB_BDT_OFFSET)
+ if (UNLIKELY((*pOffset + max_size) >= USB_BDT_OFFSET))
return false;
/*
* Allocate a new memory block, next to the last allocated block.
*/
mem_useNew = usb_malloc();
- if (mem_useNew == NULL)
+ if (UNLIKELY(mem_useNew == NULL))
return false;
/* Insert the block to the list of allocated blocks */
if (mem_use == NULL)
}
ASSERT(!(ep & 0x01));
- rx_done = true;
+ event_do(&usb_event_done[ep >> 1]);
rx_size = ep_cnfg[ep].size;
}
ssize_t usb_endpointRead(int ep, void *buffer, ssize_t size)
{
int ep_num = usb_ep_logical_to_hw(ep);
- ssize_t max_size = sizeof(ep_buffer);
+ ssize_t max_size = sizeof(ep_buffer[ep_num]);
/* Non-blocking read for EP0 */
if (ep_num == CTRL_ENP_OUT)
usb_status_handler(ep_num);
else
{
- __usb_ep_read(ep_num, ep_buffer, size,
+ __usb_ep_read(ep_num, ep_buffer[ep_num], size,
usb_status_handler);
- memcpy(buffer, ep_buffer, size);
+ memcpy(buffer, ep_buffer[ep_num], size);
}
return size;
}
if (UNLIKELY(!size))
return 0;
size = MIN(size, max_size);
- rx_done = false;
+ event_initGeneric(&usb_event_done[ep_num >> 1]);
rx_size = 0;
/* Blocking read */
- __usb_ep_read(ep_num, ep_buffer, size, usb_endpointRead_complete);
- while (!rx_done)
- cpu_relax();
- memcpy(buffer, ep_buffer, rx_size);
+ __usb_ep_read(ep_num, ep_buffer[ep_num], size,
+ usb_endpointRead_complete);
+ event_wait(&usb_event_done[ep_num >> 1]);
+ memcpy(buffer, ep_buffer[ep_num], rx_size);
return rx_size;
}
}
ASSERT(ep & 0x01);
- tx_done = true;
+ event_do(&usb_event_done[ep >> 1]);
tx_size = ep_cnfg[ep].size;
}
ssize_t usb_endpointWrite(int ep, const void *buffer, ssize_t size)
{
int ep_num = usb_ep_logical_to_hw(ep);
- ssize_t max_size = sizeof(ep_buffer);
+ ssize_t max_size = sizeof(ep_buffer[ep_num]);
/* Non-blocking write for EP0 */
if (ep_num == CTRL_ENP_IN)
usb_status_handler(ep_num);
else
{
- memcpy(ep_buffer, buffer, size);
- __usb_ep_write(ep_num, ep_buffer, size,
+ memcpy(ep_buffer[ep_num], buffer, size);
+ __usb_ep_write(ep_num, ep_buffer[ep_num], size,
usb_status_handler);
}
return size;
if (UNLIKELY(!size))
return 0;
size = MIN(size, max_size);
- tx_done = false;
+ event_initGeneric(&usb_event_done[ep_num >> 1]);
tx_size = 0;
/* Blocking write */
- memcpy(ep_buffer, buffer, size);
- __usb_ep_write(ep_num, ep_buffer, size, usb_endpointWrite_complete);
- while (!tx_done)
- cpu_relax();
+ memcpy(ep_buffer[ep_num], buffer, size);
+ __usb_ep_write(ep_num, ep_buffer[ep_num], size,
+ usb_endpointWrite_complete);
+ event_wait(&usb_event_done[ep_num >> 1]);
return tx_size;
}
udc.alt[i] = 0;
usb_set_device_state(USB_STATE_CONFIGURED);
usb_dev->configured = true;
+ event_do(&usb_event_done[0]);
LOG_INFO("%s: device configured\n", __func__);
}
else
MOD_CHECK(proc);
#endif
usb_dev = dev;
+ usb_dev->configured = false;
+
+ event_initGeneric(&usb_event_done[0]);
usb_init();
- while (!usb_dev->configured)
- cpu_relax();
+ event_wait(&usb_event_done[0]);
+
return 0;
}