aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2012-06-13 16:13:00 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2012-06-13 16:13:00 +0000
commitf620f29e0a803ed942134ac8a801d5204cebe034 (patch)
treeb2085f49e6b84e76ecc122a521c65a442381213f
parent93ed653e57fb9947feadf43d36442658e00d4339 (diff)
downloadChibiOS-f620f29e0a803ed942134ac8a801d5204cebe034.tar.gz
ChibiOS-f620f29e0a803ed942134ac8a801d5204cebe034.tar.bz2
ChibiOS-f620f29e0a803ed942134ac8a801d5204cebe034.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4273 35acf78f-673a-0410-8e92-d51de3d6d3f4
-rw-r--r--os/hal/include/io_channel.h2
-rw-r--r--os/hal/include/serial_usb.h1
-rw-r--r--os/hal/include/usb.h14
-rw-r--r--os/hal/platforms/STM32/OTGv1/usb_lld.c278
-rw-r--r--os/hal/platforms/STM32/OTGv1/usb_lld.h12
-rw-r--r--os/hal/src/serial_usb.c26
-rw-r--r--testhal/STM32F4xx/USB_CDC/Makefile2
-rw-r--r--testhal/STM32F4xx/USB_CDC/main.c11
8 files changed, 226 insertions, 120 deletions
diff --git a/os/hal/include/io_channel.h b/os/hal/include/io_channel.h
index 3357bf6bd..2f2809bf8 100644
--- a/os/hal/include/io_channel.h
+++ b/os/hal/include/io_channel.h
@@ -275,7 +275,7 @@ typedef struct {
/** @brief No pending conditions.*/
#define CHN_NO_ERROR 0
/** @brief Connection happened.*/
-#define ICHN_CONNECTED 1
+#define CHN_CONNECTED 1
/** @brief Disconnection happened.*/
#define CHN_DISCONNECTED 2
/** @brief Data available in the input queue.*/
diff --git a/os/hal/include/serial_usb.h b/os/hal/include/serial_usb.h
index c5b118e70..4ad65d76d 100644
--- a/os/hal/include/serial_usb.h
+++ b/os/hal/include/serial_usb.h
@@ -160,6 +160,7 @@ extern "C" {
void sduObjectInit(SerialUSBDriver *sdp);
void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config);
void sduStop(SerialUSBDriver *sdup);
+ void sduConfigureHookI(USBDriver *usbp);
bool_t sduRequestsHook(USBDriver *usbp);
void sduDataTransmitted(USBDriver *usbp, usbep_t ep);
void sduDataReceived(USBDriver *usbp, usbep_t ep);
diff --git a/os/hal/include/usb.h b/os/hal/include/usb.h
index d2a154949..751128c7c 100644
--- a/os/hal/include/usb.h
+++ b/os/hal/include/usb.h
@@ -322,8 +322,20 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
* @{
*/
/**
+ * @brief Returns the sriver state.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @return The driver state.
+ *
+ * @iclass
+ */
+#define usbGetDriverStateI(usbp) ((usbp)->state)
+
+/**
* @brief Connects the USB device.
*
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
* @api
*/
#define usbConnectBus(usbp) usb_lld_connect_bus(usbp)
@@ -331,6 +343,8 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
/**
* @brief Disconnect the USB device.
*
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
* @api
*/
#define usbDisconnectBus(usbp) usb_lld_disconnect_bus(usbp)
diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.c b/os/hal/platforms/STM32/OTGv1/usb_lld.c
index 33cb571ec..5dc5a1052 100644
--- a/os/hal/platforms/STM32/OTGv1/usb_lld.c
+++ b/os/hal/platforms/STM32/OTGv1/usb_lld.c
@@ -144,7 +144,7 @@ static void otg_rxfifo_flush(void) {
OTG->GRSTCTL = GRSTCTL_RXFFLSH;
while ((OTG->GRSTCTL & GRSTCTL_RXFFLSH) != 0)
;
- /* Wait for 3 PHY Clocks*/
+ /* Wait for 3 PHY Clocks.*/
halPolledDelay(12);
}
@@ -153,7 +153,7 @@ static void otg_txfifo_flush(uint32_t fifo) {
OTG->GRSTCTL = GRSTCTL_TXFNUM(fifo) | GRSTCTL_TXFFLSH;
while ((OTG->GRSTCTL & GRSTCTL_TXFFLSH) != 0)
;
- /* Wait for 3 PHY Clocks*/
+ /* Wait for 3 PHY Clocks.*/
halPolledDelay(12);
}
@@ -186,6 +186,84 @@ static uint32_t otg_ram_alloc(USBDriver *usbp, size_t size) {
"otg_fifo_alloc(), #1", "FIFO memory overflow");
return next;
}
+/**
+ * @brief Prepares for a transmit transaction on an IN endpoint.
+ * @post The endpoint is ready for @p usbStartTransmitI().
+ * @note The transmit transaction size is equal to the data contained
+ * in the queue.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[in] n maximum number of bytes to copy
+ *
+ * @special
+ */
+static void otg_prepare_transmit(USBDriver *usbp, usbep_t ep, size_t n) {
+ uint32_t pcnt;
+ USBInEndpointState *isp = usbp->epc[ep]->in_state;
+
+ isp->txsize = n;
+ isp->txcnt = 0;
+
+ /* Transfer initialization.*/
+ if (n == 0) {
+ /* Special case, sending zero size packet.*/
+ OTG->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0);
+ }
+ else {
+ /* Normal case.*/
+ pcnt = (n + usbp->epc[ep]->in_maxsize - 1) / usbp->epc[ep]->in_maxsize;
+ OTG->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(pcnt) |
+ DIEPTSIZ_XFRSIZ(usbp->epc[ep]->in_state->txsize);
+ }
+}
+
+/**
+ * @brief Prepares for a receive transaction on an OUT endpoint.
+ * @post The endpoint is ready for @p usbStartReceiveI().
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[in] n maximum number of bytes to copy
+ *
+ * @special
+ */
+static void otg_prepare_receive(USBDriver *usbp, usbep_t ep, size_t n) {
+ uint32_t pcnt;
+ USBOutEndpointState *osp = usbp->epc[ep]->out_state;
+
+ osp->rxsize = n;
+ osp->rxcnt = 0;
+
+ /* Transfer initialization.*/
+ pcnt = (n + usbp->epc[ep]->out_maxsize - 1) / usbp->epc[ep]->out_maxsize;
+ OTG->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
+ DOEPTSIZ_XFRSIZ(usbp->epc[ep]->out_maxsize);
+}
+
+/**
+ * @brief Pushes a series of words into a FIFO.
+ *
+ * @param[in] fifop pointer to the FIFO register
+ * @param[in] buf pointer to the words buffer, not necessarily word
+ * aligned
+ * @param[in] n number of words to push
+ *
+ * @return A pointer after the last word pushed.
+ *
+ * @notapi
+ */
+static uint8_t *otg_do_push(volatile uint32_t *fifop, uint8_t *buf, size_t n) {
+
+ while (n > 0) {
+ /* Note, this line relies on the Cortex-M3/M4 ability to perform
+ unaligned word accesses and on the LSB-first memory organization.*/
+ *fifop = *((uint32_t *)buf);
+ buf += 4;
+ n--;
+ }
+ return buf;
+}
/**
* @brief Writes to a TX FIFO.
@@ -199,19 +277,8 @@ static uint32_t otg_ram_alloc(USBDriver *usbp, size_t size) {
static void otg_fifo_write_from_buffer(usbep_t ep,
const uint8_t *buf,
size_t n) {
- volatile uint32_t *fifop;
- fifop = OTG_FIFO(ep);
- n = (n + 3) / 4;
- while (n) {
- uint32_t dw = (uint32_t)buf[0] |
- ((uint32_t)buf[1] << 8) |
- ((uint32_t)buf[2] << 16) |
- ((uint32_t)buf[3] << 24);
- *fifop = dw;
- n--;
- buf += 4;
- }
+ otg_do_push(OTG_FIFO(ep), (uint8_t *)buf, (n + 3) / 4);
}
/**
@@ -226,37 +293,44 @@ static void otg_fifo_write_from_buffer(usbep_t ep,
static void otg_fifo_write_from_queue(usbep_t ep,
OutputQueue *oqp,
size_t n) {
- size_t nw;
- uint8_t *bp;
+ size_t ntogo;
volatile uint32_t *fifop;
fifop = OTG_FIFO(ep);
- /* Fetching data from the queue buffer directly.*/
- bp = oqp->q_rdptr;
- nw = (n + 3) / 4;
- do {
- uint32_t dw;
- dw = (uint32_t)*bp++;
- if (bp >= oqp->q_top)
- bp = oqp->q_buffer;
- dw |= (uint32_t)*bp++ << 8;
- if (bp >= oqp->q_top)
- bp = oqp->q_buffer;
- dw |= (uint32_t)*bp++ << 16;
- if (bp >= oqp->q_top)
- bp = oqp->q_buffer;
- dw |= (uint32_t)*bp++ << 24;
- if (bp >= oqp->q_top)
- bp = oqp->q_buffer;
+ ntogo = n;
+ while (ntogo > 0) {
+ uint32_t dw, i;
+ size_t streak, nw = ntogo / 4;
+ uint32_t nw2end = (oqp->q_top - oqp->q_rdptr) / 4;
+
+ ntogo -= (streak = nw <= nw2end ? nw : nw2end) * 4;
+ oqp->q_rdptr = otg_do_push(fifop, oqp->q_rdptr, streak);
+ if (oqp->q_rdptr >= oqp->q_top) {
+ oqp->q_rdptr = oqp->q_buffer;
+ continue;
+ }
+
+ /* If this condition is not satisfied then there is a word lying across
+ queue circular buffer boundary.*/
+ if (ntogo <= 0)
+ break;
+
+ /* One byte at time.*/
+ dw = 0;
+ i = 0;
+ while ((ntogo > 0) && (i < 4)) {
+ dw |= (uint32_t)*oqp->q_rdptr++ << (i * 8);
+ if (oqp->q_rdptr >= oqp->q_top)
+ oqp->q_rdptr = oqp->q_buffer;
+ ntogo--;
+ i++;
+ }
*fifop = dw;
- } while (--nw > 0);
+ }
/* Updating queue.*/
chSysLockFromIsr();
- oqp->q_rdptr += n;
- if (oqp->q_rdptr >= oqp->q_top)
- oqp->q_rdptr -= chQSizeI(oqp);
oqp->q_counter += n;
while (notempty(&oqp->q_waiting))
chSchReadyI(fifo_remove(&oqp->q_waiting))->p_u.rdymsg = Q_OK;
@@ -264,6 +338,31 @@ static void otg_fifo_write_from_queue(usbep_t ep,
}
/**
+ * @brief Pops a series of words from a FIFO.
+ *
+ * @param[in] fifop pointer to the FIFO register
+ * @param[in] buf pointer to the words buffer, not necessarily word
+ * aligned
+ * @param[in] n number of words to push
+ *
+ * @return A pointer after the last word pushed.
+ *
+ * @notapi
+ */
+static uint8_t *otg_do_pop(volatile uint32_t *fifop, uint8_t *buf, size_t n) {
+
+ while (n > 0) {
+ uint32_t dw = *fifop;
+ /* Note, this line relies on the Cortex-M3/M4 ability to perform
+ unaligned word accesses and on the LSB-first memory organization.*/
+ *((uint32_t *)buf) = dw;
+ buf += 4;
+ n--;
+ }
+ return buf;
+}
+
+/**
* @brief Reads a packet from the RXFIFO.
*
* @param[out] buf buffer where to copy the endpoint data
@@ -281,10 +380,10 @@ static void otg_fifo_read_to_buffer(uint8_t *buf, size_t n, size_t max) {
while (n) {
uint32_t dw = *fifop;
if (max) {
- *buf++ = (uint8_t)dw;
- *buf++ = (uint8_t)(dw >> 8);
- *buf++ = (uint8_t)(dw >> 16);
- *buf++ = (uint8_t)(dw >> 24);
+ /* Note, this line relies on the Cortex-M3/M4 ability to perform
+ unaligned word accesses and on the LSB-first memory organization.*/
+ *((uint32_t *)buf) = dw;
+ buf += 4;
max--;
}
n--;
@@ -300,37 +399,40 @@ static void otg_fifo_read_to_buffer(uint8_t *buf, size_t n, size_t max) {
* @notapi
*/
static void otg_fifo_read_to_queue(InputQueue *iqp, size_t n) {
- size_t nw, nb;
+ size_t ntogo;
volatile uint32_t *fifop;
fifop = OTG_FIFO(0);
- nb = n;
- nw = (n + 3) / 4;
- do {
- uint32_t dw = *fifop;
- *iqp->q_wrptr++ = (uint8_t)dw;
- if (iqp->q_wrptr >= iqp->q_top)
- iqp->q_wrptr = iqp->q_buffer;
- if (--nb > 0) {
- *iqp->q_wrptr++ = (uint8_t)(dw >> 8);
- if (iqp->q_wrptr >= iqp->q_top)
- iqp->q_wrptr = iqp->q_buffer;
- if (--nb > 0) {
- *iqp->q_wrptr++ = (uint8_t)(dw >> 16);
- if (iqp->q_wrptr >= iqp->q_top)
- iqp->q_wrptr = iqp->q_buffer;
+ ntogo = n;
+ while (ntogo > 0) {
+ uint32_t dw, i;
+ size_t streak, nw = ntogo / 4;
+ uint32_t nw2end = (iqp->q_wrptr - iqp->q_wrptr) / 4;
- if (--nb > 0) {
- *iqp->q_wrptr++ = (uint8_t)(dw >> 24);
- if (iqp->q_wrptr >= iqp->q_top)
- iqp->q_wrptr = iqp->q_buffer;
+ ntogo -= (streak = nw <= nw2end ? nw : nw2end) * 4;
+ iqp->q_wrptr = otg_do_pop(fifop, iqp->q_wrptr, streak);
+ if (iqp->q_wrptr >= iqp->q_top) {
+ iqp->q_wrptr = iqp->q_buffer;
+ continue;
+ }
+
+ /* If this condition is not satisfied then there is a word lying across
+ queue circular buffer boundary.*/
+ if (ntogo <= 0)
+ break;
- --nb;
- }
- }
+ /* One byte at time.*/
+ dw = *fifop;
+ i = 0;
+ while ((ntogo > 0) && (i < 4)) {
+ *iqp->q_wrptr++ = (uint8_t)dw >> (i * 8);
+ if (iqp->q_wrptr >= iqp->q_top)
+ iqp->q_wrptr = iqp->q_buffer;
+ ntogo--;
+ i++;
}
- } while (--nw > 0);
+ }
/* Updating queue.*/
chSysLockFromIsr();
@@ -846,18 +948,11 @@ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
*/
void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep,
uint8_t *buf, size_t n) {
- uint32_t pcnt;
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
osp->rxqueued = FALSE;
- osp->rxsize = n;
- osp->rxcnt = 0;
osp->mode.linear.rxbuf = buf;
-
- /* Transfer initialization.*/
- pcnt = (n + usbp->epc[ep]->out_maxsize - 1) / usbp->epc[ep]->out_maxsize;
- OTG->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
- DOEPTSIZ_XFRSIZ(usbp->epc[ep]->out_maxsize);
+ otg_prepare_receive(usbp, ep, n);
}
/**
@@ -872,30 +967,15 @@ void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep,
*/
void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
const uint8_t *buf, size_t n) {
- uint32_t pcnt;
USBInEndpointState *isp = usbp->epc[ep]->in_state;
isp->txqueued = FALSE;
- isp->txsize = n;
- isp->txcnt = 0;
isp->mode.linear.txbuf = buf;
-
- if (n == 0) {
- /* Special case, sending zero size packet.*/
- OTG->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0);
- }
- else {
- /* Transfer initialization.*/
- pcnt = (n + usbp->epc[ep]->in_maxsize - 1) / usbp->epc[ep]->in_maxsize;
- OTG->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(pcnt) |
- DIEPTSIZ_XFRSIZ(usbp->epc[ep]->in_state->txsize);
- }
+ otg_prepare_transmit(usbp, ep, n);
}
/**
* @brief Prepares for a receive transaction on an OUT endpoint.
- * @pre In order to use this function the endpoint must have been
- * initialized in transaction mode.
* @post The endpoint is ready for @p usbStartReceiveI().
* @note The receive transaction size is equal to the space in the queue
* rounded to the lower multiple of a packet size. So make sure there
@@ -911,24 +991,15 @@ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
*/
void usb_lld_prepare_queued_receive(USBDriver *usbp, usbep_t ep,
InputQueue *iq, size_t n) {
- uint32_t pcnt;
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
osp->rxqueued = TRUE;
- osp->rxsize = n;
- osp->rxcnt = 0;
osp->mode.queue.rxqueue = iq;
-
- /* Transfer initialization.*/
- pcnt = (n + usbp->epc[ep]->out_maxsize - 1) / usbp->epc[ep]->out_maxsize;
- OTG->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
- DOEPTSIZ_XFRSIZ(usbp->epc[ep]->out_maxsize);
+ otg_prepare_receive(usbp, ep, n);
}
/**
* @brief Prepares for a transmit transaction on an IN endpoint.
- * @pre In order to use this function the endpoint must have been
- * initialized in transaction mode.
* @post The endpoint is ready for @p usbStartTransmitI().
* @note The transmit transaction size is equal to the data contained
* in the queue.
@@ -942,18 +1013,11 @@ void usb_lld_prepare_queued_receive(USBDriver *usbp, usbep_t ep,
*/
void usb_lld_prepare_queued_transmit(USBDriver *usbp, usbep_t ep,
OutputQueue *oq, size_t n) {
- uint32_t pcnt;
USBInEndpointState *isp = usbp->epc[ep]->in_state;
isp->txqueued = TRUE;
- isp->txsize = n;
- isp->txcnt = 0;
isp->mode.queue.txqueue = oq;
-
- /* Transfer initialization.*/
- pcnt = (n + usbp->epc[ep]->in_maxsize - 1) / usbp->epc[ep]->in_maxsize;
- OTG->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(pcnt) |
- DIEPTSIZ_XFRSIZ(usbp->epc[ep]->in_state->txsize);
+ otg_prepare_transmit(usbp, ep, n);
}
/**
diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.h b/os/hal/platforms/STM32/OTGv1/usb_lld.h
index ea0def924..9dc2a0eec 100644
--- a/os/hal/platforms/STM32/OTGv1/usb_lld.h
+++ b/os/hal/platforms/STM32/OTGv1/usb_lld.h
@@ -126,7 +126,7 @@ typedef struct {
union {
struct {
/**
- * @brief Pointer to the transmission buffer.
+ * @brief Pointer to the transmission linear buffer.
*/
const uint8_t *txbuf;
} linear;
@@ -158,7 +158,7 @@ typedef struct {
union {
struct {
/**
- * @brief Pointer to the receive buffer.
+ * @brief Pointer to the receive linear buffer.
*/
uint8_t *rxbuf;
} linear;
@@ -217,16 +217,12 @@ typedef struct {
uint16_t out_maxsize;
/**
* @brief @p USBEndpointState associated to the IN endpoint.
- * @details This structure maintains the state of the IN endpoint when
- * the endpoint is not in packet mode. Endpoints configured in
- * packet mode must set this field to @p NULL.
+ * @details This structure maintains the state of the IN endpoint.
*/
USBInEndpointState *in_state;
/**
* @brief @p USBEndpointState associated to the OUT endpoint.
- * @details This structure maintains the state of the OUT endpoint when
- * the endpoint is not in packet mode. Endpoints configured in
- * packet mode must set this field to @p NULL.
+ * @details This structure maintains the state of the OUT endpoint.
*/
USBOutEndpointState *out_state;
/* End of the mandatory fields.*/
diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c
index 52be6e975..2b02ae02f 100644
--- a/os/hal/src/serial_usb.c
+++ b/os/hal/src/serial_usb.c
@@ -120,6 +120,11 @@ static void inotify(GenericQueue *qp) {
size_t n, maxsize;
SerialUSBDriver *sdup = chQGetLink(qp);
+ /* If the USB driver is not in the appropriate state then transactions
+ must not be started.*/
+ if (usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE)
+ return;
+
/* If there is in the queue enough space to hold at least one packet and
a transaction is not yet started then a new transaction is started for
the available space.*/
@@ -145,6 +150,11 @@ static void onotify(GenericQueue *qp) {
size_t n;
SerialUSBDriver *sdup = chQGetLink(qp);
+ /* If the USB driver is not in the appropriate state then transactions
+ must not be started.*/
+ if (usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE)
+ return;
+
/* If there is not an ongoing transaction and the output queue contains
data then a new transaction is started.*/
if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP) &&
@@ -239,6 +249,22 @@ void sduStop(SerialUSBDriver *sdup) {
}
/**
+ * @brief USB device configured handler.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ *
+ * @iclass
+ */
+void sduConfigureHookI(USBDriver *usbp) {
+ SerialUSBDriver *sdup = usbp->param;
+
+ sdup->flags = CHN_NO_ERROR;
+ chIQResetI(&sdup->iqueue);
+ chOQResetI(&sdup->oqueue);
+ chnAddFlagsI(sdup, CHN_CONNECTED);
+}
+
+/**
* @brief Default requests hook.
* @details Applications wanting to use the Serial over USB driver can use
* this function as requests hook in the USB configuration.
diff --git a/testhal/STM32F4xx/USB_CDC/Makefile b/testhal/STM32F4xx/USB_CDC/Makefile
index 233e47d0e..1a6ac2d74 100644
--- a/testhal/STM32F4xx/USB_CDC/Makefile
+++ b/testhal/STM32F4xx/USB_CDC/Makefile
@@ -5,7 +5,7 @@
# Compiler options here.
ifeq ($(USE_OPT),)
- USE_OPT = -O0 -ggdb -fomit-frame-pointer -falign-functions=16
+ USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
endif
# C specific options here (added to USE_OPT).
diff --git a/testhal/STM32F4xx/USB_CDC/main.c b/testhal/STM32F4xx/USB_CDC/main.c
index 0ae9c81e0..99acdc894 100644
--- a/testhal/STM32F4xx/USB_CDC/main.c
+++ b/testhal/STM32F4xx/USB_CDC/main.c
@@ -296,13 +296,18 @@ static void usb_event(USBDriver *usbp, usbevent_t event) {
case USB_EVENT_ADDRESS:
return;
case USB_EVENT_CONFIGURED:
+ chSysLockFromIsr();
+
/* Enables the endpoints specified into the configuration.
Note, this callback is invoked from an ISR so I-Class functions
must be used.*/
- chSysLockFromIsr();
usbInitEndpointI(usbp, USB_CDC_DATA_REQUEST_EP, &ep1config);
usbInitEndpointI(usbp, USB_CDC_INTERRUPT_REQUEST_EP, &ep2config);
usbInitEndpointI(usbp, USB_CDC_DATA_AVAILABLE_EP, &ep3config);
+
+ /* Resetting the state of the CDC subsystem.*/
+ sduConfigureHookI(usbp);
+
chSysUnlockFromIsr();
return;
case USB_EVENT_SUSPEND:
@@ -437,10 +442,10 @@ int main(void) {
/*
* Activates the USB driver and then the USB bus pull-up on D+.
*/
+ usbDisconnectBus(serusbcfg.usbp);
+ chThdSleepMilliseconds(1000);
sduObjectInit(&SDU1);
sduStart(&SDU1, &serusbcfg);
- usbDisconnectBus(serusbcfg.usbp);
- chThdSleepMilliseconds(100);
usbConnectBus(serusbcfg.usbp);
/*