X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fcpu%2Fcortex-m3%2Fdrv%2Fusb_stm32.c;h=ad91a9b83f8f578a2beefd501c6fca590bdc9817;hb=0e8d3b095f4b5ba3ac5c080c0e9edb5226c38bad;hp=e1fa5fbd48a90cc242e10554983fd394d326e312;hpb=6480c41afbe49bae54aeb18ce38bf58f541bf14e;p=bertos.git diff --git a/bertos/cpu/cortex-m3/drv/usb_stm32.c b/bertos/cpu/cortex-m3/drv/usb_stm32.c index e1fa5fbd..ad91a9b8 100644 --- a/bertos/cpu/cortex-m3/drv/usb_stm32.c +++ b/bertos/cpu/cortex-m3/drv/usb_stm32.c @@ -58,9 +58,14 @@ #include "usb_stm32.h" +#define ALIGNED(x) __attribute__ ((__aligned__(x))) #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)) + /* STM32 USB registers */ struct stm32_usb { @@ -143,6 +148,15 @@ static stm32_UsbMemSlot *mem_use; #define EP_MAX_SLOTS 16 static stm32_UsbMemSlot memory_buffer[EP_MAX_SLOTS]; +/* 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 rx_buffer[_MIN(CONFIG_USB_RXBUFSIZE, USB_RX_MAX_SIZE)] ALIGNED(4); +static uint8_t tx_buffer[_MIN(CONFIG_USB_TXBUFSIZE, USB_TX_MAX_SIZE)] ALIGNED(4); +/// \endcond + /* Allocate a free block of the packet memory */ static stm32_UsbMemSlot *usb_malloc(void) { @@ -671,12 +685,18 @@ out: \ static stm32_UsbIoStatus __usb_ep_read(int ep, void *buffer, ssize_t size, void (*complete)(int)) { - if (UNLIKELY(ep >= ENP_MAX_NUMB)) + if (UNLIKELY((ep >= ENP_MAX_NUMB) || (ep & 0x01))) { + LOG_ERR("%s: invalid EP number %d\n", __func__, ep); + ASSERT(0); + return STALLED; + } + if (UNLIKELY((size_t)buffer & 0x03)) + { + LOG_ERR("%s: unaligned buffer @ %p\n", __func__, buffer); ASSERT(0); return STALLED; } - ASSERT(!(ep & 0x01)); return USB_EP_IO(ep, read, buffer, size, complete); } @@ -684,12 +704,18 @@ __usb_ep_read(int ep, void *buffer, ssize_t size, void (*complete)(int)) static stm32_UsbIoStatus __usb_ep_write(int ep, const void *buffer, ssize_t size, void (*complete)(int)) { - if (UNLIKELY(ep >= ENP_MAX_NUMB)) + if (UNLIKELY((ep >= ENP_MAX_NUMB) || !(ep & 0x01))) { + LOG_ERR("%s: invalid EP number %d\n", __func__, ep); + ASSERT(0); + return STALLED; + } + if (UNLIKELY((size_t)buffer & 0x03)) + { + LOG_ERR("%s: unaligned buffer @ %p\n", __func__, buffer); ASSERT(0); return STALLED; } - ASSERT(ep & 0x01); return USB_EP_IO(ep, write, buffer, size, complete); } @@ -1076,9 +1102,6 @@ static void usb_status_handler(UNUSED_ARG(int, EP)) } } -static bool rx_done; -static size_t rx_size; - static void usb_endpointRead_complete(int ep) { if (UNLIKELY(ep >= ENP_MAX_NUMB)) @@ -1095,35 +1118,44 @@ static void usb_endpointRead_complete(int ep) 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(rx_buffer); /* Non-blocking read for EP0 */ if (ep_num == CTRL_ENP_OUT) { size = usb_size(size, usb_le16_to_cpu(setup_packet.wLength)); + if (UNLIKELY(size > max_size)) + { + LOG_ERR("%s: rx_buffer exceeded, try to enlarge CONFIG_USB_RXBUFSIZE\n", + __func__); + ASSERT(0); + return -USB_BUF_OVERFLOW; + } if (!size) usb_status_handler(ep_num); else - __usb_ep_read(ep_num, buffer, size, + { + __usb_ep_read(ep_num, rx_buffer, size, usb_status_handler); + memcpy(buffer, rx_buffer, size); + } return size; } if (UNLIKELY(!size)) return 0; - size = MIN(size, USB_RX_MAX_SIZE); + size = MIN(size, max_size); rx_done = false; rx_size = 0; /* Blocking read */ - __usb_ep_read(ep_num, buffer, size, usb_endpointRead_complete); + __usb_ep_read(ep_num, rx_buffer, size, usb_endpointRead_complete); while (!rx_done) cpu_relax(); + memcpy(buffer, rx_buffer, rx_size); return rx_size; } -static bool tx_done; -static size_t tx_size; - static void usb_endpointWrite_complete(int ep) { if (UNLIKELY(ep >= ENP_MAX_NUMB)) @@ -1140,26 +1172,38 @@ static void usb_endpointWrite_complete(int ep) 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(tx_buffer); /* Non-blocking write for EP0 */ if (ep_num == CTRL_ENP_IN) { size = usb_size(size, usb_le16_to_cpu(setup_packet.wLength)); + if (UNLIKELY(size > max_size)) + { + LOG_ERR("%s: tx_buffer exceeded, try to enlarge CONFIG_USB_TXBUFSIZE\n", + __func__); + ASSERT(0); + return -USB_BUF_OVERFLOW; + } if (!size) usb_status_handler(ep_num); else - __usb_ep_write(ep_num, buffer, size, + { + memcpy(tx_buffer, buffer, size); + __usb_ep_write(ep_num, tx_buffer, size, usb_status_handler); + } return size; } if (UNLIKELY(!size)) return 0; - size = MIN(size, USB_TX_MAX_SIZE); + size = MIN(size, max_size); tx_done = false; tx_size = 0; /* Blocking write */ - __usb_ep_write(ep_num, buffer, size, usb_endpointWrite_complete); + memcpy(tx_buffer, buffer, size); + __usb_ep_write(ep_num, tx_buffer, size, usb_endpointWrite_complete); while (!tx_done) cpu_relax(); @@ -1533,6 +1577,7 @@ static int usb_set_config_state(uint32_t conf) udc.alt[i] = 0; usb_set_device_state(USB_STATE_CONFIGURED); usb_dev->configured = true; + LOG_INFO("%s: device configured\n", __func__); } else {