diff options
-rw-r--r-- | demos/ARM7-AT91SAM7S-FATFS-GCC/main.c | 18 | ||||
-rw-r--r-- | demos/ARM7-AT91SAM7X-FATFS-GCC/main.c | 18 | ||||
-rw-r--r-- | demos/ARMCM3-STM32F103-FATFS/main.c | 18 | ||||
-rw-r--r-- | demos/ARMCM3-STM32F103ZG-FATFS/main.c | 18 | ||||
-rw-r--r-- | demos/PPC-SPC563-GCC/main.c | 18 | ||||
-rw-r--r-- | demos/Posix-GCC/main.c | 18 | ||||
-rw-r--r-- | demos/Win32-MinGW/main.c | 18 | ||||
-rw-r--r-- | os/hal/include/usb.h | 86 | ||||
-rw-r--r-- | os/hal/platforms/STM32/USBv1/usb_lld.c | 133 | ||||
-rw-r--r-- | os/hal/platforms/STM32/USBv1/usb_lld.h | 20 | ||||
-rw-r--r-- | os/hal/src/serial_usb.c | 91 | ||||
-rw-r--r-- | os/hal/src/usb.c | 107 | ||||
-rw-r--r-- | os/kernel/include/chthreads.h | 10 | ||||
-rw-r--r-- | os/kernel/src/chqueues.c | 23 | ||||
-rw-r--r-- | readme.txt | 8 | ||||
-rw-r--r-- | testhal/STM32F1xx/USB_CDC/main.c | 17 |
16 files changed, 254 insertions, 367 deletions
diff --git a/demos/ARM7-AT91SAM7S-FATFS-GCC/main.c b/demos/ARM7-AT91SAM7S-FATFS-GCC/main.c index c525cdc54..582135cca 100644 --- a/demos/ARM7-AT91SAM7S-FATFS-GCC/main.c +++ b/demos/ARM7-AT91SAM7S-FATFS-GCC/main.c @@ -129,23 +129,7 @@ static void cmd_mem(BaseChannel *chp, int argc, char *argv[]) { }
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
- static const char *states[] = {
- "READY",
- "CURRENT",
- "SUSPENDED",
- "WTSEM",
- "WTMTX",
- "WTCOND",
- "SLEEPING",
- "WTEXIT",
- "WTOREVT",
- "WTANDEVT",
- "SNDMSGQ",
- "SNDMSG",
- "WTMSG",
- "WTQUEUE",
- "FINAL"
- };
+ static const char *states[] = {THD_STATE_NAMES};
Thread *tp;
(void)argv;
diff --git a/demos/ARM7-AT91SAM7X-FATFS-GCC/main.c b/demos/ARM7-AT91SAM7X-FATFS-GCC/main.c index d761f2b2d..f9a53ae24 100644 --- a/demos/ARM7-AT91SAM7X-FATFS-GCC/main.c +++ b/demos/ARM7-AT91SAM7X-FATFS-GCC/main.c @@ -129,23 +129,7 @@ static void cmd_mem(BaseChannel *chp, int argc, char *argv[]) { }
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
- static const char *states[] = {
- "READY",
- "CURRENT",
- "SUSPENDED",
- "WTSEM",
- "WTMTX",
- "WTCOND",
- "SLEEPING",
- "WTEXIT",
- "WTOREVT",
- "WTANDEVT",
- "SNDMSGQ",
- "SNDMSG",
- "WTMSG",
- "WTQUEUE",
- "FINAL"
- };
+ static const char *states[] = {THD_STATE_NAMES};
Thread *tp;
(void)argv;
diff --git a/demos/ARMCM3-STM32F103-FATFS/main.c b/demos/ARMCM3-STM32F103-FATFS/main.c index a2bc4cf03..a41ea239d 100644 --- a/demos/ARMCM3-STM32F103-FATFS/main.c +++ b/demos/ARMCM3-STM32F103-FATFS/main.c @@ -117,23 +117,7 @@ static void cmd_mem(BaseChannel *chp, int argc, char *argv[]) { }
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
- static const char *states[] = {
- "READY",
- "CURRENT",
- "SUSPENDED",
- "WTSEM",
- "WTMTX",
- "WTCOND",
- "SLEEPING",
- "WTEXIT",
- "WTOREVT",
- "WTANDEVT",
- "SNDMSGQ",
- "SNDMSG",
- "WTMSG",
- "WTQUEUE",
- "FINAL"
- };
+ static const char *states[] = {THD_STATE_NAMES};
Thread *tp;
(void)argv;
diff --git a/demos/ARMCM3-STM32F103ZG-FATFS/main.c b/demos/ARMCM3-STM32F103ZG-FATFS/main.c index 258b1f007..0b9020dcf 100644 --- a/demos/ARMCM3-STM32F103ZG-FATFS/main.c +++ b/demos/ARMCM3-STM32F103ZG-FATFS/main.c @@ -194,23 +194,7 @@ static void cmd_mem(BaseChannel *chp, int argc, char *argv[]) { }
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
- static const char *states[] = {
- "READY",
- "CURRENT",
- "SUSPENDED",
- "WTSEM",
- "WTMTX",
- "WTCOND",
- "SLEEPING",
- "WTEXIT",
- "WTOREVT",
- "WTANDEVT",
- "SNDMSGQ",
- "SNDMSG",
- "WTMSG",
- "WTQUEUE",
- "FINAL"
- };
+ static const char *states[] = {THD_STATE_NAMES};
Thread *tp;
(void)argv;
diff --git a/demos/PPC-SPC563-GCC/main.c b/demos/PPC-SPC563-GCC/main.c index aa1b9fd7e..24b831770 100644 --- a/demos/PPC-SPC563-GCC/main.c +++ b/demos/PPC-SPC563-GCC/main.c @@ -44,23 +44,7 @@ static void cmd_mem(BaseChannel *chp, int argc, char *argv[]) { }
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
- static const char *states[] = {
- "READY",
- "CURRENT",
- "SUSPENDED",
- "WTSEM",
- "WTMTX",
- "WTCOND",
- "SLEEPING",
- "WTEXIT",
- "WTOREVT",
- "WTANDEVT",
- "SNDMSGQ",
- "SNDMSG",
- "WTMSG",
- "WTQUEUE",
- "FINAL"
- };
+ static const char *states[] = {THD_STATE_NAMES};
Thread *tp;
(void)argv;
diff --git a/demos/Posix-GCC/main.c b/demos/Posix-GCC/main.c index 543386a85..4904edec0 100644 --- a/demos/Posix-GCC/main.c +++ b/demos/Posix-GCC/main.c @@ -51,23 +51,7 @@ static void cmd_mem(BaseChannel *chp, int argc, char *argv[]) { }
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
- static const char *states[] = {
- "READY",
- "CURRENT",
- "SUSPENDED",
- "WTSEM",
- "WTMTX",
- "WTCOND",
- "SLEEPING",
- "WTEXIT",
- "WTOREVT",
- "WTANDEVT",
- "SNDMSGQ",
- "SNDMSG",
- "WTMSG",
- "WTQUEUE",
- "FINAL"
- };
+ static const char *states[] = {THD_STATE_NAMES};
Thread *tp;
(void)argv;
diff --git a/demos/Win32-MinGW/main.c b/demos/Win32-MinGW/main.c index a735dfa0c..d4cc554ce 100644 --- a/demos/Win32-MinGW/main.c +++ b/demos/Win32-MinGW/main.c @@ -49,23 +49,7 @@ static void cmd_mem(BaseChannel *chp, int argc, char *argv[]) { }
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
- static const char *states[] = {
- "READY",
- "CURRENT",
- "SUSPENDED",
- "WTSEM",
- "WTMTX",
- "WTCOND",
- "SLEEPING",
- "WTEXIT",
- "WTOREVT",
- "WTANDEVT",
- "SNDMSGQ",
- "SNDMSG",
- "WTMSG",
- "WTQUEUE",
- "FINAL"
- };
+ static const char *states[] = {THD_STATE_NAMES};
Thread *tp;
(void)argv;
diff --git a/os/hal/include/usb.h b/os/hal/include/usb.h index 884b11e8d..18842abd3 100644 --- a/os/hal/include/usb.h +++ b/os/hal/include/usb.h @@ -173,11 +173,6 @@ /** @} */
/**
- * @brief Returned by some functions to report a busy endpoint.
- */
-#define USB_ENDPOINT_BUSY ((size_t)0xFFFFFFFF)
-
-/**
* @name Endpoint types and settings
* @{
*/
@@ -363,6 +358,75 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp, #define usbGetReceiveStatusI(usbp, ep) ((usbp)->receiving & (1 << (ep)))
/**
+ * @brief Reads from a dedicated packet buffer.
+ * @pre In order to use this function he endpoint must have been
+ * initialized in packet mode.
+ * @note This function can be invoked both in thread and IRQ context.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[out] buf buffer where to copy the packet data
+ * @param[in] n maximum number of bytes to copy. This value must
+ * not exceed the maximum packet size for this endpoint.
+ * @return The received packet size regardless the specified
+ * @p n parameter.
+ * @retval 0 Zero size packet received.
+ *
+ * @special
+ */
+#define usbReadPacketBuffer(usbp, ep, buf, n) \
+ usb_lld_read_packet_buffer(usbp, ep, buf, n)
+
+/**
+ * @brief Writes to a dedicated packet buffer.
+ * @pre In order to use this function he endpoint must have been
+ * initialized in packet mode.
+ * @note This function can be invoked both in thread and IRQ context.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[in] buf buffer where to fetch the packet data
+ * @param[in] n maximum number of bytes to copy. This value must
+ * not exceed the maximum packet size for this endpoint.
+ *
+ * @special
+ */
+#define usbWritePacketBuffer(usbp, ep, buf, n) \
+ usb_lld_write_packet_buffer(usbp, ep, buf, n)
+
+/**
+ * @brief Prepares for a receive transaction on an OUT endpoint.
+ * @pre In order to use this function he endpoint must have been
+ * initialized in transaction mode.
+ * @post The endpoint is ready for @p usbStartReceiveI().
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[out] buf buffer where to copy the received data
+ * @param[in] n maximum number of bytes to copy
+ *
+ * @special
+ */
+#define usbPrepareReceive(usbp, ep, buf, n) \
+ usb_lld_prepare_receive(usbp, ep, buf, n)
+
+/**
+ * @brief Prepares for a transmit transaction on an IN endpoint.
+ * @pre In order to use this function he endpoint must have been
+ * initialized in transaction mode.
+ * @post The endpoint is ready for @p usbStartTransmitI().
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[in] buf buffer where to fetch the data to be transmitted
+ * @param[in] n maximum number of bytes to copy
+ *
+ * @special
+ */
+#define usbPrepareTransmit(usbp, ep, buf, n) \
+ usb_lld_prepare_transmit(usbp, ep, buf, n)
+
+/**
* @brief Returns the exact size of a receive transaction.
* @details The received size can be different from the size specified in
* @p usbStartReceiveI() because the last packet could have a size
@@ -417,7 +481,7 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp, * callback in order to read the received setup packet.
* @pre In order to use this function the endpoint must have been
* initialized as a control endpoint.
- * @post The endpoint is ready to accept another packet.
+ * @note This function can be invoked both in thread and IRQ context.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
@@ -511,14 +575,8 @@ extern "C" { const USBEndpointConfig *epcp);
void usbDisableEndpointsI(USBDriver *usbp);
void usbReadSetupI(USBDriver *usbp, usbep_t ep, uint8_t *buf);
- size_t usbReadPacketI(USBDriver *usbp, usbep_t ep,
- uint8_t *buf, size_t n);
- size_t usbWritePacketI(USBDriver *usbp, usbep_t ep,
- const uint8_t *buf, size_t n);
- bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep,
- uint8_t *buf, size_t n);
- bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep,
- const uint8_t *buf, size_t n);
+ bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep);
+ bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep);
bool_t usbStallReceiveI(USBDriver *usbp, usbep_t ep);
bool_t usbStallTransmitI(USBDriver *usbp, usbep_t ep);
void _usb_reset(USBDriver *usbp);
diff --git a/os/hal/platforms/STM32/USBv1/usb_lld.c b/os/hal/platforms/STM32/USBv1/usb_lld.c index 01bc50090..253f45197 100644 --- a/os/hal/platforms/STM32/USBv1/usb_lld.c +++ b/os/hal/platforms/STM32/USBv1/usb_lld.c @@ -109,58 +109,6 @@ static uint32_t pm_alloc(USBDriver *usbp, size_t size) { return next;
}
-/**
- * @brief Copies a packet from memory into a packet buffer.
- *
- * @param[in] ep endpoint number
- * @param[in] buf buffer where to fetch the endpoint data
- * @param[in] n maximum number of bytes to copy
- */
-static void write_packet(usbep_t ep, const uint8_t *buf, size_t n){
- uint32_t *pmap;
- stm32_usb_descriptor_t *udp;
- size_t count;
-
- udp = USB_GET_DESCRIPTOR(ep);
- pmap = USB_ADDR2PTR(udp->TXADDR);
- udp->TXCOUNT = n;
- count = (n + 1) / 2;
- while (count) {
- *pmap++ = *(uint16_t *)buf;
- buf += 2;
- count--;
- }
- EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID);
-}
-
-/**
- * @brief Copies a packet from a packet buffer into memory.
- *
- * @param[in] ep endpoint number
- * @param[in] buf buffer where to copy the endpoint data
- * @param[in] n maximum number of bytes to copy
- * @return The packet size.
- * @retval 0 Special case, zero sized packet.
- */
-static size_t read_packet(usbep_t ep, uint8_t *buf, size_t n){
- uint32_t *pmap;
- stm32_usb_descriptor_t *udp;
- size_t count;
-
- udp = USB_GET_DESCRIPTOR(ep);
- pmap = USB_ADDR2PTR(udp->RXADDR);
- count = udp->RXCOUNT & RXCOUNT_COUNT_MASK;
- if (n > count)
- n = count;
- count = (n + 1) / 2;
- while (count) {
- *(uint16_t *)buf = (uint16_t)*pmap++;
- buf += 2;
- count--;
- }
- return n;
-}
-
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
@@ -257,7 +205,8 @@ CH_IRQ_HANDLER(Vector90) { n = epcp->in_maxsize;
else
n = epcp->in_state->txsize;
- write_packet(ep, epcp->in_state->txbuf, n);
+ usb_lld_write_packet_buffer(usbp, ep, epcp->in_state->txbuf, n);
+ usb_lld_start_in(usbp, ep);
}
else {
/* Transfer completed, invokes the callback.*/
@@ -279,7 +228,10 @@ CH_IRQ_HANDLER(Vector90) { }
else {
/* Transaction mode.*/
- n = read_packet(ep, epcp->out_state->rxbuf, epcp->out_state->rxsize);
+ n = usb_lld_read_packet_buffer(usbp, ep,
+ epcp->out_state->rxbuf,
+ epcp->out_state->rxsize);
+ usb_lld_start_out(usbp, ep);
epcp->out_state->rxbuf += n;
epcp->out_state->rxcnt += n;
epcp->out_state->rxsize -= n;
@@ -569,14 +521,13 @@ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { *(uint16_t *)buf = (uint16_t)*pmap++;
buf += 2;
}
- EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID);
}
/**
- * @brief Reads a packet from the dedicated packet buffer.
+ * @brief Reads from a dedicated packet buffer.
* @pre In order to use this function he endpoint must have been
* initialized in packet mode.
- * @post The endpoint is ready to accept another packet.
+ * @note This function can be invoked both in thread and IRQ context.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
@@ -589,8 +540,8 @@ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { *
* @notapi
*/
-size_t usb_lld_read_packet(USBDriver *usbp, usbep_t ep,
- uint8_t *buf, size_t n) {
+size_t usb_lld_read_packet_buffer(USBDriver *usbp, usbep_t ep,
+ uint8_t *buf, size_t n) {
uint32_t *pmap;
stm32_usb_descriptor_t *udp;
size_t count;
@@ -607,15 +558,14 @@ size_t usb_lld_read_packet(USBDriver *usbp, usbep_t ep, buf += 2;
n--;
}
- EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID);
return count;
}
/**
- * @brief Writes a packet to the dedicated packet buffer.
+ * @brief Writes to a dedicated packet buffer.
* @pre In order to use this function he endpoint must have been
* initialized in packet mode.
- * @post The endpoint is ready to transmit the packet.
+ * @note This function can be invoked both in thread and IRQ context.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
@@ -625,8 +575,8 @@ size_t usb_lld_read_packet(USBDriver *usbp, usbep_t ep, *
* @notapi
*/
-void usb_lld_write_packet(USBDriver *usbp, usbep_t ep,
- const uint8_t *buf, size_t n) {
+void usb_lld_write_packet_buffer(USBDriver *usbp, usbep_t ep,
+ const uint8_t *buf, size_t n) {
uint32_t *pmap;
stm32_usb_descriptor_t *udp;
@@ -640,21 +590,20 @@ void usb_lld_write_packet(USBDriver *usbp, usbep_t ep, buf += 2;
n--;
}
- EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID);
}
/**
- * @brief Starts a receive operation on an OUT endpoint.
+ * @brief Prepares for a receive operation.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
- * @param[out] buf buffer where to copy the endpoint data
- * @param[in] n maximum number of bytes to copy in the buffer
+ * @param[out] buf buffer where to copy the received data
+ * @param[in] n maximum number of bytes to copy
*
* @notapi
*/
-void usb_lld_start_out(USBDriver *usbp, usbep_t ep,
- uint8_t *buf, size_t n) {
+void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep,
+ uint8_t *buf, size_t n) {
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
osp->rxbuf = buf;
@@ -665,21 +614,20 @@ void usb_lld_start_out(USBDriver *usbp, usbep_t ep, else
osp->rxpkts = (uint16_t)((n + usbp->epc[ep]->out_maxsize - 1) /
usbp->epc[ep]->out_maxsize);
- EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID);
}
/**
- * @brief Starts a transmit operation on an IN endpoint.
+ * @brief Prepares for a transmit operation.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
- * @param[in] buf buffer where to fetch the endpoint data
+ * @param[in] buf buffer where to fetch the data to be transmitted
* @param[in] n maximum number of bytes to copy
*
* @notapi
*/
-void usb_lld_start_in(USBDriver *usbp, usbep_t ep,
- const uint8_t *buf, size_t n) {
+void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
+ const uint8_t *buf, size_t n) {
USBInEndpointState *isp = usbp->epc[ep]->in_state;
isp->txbuf = buf;
@@ -687,7 +635,39 @@ void usb_lld_start_in(USBDriver *usbp, usbep_t ep, isp->txcnt = 0;
if (n > (size_t)usbp->epc[ep]->in_maxsize)
n = (size_t)usbp->epc[ep]->in_maxsize;
- write_packet(ep, buf, n);
+ usb_lld_write_packet_buffer(usbp, ep, buf, n);
+}
+
+/**
+ * @brief Starts a receive operation on an OUT endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ *
+ * @notapi
+ */
+void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+
+ EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID);
+}
+
+/**
+ * @brief Starts a transmit operation on an IN endpoint.
+ *
+ * @param[in] usbp pointer to the @p USBDriver object
+ * @param[in] ep endpoint number
+ * @param[in] buf buffer where to fetch the endpoint data
+ * @param[in] n maximum number of bytes to copy
+ *
+ * @notapi
+ */
+void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
+
+ (void)usbp;
+
+ EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID);
}
/**
@@ -701,6 +681,7 @@ void usb_lld_start_in(USBDriver *usbp, usbep_t ep, void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) {
(void)usbp;
+
EPR_SET_STAT_RX(ep, EPR_STAT_RX_STALL);
}
diff --git a/os/hal/platforms/STM32/USBv1/usb_lld.h b/os/hal/platforms/STM32/USBv1/usb_lld.h index 47160af56..0ee9fd6c2 100644 --- a/os/hal/platforms/STM32/USBv1/usb_lld.h +++ b/os/hal/platforms/STM32/USBv1/usb_lld.h @@ -375,16 +375,18 @@ extern "C" { usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep);
usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep);
void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf);
- size_t usb_lld_read_packet(USBDriver *usbp, usbep_t ep,
- uint8_t *buf, size_t n);
- void usb_lld_write_packet(USBDriver *usbp, usbep_t ep,
- const uint8_t *buf, size_t n);
- void usb_lld_start_out(USBDriver *usbp, usbep_t ep,
- uint8_t *buf, size_t n);
- void usb_lld_start_in(USBDriver *usbp, usbep_t ep,
- const uint8_t *buf, size_t n);
- void usb_lld_stall_in(USBDriver *usbp, usbep_t ep);
+ size_t usb_lld_read_packet_buffer(USBDriver *usbp, usbep_t ep,
+ uint8_t *buf, size_t n);
+ void usb_lld_write_packet_buffer(USBDriver *usbp, usbep_t ep,
+ const uint8_t *buf, size_t n);
+ void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep,
+ uint8_t *buf, size_t n);
+ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep,
+ const uint8_t *buf, size_t n);
+ void usb_lld_start_out(USBDriver *usbp, usbep_t ep);
+ void usb_lld_start_in(USBDriver *usbp, usbep_t ep);
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep);
+ void usb_lld_stall_in(USBDriver *usbp, usbep_t ep);
void usb_lld_clear_out(USBDriver *usbp, usbep_t ep);
void usb_lld_clear_in(USBDriver *usbp, usbep_t ep);
#ifdef __cplusplus
diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 16822502a..ea434b197 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -118,21 +118,26 @@ static const struct SerialUSBDriverVMT vmt = { */
static void inotify(GenericQueue *qp) {
SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_wrptr;
- size_t n;
/* Writes to the input queue can only happen when the queue has been
emptied, then a whole packet is loaded in the queue.*/
- if (chIQIsEmptyI(&sdup->iqueue)) {
-
- n = usbReadPacketI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP,
- sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE);
- if (n != USB_ENDPOINT_BUSY) {
- chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE);
- sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer;
- sdup->iqueue.q_counter = n;
- while (notempty(&sdup->iqueue.q_waiting))
- chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK;
- }
+ if (!usbGetReceiveStatusI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP) &&
+ chIQIsEmptyI(&sdup->iqueue)) {
+ chSysUnlock();
+
+ /* Unlocked to make the potentially long read operation preemptable.*/
+ size_t n = usbReadPacketBuffer(sdup->config->usbp,
+ USB_CDC_DATA_AVAILABLE_EP,
+ sdup->iqueue.q_buffer,
+ SERIAL_USB_BUFFERS_SIZE);
+
+ chSysLock();
+ usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP);
+ chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE);
+ sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer;
+ sdup->iqueue.q_counter = n;
+ while (notempty(&sdup->iqueue.q_waiting))
+ chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK;
}
}
@@ -141,14 +146,20 @@ static void inotify(GenericQueue *qp) { */
static void onotify(GenericQueue *qp) {
SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_rdptr;
- size_t w, n;
+ size_t n;
/* If there is any data in the output queue then it is sent within a
single packet and the queue is emptied.*/
n = chOQGetFullI(&sdup->oqueue);
- w = usbWritePacketI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP,
- sdup->oqueue.q_buffer, n);
- if (w != USB_ENDPOINT_BUSY) {
+ if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP)) {
+ chSysUnlock();
+
+ /* Unlocked to make the potentially long write operation preemptable.*/
+ usbWritePacketBuffer(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP,
+ sdup->oqueue.q_buffer, n);
+
+ chSysLock();
+ usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP);
chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY);
sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer;
sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue);
@@ -285,21 +296,27 @@ bool_t sduRequestsHook(USBDriver *usbp) { */
void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
SerialUSBDriver *sdup = usbp->param;
- size_t n, w;
+ size_t n;
chSysLockFromIsr();
/* If there is any data in the output queue then it is sent within a
single packet and the queue is emptied.*/
n = chOQGetFullI(&sdup->oqueue);
if (n > 0) {
- w = usbWritePacketI(usbp, ep, sdup->oqueue.q_buffer, n);
- if (w != USB_ENDPOINT_BUSY) {
- chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY);
- sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer;
- sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue);
- while (notempty(&sdup->oqueue.q_waiting))
- chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK;
- }
+ /* The endpoint cannot be busy, we are in the context of the callback,
+ so it is safe to transmit without a check.*/
+ chSysUnlockFromIsr();
+
+ /* Unlocked to make the potentially long write operation preemptable.*/
+ usbWritePacketBuffer(usbp, ep, sdup->oqueue.q_buffer, n);
+
+ chSysLockFromIsr();
+ usbStartTransmitI(usbp, ep);
+ chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY);
+ sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer;
+ sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue);
+ while (notempty(&sdup->oqueue.q_waiting))
+ chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK;
}
chSysUnlockFromIsr();
}
@@ -319,17 +336,23 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { /* Writes to the input queue can only happen when the queue has been
emptied, then a whole packet is loaded in the queue.*/
if (chIQIsEmptyI(&sdup->iqueue)) {
+ /* The endpoint cannot be busy, we are in the context of the callback,
+ so a packet is in the buffer for sure.*/
size_t n;
- n = usbReadPacketI(usbp, ep, sdup->iqueue.q_buffer,
- SERIAL_USB_BUFFERS_SIZE);
- if (n != USB_ENDPOINT_BUSY) {
- chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE);
- sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer;
- sdup->iqueue.q_counter = n;
- while (notempty(&sdup->iqueue.q_waiting))
- chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK;
- }
+ chSysUnlockFromIsr();
+
+ /* Unlocked to make the potentially long write operation preemptable.*/
+ n = usbReadPacketBuffer(usbp, ep, sdup->iqueue.q_buffer,
+ SERIAL_USB_BUFFERS_SIZE);
+
+ chSysLockFromIsr();
+ usbStartReceiveI(usbp, ep);
+ chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE);
+ sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer;
+ sdup->iqueue.q_counter = n;
+ while (notempty(&sdup->iqueue.q_waiting))
+ chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK;
}
chSysUnlockFromIsr();
}
diff --git a/os/hal/src/usb.c b/os/hal/src/usb.c index 44a772ab1..30919580c 100644 --- a/os/hal/src/usb.c +++ b/os/hal/src/usb.c @@ -309,7 +309,7 @@ void usbInitEndpointI(USBDriver *usbp, usbep_t ep, chDbgCheck((usbp != NULL) && (epcp != NULL), "usbInitEndpointI");
chDbgAssert(usbp->state == USB_ACTIVE,
"usbEnableEndpointI(), #1", "invalid state");
- chDbgAssert(usbp->epc[ep] != NULL,
+ chDbgAssert(usbp->epc[ep] == NULL,
"usbEnableEndpointI(), #2", "already initialized");
/* Logically enabling the endpoint in the USBDriver structure.*/
@@ -352,126 +352,54 @@ void usbDisableEndpointsI(USBDriver *usbp) { }
/**
- * @brief Reads a packet from the dedicated packet buffer.
- * @pre In order to use this function he endpoint must have been
- * initialized in packet mode.
- * @post The endpoint is ready to accept another packet.
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- * @param[out] buf buffer where to copy the packet data
- * @param[in] n maximum number of bytes to copy. This value must
- * not exceed the maximum packet size for this endpoint.
- * @return The received packet size regardless the specified
- * @p n parameter.
- * @retval USB_ENDPOINT_BUSY Endpoint busy receiving.
- * @retval 0 Zero size packet received.
- *
- * @iclass
- */
-size_t usbReadPacketI(USBDriver *usbp, usbep_t ep,
- uint8_t *buf, size_t n) {
-
- chDbgCheckClassI();
- chDbgCheck((usbp != NULL) && (buf != NULL), "usbReadPacketI");
-
- if (usbGetReceiveStatusI(usbp, ep))
- return USB_ENDPOINT_BUSY;
-
- usbp->receiving |= (1 << ep);
- return usb_lld_read_packet(usbp, ep, buf, n);;
-}
-
-/**
- * @brief Writes a packet to the dedicated packet buffer.
- * @pre In order to use this function he endpoint must have been
- * initialized in packet mode.
- * @post The endpoint is ready to transmit the packet.
- *
- * @param[in] usbp pointer to the @p USBDriver object
- * @param[in] ep endpoint number
- * @param[in] buf buffer where to fetch the packet data
- * @param[in] n maximum number of bytes to copy. This value must
- * not exceed the maximum packet size for this endpoint.
- * @return The operation status.
- * @retval USB_ENDPOINT_BUSY Endpoint busy transmitting.
- * @retval 0 Operation complete.
- *
- * @iclass
- */
-size_t usbWritePacketI(USBDriver *usbp, usbep_t ep,
- const uint8_t *buf, size_t n) {
-
- chDbgCheckClassI();
- chDbgCheck((usbp != NULL) && (buf != NULL), "usbWritePacketI");
-
- if (usbGetTransmitStatusI(usbp, ep))
- return USB_ENDPOINT_BUSY;
-
- usbp->transmitting |= (1 << ep);
- usb_lld_write_packet(usbp, ep, buf, n);
- return 0;
-}
-
-/**
* @brief Starts a receive transaction on an OUT endpoint.
- * @pre In order to use this function he endpoint must have been
- * initialized in transaction mode.
* @post The endpoint callback is invoked when the transfer has been
* completed.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
- * @param[out] buf buffer where to copy the received data
- * @param[in] n maximum number of bytes to copy
* @return The operation status.
* @retval FALSE Operation started successfully.
* @retval TRUE Endpoint busy, operation not started.
*
* @iclass
*/
-bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep,
- uint8_t *buf, size_t n) {
+bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep) {
chDbgCheckClassI();
- chDbgCheck((usbp != NULL) && (buf != NULL), "usbStartReceiveI");
+ chDbgCheck(usbp != NULL, "usbStartReceiveI");
if (usbGetReceiveStatusI(usbp, ep))
return TRUE;
usbp->receiving |= (1 << ep);
- usb_lld_start_out(usbp, ep, buf, n);
+ usb_lld_start_out(usbp, ep);
return FALSE;
}
/**
* @brief Starts a transmit transaction on an IN endpoint.
- * @pre In order to use this function he endpoint must have been
- * initialized in transaction mode.
* @post The endpoint callback is invoked when the transfer has been
* completed.
*
* @param[in] usbp pointer to the @p USBDriver object
* @param[in] ep endpoint number
- * @param[in] buf buffer where to fetch the data to be transmitted
- * @param[in] n maximum number of bytes to copy
* @return The operation status.
* @retval FALSE Operation started successfully.
* @retval TRUE Endpoint busy, operation not started.
*
* @iclass
*/
-bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep,
- const uint8_t *buf, size_t n) {
+bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep) {
chDbgCheckClassI();
- chDbgCheck((usbp != NULL) && (buf != NULL), "usbStartTransmitI");
+ chDbgCheck(usbp != NULL, "usbStartTransmitI");
if (usbGetTransmitStatusI(usbp, ep))
return TRUE;
usbp->transmitting |= (1 << ep);
- usb_lld_start_in(usbp, ep, buf, n);
+ usb_lld_start_in(usbp, ep);
return FALSE;
}
@@ -597,13 +525,15 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) { if (usbp->ep0n > 0) {
/* Starts the transmit phase.*/
usbp->ep0state = USB_EP0_TX;
- usb_lld_start_in(usbp, 0, usbp->ep0next, usbp->ep0n);
+ usb_lld_prepare_transmit(usbp, 0, usbp->ep0next, usbp->ep0n);
+ usb_lld_start_in(usbp, 0);
}
else {
/* No transmission phase, directly receiving the zero sized status
packet.*/
usbp->ep0state = USB_EP0_WAITING_STS;
- usb_lld_start_out(usbp, 0, NULL, 0);
+ usb_lld_prepare_receive(usbp, 0, NULL, 0);
+ usb_lld_start_out(usbp, 0);
}
}
else {
@@ -611,13 +541,15 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) { if (usbp->ep0n > 0) {
/* Starts the receive phase.*/
usbp->ep0state = USB_EP0_RX;
- usb_lld_start_out(usbp, 0, usbp->ep0next, usbp->ep0n);
+ usb_lld_prepare_receive(usbp, 0, usbp->ep0next, usbp->ep0n);
+ usb_lld_start_out(usbp, 0);
}
else {
/* No receive phase, directly sending the zero sized status
packet.*/
usbp->ep0state = USB_EP0_SENDING_STS;
- usb_lld_start_in(usbp, 0, NULL, 0);
+ usb_lld_prepare_transmit(usbp, 0, NULL, 0);
+ usb_lld_start_in(usbp, 0);
}
}
}
@@ -644,13 +576,15 @@ void _usb_ep0in(USBDriver *usbp, usbep_t ep) { transmitted.*/
if ((usbp->ep0n < max) &&
((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0)) {
- usb_lld_start_in(usbp, 0, NULL, 0);
+ usb_lld_prepare_transmit(usbp, 0, NULL, 0);
+ usb_lld_start_in(usbp, 0);
return;
}
/* Transmit phase over, receiving the zero sized status packet.*/
usbp->ep0state = USB_EP0_WAITING_STS;
- usb_lld_start_out(usbp, 0, NULL, 0);
+ usb_lld_prepare_receive(usbp, 0, NULL, 0);
+ usb_lld_start_out(usbp, 0);
return;
case USB_EP0_SENDING_STS:
/* Status packet sent, invoking the callback if defined.*/
@@ -687,7 +621,8 @@ void _usb_ep0out(USBDriver *usbp, usbep_t ep) { case USB_EP0_RX:
/* Receive phase over, sending the zero sized status packet.*/
usbp->ep0state = USB_EP0_SENDING_STS;
- usb_lld_start_in(usbp, 0, NULL, 0);
+ usb_lld_prepare_transmit(usbp, 0, NULL, 0);
+ usb_lld_start_in(usbp, 0);
return;
case USB_EP0_WAITING_STS:
/* Status packet received, it must be zero sized, invoking the callback
diff --git a/os/kernel/include/chthreads.h b/os/kernel/include/chthreads.h index 582b4e1e1..5848d5643 100644 --- a/os/kernel/include/chthreads.h +++ b/os/kernel/include/chthreads.h @@ -51,6 +51,16 @@ #define THD_STATE_WTMSG 12 /**< @brief Waiting for a message. */
#define THD_STATE_WTQUEUE 13 /**< @brief Waiting on an I/O queue. */
#define THD_STATE_FINAL 14 /**< @brief Thread terminated. */
+
+/**
+ * @brief Thread states as array of strings.
+ * @details Each element in an array initialized with this macro can be
+ * indexed using the numeric thread state values.
+ */
+#define THD_STATE_NAMES \
+ "READY", "CURRENT", "SUSPENDED", "WTSEM", "WTMTX", "WTCOND", "SLEEPING", \
+ "WTEXIT", "WTOREVT", "WTANDEVT", "SNDMSGQ", "SNDMSG", "WTMSG", "WTQUEUE", \
+ "FINAL"
/** @} */
/**
diff --git a/os/kernel/src/chqueues.c b/os/kernel/src/chqueues.c index cf3d21732..b32ccf803 100644 --- a/os/kernel/src/chqueues.c +++ b/os/kernel/src/chqueues.c @@ -152,9 +152,8 @@ msg_t chIQPutI(InputQueue *iqp, uint8_t b) { * @details This function reads a byte value from an input queue. If the queue
* is empty then the calling thread is suspended until a byte arrives
* in the queue or a timeout occurs.
- * @note The callback is invoked if the queue is empty before entering the
- * @p THD_STATE_WTQUEUE state in order to solicit the low level to
- * start queue filling.
+ * @note The callback is invoked before reading the character from the
+ * buffer or before entering the state @p THD_STATE_WTQUEUE.
*
* @param[in] iqp pointer to an @p InputQueue structure
* @param[in] time the number of ticks before the operation timeouts,
@@ -172,12 +171,11 @@ msg_t chIQGetTimeout(InputQueue *iqp, systime_t time) { uint8_t b;
chSysLock();
+ if (iqp->q_notify)
+ iqp->q_notify(iqp);
+
while (chIQIsEmptyI(iqp)) {
msg_t msg;
-
- if (iqp->q_notify)
- iqp->q_notify(iqp);
-
if ((msg = qwait((GenericQueue *)iqp, time)) < Q_OK) {
chSysUnlock();
return msg;
@@ -201,9 +199,8 @@ msg_t chIQGetTimeout(InputQueue *iqp, systime_t time) { * been reset.
* @note The function is not atomic, if you need atomicity it is suggested
* to use a semaphore or a mutex for mutual exclusion.
- * @note The callback is invoked if the queue is empty before entering the
- * @p THD_STATE_WTQUEUE state in order to solicit the low level to
- * start queue filling.
+ * @note The callback is invoked before reading each character from the
+ * buffer or before entering the state @p THD_STATE_WTQUEUE.
*
* @param[in] iqp pointer to an @p InputQueue structure
* @param[out] bp pointer to the data buffer
@@ -227,10 +224,10 @@ size_t chIQReadTimeout(InputQueue *iqp, uint8_t *bp, chSysLock();
while (TRUE) {
- while (chIQIsEmptyI(iqp)) {
- if (nfy)
- nfy(iqp);
+ if (nfy)
+ nfy(iqp);
+ while (chIQIsEmptyI(iqp)) {
if (qwait((GenericQueue *)iqp, time) != Q_OK) {
chSysUnlock();
return r;
diff --git a/readme.txt b/readme.txt index e6a0d72d8..2b4eb54ed 100644 --- a/readme.txt +++ b/readme.txt @@ -76,6 +76,11 @@ *** 2.3.4 ***
- FIX: Fixed broken TIM8 support in STM32 PWM driver (bug 3418620).
- FIX: Fixed halconf.h file corrupted in some STM32 demos (bug 3418626).
+- NEW: Updated USB driver model and STM32 implementation. Updated the
+ SERIAL_USB driver to match the new API. Fixed several problems in
+ both drivers.
+- NEW: Added a macro THD_STATE_NAMES to chthreads.h. This macro is an
+ initializer for string arrays containing thread state names.
- NEW: Added memory copy functionality to the STM32 DMA driver.
- NEW: Implemented new makefile system for ARM GCC ports, now objects,
listings and output files are generated into a "build" directory and not
@@ -84,6 +89,9 @@ rebuild if touched.
- NEW: Updated AVR demos to use the new PAL driver.
- NEW: Added Keil build files to the STM32L-Discovery demo.
+- CHANGE: Now the callback associated to input queues is invoked before
+ reading each character. Previously it was invoked only before going
+ to sleep into the THD_STATE_WTQUEUE state.
- CHANGE: Moved the STM32 DMA helper drivers files under the sub-family
specific directories because documentation issues.
diff --git a/testhal/STM32F1xx/USB_CDC/main.c b/testhal/STM32F1xx/USB_CDC/main.c index 601b6ce0b..2c46eb11b 100644 --- a/testhal/STM32F1xx/USB_CDC/main.c +++ b/testhal/STM32F1xx/USB_CDC/main.c @@ -332,22 +332,7 @@ static void cmd_mem(BaseChannel *chp, int argc, char *argv[]) { }
static void cmd_threads(BaseChannel *chp, int argc, char *argv[]) {
- static const char *states[] = {
- "READY",
- "CURRENT",
- "SUSPENDED",
- "WTSEM",
- "WTMTX",
- "WTCOND",
- "SLEEPING",
- "WTEXIT",
- "WTOREVT",
- "WTANDEVT",
- "SNDMSGQ",
- "SNDMSG",
- "WTMSG",
- "FINAL"
- };
+ static const char *states[] = {THD_STATE_NAMES};
Thread *tp;
(void)argv;
|