From: arighi Date: Fri, 18 Feb 2011 23:55:18 +0000 (+0000) Subject: STM32: USB: correctly detect when read/write must be called without blocking X-Git-Tag: 2.7.0~249 X-Git-Url: https://codewiz.org/gitweb?a=commitdiff_plain;h=80ac3ae104b48f42eb8911de0879a477cf812a4c;p=bertos.git STM32: USB: correctly detect when read/write must be called without blocking Read or write operations with the EP0 may happen within the USB interrupt. Make the driver able to understand when the usb_endpointRead() or usb_endpointWrite() is called from the interrupt context or not. Basically, only the even callbacks concerning the EP0 should be called in a interrupt context. For all the other cases the user must take care of using usb_endpointRead() and usb_endointWrite() from a non-atomic (sleepable) context. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4717 38d2e660-2303-0410-9eaa-f027e97ec537 --- diff --git a/bertos/cpu/cortex-m3/drv/usb_stm32.c b/bertos/cpu/cortex-m3/drv/usb_stm32.c index 794aa891..ac3f55fa 100644 --- a/bertos/cpu/cortex-m3/drv/usb_stm32.c +++ b/bertos/cpu/cortex-m3/drv/usb_stm32.c @@ -160,6 +160,9 @@ static uint8_t ep_buffer[EP_MAX_NUM][EP_BUFFER_SIZE] ALIGNED(4); static Event usb_event_done[EP_MAX_SLOTS]; +/* Check if we're running in atomic (non-sleepable) context or not */ +static volatile bool in_atomic = false; + /* Allocate a free block of the packet memory */ static stm32_UsbMemSlot *usb_malloc(void) { @@ -1129,7 +1132,7 @@ ssize_t usb_endpointRead(int ep, void *buffer, ssize_t size) ssize_t max_size = sizeof(ep_buffer[ep_num]); /* Non-blocking read for EP0 */ - if (ep_num == CTRL_ENP_OUT) + if (in_atomic && (ep_num == CTRL_ENP_OUT)) { size = usb_size(size, usb_le16_to_cpu(setup_packet.wLength)); if (UNLIKELY(size > max_size)) @@ -1183,7 +1186,7 @@ ssize_t usb_endpointWrite(int ep, const void *buffer, ssize_t size) ssize_t max_size = sizeof(ep_buffer[ep_num]); /* Non-blocking write for EP0 */ - if (ep_num == CTRL_ENP_IN) + if (in_atomic && (ep_num == CTRL_ENP_IN)) { size = usb_size(size, usb_le16_to_cpu(setup_packet.wLength)); if (UNLIKELY(size > max_size)) @@ -1806,6 +1809,9 @@ static void usb_isr(void) interrupt.status = usb->ISTR; interrupt.status &= usb->CNTR | 0x1f; + /* Set the context as atomic */ + in_atomic = true; + if (interrupt.PMAOVR) { LOG_WARN("%s: DMA overrun / underrun\n", __func__); @@ -1855,6 +1861,7 @@ static void usb_isr(void) { usb_isr_correct_transfer(interrupt); } + in_atomic = false; } /* USB: hardware initialization */