From 77934792d53efe99678286bab123c42c546478a7 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Wed, 9 Feb 2011 16:36:49 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2722 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- boards/GENERIC_SPC563/board.h | 2 +- os/hal/include/usb.h | 13 +++++-- os/hal/platforms/SPC56x/hal_lld.h | 4 +-- os/hal/platforms/STM32/usb_lld.c | 71 ++++++++++++++++++++++++++++++++++++ os/hal/platforms/STM32/usb_lld.h | 4 +++ os/hal/src/serial_usb.c | 21 +++++------ os/hal/src/usb.c | 76 +++++++++++++++++++++++++++++++++++---- 7 files changed, 169 insertions(+), 22 deletions(-) diff --git a/boards/GENERIC_SPC563/board.h b/boards/GENERIC_SPC563/board.h index 53c1140ce..0c840175f 100644 --- a/boards/GENERIC_SPC563/board.h +++ b/boards/GENERIC_SPC563/board.h @@ -34,7 +34,7 @@ * Board frequencies. */ #if !defined(EXTCLK) -#define EXTCLK 8000000 +#define EXTCLK 12000000 #endif /* diff --git a/os/hal/include/usb.h b/os/hal/include/usb.h index 26c701f52..c6c5d57cf 100644 --- a/os/hal/include/usb.h +++ b/os/hal/include/usb.h @@ -76,6 +76,11 @@ #define USB_EARLY_SET_ADDRESS 0 #define USB_LATE_SET_ADDRESS 1 +/** + * @brief Returned by some functions to report a busy endpoint. + */ +#define USB_ENDPOINT_BUSY ((size_t)0xFFFFFFFF) + /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ @@ -233,7 +238,7 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp, * @param[in] ep endpoint number * @return The operation status. * @retval FALSE Endpoint ready. - * @retval TRUE Endpoint busy. + * @retval TRUE Endpoint transmitting. * * @iclass */ @@ -246,7 +251,7 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp, * @param[in] ep endpoint number * @return The operation status. * @retval FALSE Endpoint ready. - * @retval TRUE Endpoint busy. + * @retval TRUE Endpoint receiving. * * @iclass */ @@ -282,6 +287,10 @@ extern "C" { void usbInitEndpointI(USBDriver *usbp, usbep_t ep, USBEndpointState *epp, const USBEndpointConfig *epcp); void usbDisableEndpointsI(USBDriver *usbp); + 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, diff --git a/os/hal/platforms/SPC56x/hal_lld.h b/os/hal/platforms/SPC56x/hal_lld.h index c61089a38..13dc9a267 100644 --- a/os/hal/platforms/SPC56x/hal_lld.h +++ b/os/hal/platforms/SPC56x/hal_lld.h @@ -112,7 +112,7 @@ * @note The effective divider factor is this value plus one. */ #if !defined(SPC563_CLK_PREDIV) || defined(__DOXYGEN__) -#define SPC563_CLK_PREDIV 0 +#define SPC563_CLK_PREDIV 2 #endif /** @@ -120,7 +120,7 @@ * @note Must be in range 32...96. */ #if !defined(SPC563_CLK_MFD) || defined(__DOXYGEN__) -#define SPC563_CLK_MFD 40 +#define SPC563_CLK_MFD 80 #endif /** diff --git a/os/hal/platforms/STM32/usb_lld.c b/os/hal/platforms/STM32/usb_lld.c index a95baf45f..62e7caa82 100644 --- a/os/hal/platforms/STM32/usb_lld.c +++ b/os/hal/platforms/STM32/usb_lld.c @@ -482,6 +482,77 @@ usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) { } } +/** + * @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 0 Zero size packet received. + * + * @notapi + */ +size_t usb_lld_read_packet(USBDriver *usbp, usbep_t ep, + uint8_t *buf, size_t n) { + uint32_t *pmap; + stm32_usb_descriptor_t *udp; + size_t count; + + (void)usbp; + udp = USB_GET_DESCRIPTOR(ep); + pmap = USB_ADDR2PTR(udp->RXADDR); + count = udp->RXCOUNT & RXCOUNT_COUNT_MASK; + if (n > count) + n = count; + n = (n + 1) / 2; + while (n > 0) { + *(uint16_t *)buf = (uint16_t)*pmap++; + buf += 2; + n--; + } + EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); + return count; +} + +/** + * @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. + * + * @notapi + */ +void usb_lld_write_packet(USBDriver *usbp, usbep_t ep, + const uint8_t *buf, size_t n) { + uint32_t *pmap; + stm32_usb_descriptor_t *udp; + + (void)usbp; + udp = USB_GET_DESCRIPTOR(ep); + pmap = USB_ADDR2PTR(udp->TXADDR); + udp->TXCOUNT = n; + n = (n + 1) / 2; + while (n > 0) { + *pmap++ = *(uint16_t *)buf; + buf += 2; + n--; + } + EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID); +} + /** * @brief Starts a receive operation on an OUT endpoint. * diff --git a/os/hal/platforms/STM32/usb_lld.h b/os/hal/platforms/STM32/usb_lld.h index d1e3169c2..6d131796e 100644 --- a/os/hal/platforms/STM32/usb_lld.h +++ b/os/hal/platforms/STM32/usb_lld.h @@ -333,6 +333,10 @@ extern "C" { void usb_lld_disable_endpoints(USBDriver *usbp); usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep); usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep); + 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, diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 60976eca2..29aec2650 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -119,9 +119,9 @@ static void inotify(GenericQueue *qp) { emptied, then a whole packet is loaded in the queue.*/ if (chIQIsEmptyI(&sdup->iqueue)) { - n = usbReadI(sdup->config->usbp, sdup->config->data_available_ep, - sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE); - if (n > 0) { + n = usbReadPacketI(sdup->config->usbp, sdup->config->data_available_ep, + sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE); + if (n != USB_ENDPOINT_BUSY) { sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; chSemSetCounterI(&sdup->iqueue.q_sem, n); } @@ -137,9 +137,9 @@ static void onotify(GenericQueue *qp) { /* If there is any data in the output queue then it is sent within a single packet and the queue is emptied.*/ - n = usbWriteI(sdup->config->usbp, sdup->config->data_request_ep, - sdup->oqueue.q_buffer, chOQGetFullI(&sdup->oqueue)); - if (n > 0) { + n = usbWritePacketI(sdup->config->usbp, sdup->config->data_request_ep, + sdup->oqueue.q_buffer, chOQGetFullI(&sdup->oqueue)); + if (n != USB_ENDPOINT_BUSY) { sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; chSemSetCounterI(&sdup->oqueue.q_sem, SERIAL_USB_BUFFERS_SIZE); } @@ -278,8 +278,8 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { single packet and the queue is emptied.*/ n = chOQGetFullI(&sdup->oqueue); if (n > 0) { - n = usbWriteI(usbp, ep, sdup->oqueue.q_buffer, n); - if (n > 0) { + n = usbWritePacketI(usbp, ep, sdup->oqueue.q_buffer, n); + if (n != USB_ENDPOINT_BUSY) { sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; chSemSetCounterI(&sdup->oqueue.q_sem, SERIAL_USB_BUFFERS_SIZE); chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); @@ -302,8 +302,9 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { if (chIQIsEmptyI(&sdup->iqueue)) { size_t n; - n = usbReadI(usbp, ep, sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE); - if (n > 0) { + n = usbReadPacketI(usbp, ep, sdup->iqueue.q_buffer, + SERIAL_USB_BUFFERS_SIZE); + if (n != USB_ENDPOINT_BUSY) { sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; chSemSetCounterI(&sdup->iqueue.q_sem, n); chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); diff --git a/os/hal/src/usb.c b/os/hal/src/usb.c index d0db0ed5c..afec3c645 100644 --- a/os/hal/src/usb.c +++ b/os/hal/src/usb.c @@ -337,16 +337,74 @@ void usbDisableEndpointsI(USBDriver *usbp) { usb_lld_disable_endpoints(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) { + + if (usbp->ep[ep]->receiving) + return USB_ENDPOINT_BUSY; + + 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) { + + if (usbp->ep[ep]->transmitting) + return USB_ENDPOINT_BUSY; + + usb_lld_write_packet(usbp, ep, buf, n); + return 0; +} + /** * @brief Starts a receive operation 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 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 * @return The operation status. - * @retval FALSE Receive operation started. - * @retval TRUE Endpoint already receiving. + * @retval FALSE Operation complete. + * @retval TRUE Endpoint busy receiving. * * @iclass */ @@ -362,14 +420,18 @@ bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep, /** * @brief Starts a transmit operation 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 endpoint data + * @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 Transmit operation started. - * @retval TRUE Endpoint already transmitting. + * @retval FALSE Operation complete. + * @retval TRUE Endpoint busy transmitting. * * @iclass */ -- cgit v1.2.3