diff options
Diffstat (limited to 'os/hal/platforms/STM32')
-rw-r--r-- | os/hal/platforms/STM32/usb_lld.c | 112 | ||||
-rw-r--r-- | os/hal/platforms/STM32/usb_lld.h | 27 |
2 files changed, 102 insertions, 37 deletions
diff --git a/os/hal/platforms/STM32/usb_lld.c b/os/hal/platforms/STM32/usb_lld.c index e1ba15de5..a95baf45f 100644 --- a/os/hal/platforms/STM32/usb_lld.c +++ b/os/hal/platforms/STM32/usb_lld.c @@ -58,11 +58,12 @@ static USBEndpointState ep0state; * @brief EP0 initialization structure.
*/
static const USBEndpointConfig ep0config = {
+ EP_TYPE_CTRL,
_usb_ep0in,
_usb_ep0out,
0x40,
0x40,
- EPR_EP_TYPE_CONTROL | EPR_STAT_TX_NAK | EPR_STAT_RX_VALID,
+ 0,
0x40,
0x80
};
@@ -178,50 +179,63 @@ CH_IRQ_HANDLER(USB_LP_IRQHandler) { if (epr & EPR_CTR_TX) {
/* IN endpoint, transmission.*/
EPR_CLEAR_CTR_TX(ep);
- n = USB_GET_DESCRIPTOR(ep)->TXCOUNT;
- usbp->ep[ep]->txbuf += n;
- usbp->ep[ep]->txcnt += n;
- usbp->ep[ep]->txsize -= n;
- if (usbp->ep[ep]->txsize > 0) {
- /* Transfer not completed, there are more packets to send.*/
- if (usbp->ep[ep]->txsize > epcp->in_maxsize)
- n = epcp->in_maxsize;
- else
- n = usbp->ep[ep]->txsize;
- write_packet(ep, usbp->ep[ep]->txbuf, n);
+ if (epcp->flags & USB_EP_FLAGS_IN_PACKET_MODE) {
+ /* Packet mode, just invokes the callback.*/
+ (usbp)->ep[ep]->transmitting = FALSE;
+ epcp->in_cb(usbp, ep);
}
else {
- /* Transfer completed, invoking the callback, if defined.*/
- (usbp)->ep[ep]->transmitting = FALSE;
- if (epcp->in_cb)
+ /* Transaction mode.*/
+ n = USB_GET_DESCRIPTOR(ep)->TXCOUNT;
+ usbp->ep[ep]->txbuf += n;
+ usbp->ep[ep]->txcnt += n;
+ usbp->ep[ep]->txsize -= n;
+ if (usbp->ep[ep]->txsize > 0) {
+ /* Transfer not completed, there are more packets to send.*/
+ if (usbp->ep[ep]->txsize > epcp->in_maxsize)
+ n = epcp->in_maxsize;
+ else
+ n = usbp->ep[ep]->txsize;
+ write_packet(ep, usbp->ep[ep]->txbuf, n);
+ }
+ else {
+ /* Transfer completed, invokes the callback.*/
+ (usbp)->ep[ep]->transmitting = FALSE;
epcp->in_cb(usbp, ep);
+ }
}
}
if (epr & EPR_CTR_RX) {
EPR_CLEAR_CTR_RX(ep);
/* OUT endpoint, receive.*/
- if ((epr & EPR_SETUP) && (ep == 0)) {
- /* Special case, setup packet for EP0, enforcing a reset of the
- EP0 state machine for robustness.*/
- usbp->ep0state = USB_EP0_WAITING_SETUP;
- read_packet(0, usbp->setup, 8);
+ if (epcp->flags & USB_EP_FLAGS_IN_PACKET_MODE) {
+ /* Packet mode, just invokes the callback.*/
+ (usbp)->ep[ep]->receiving = FALSE;
epcp->out_cb(usbp, ep);
}
else {
- n = read_packet(ep, usbp->ep[ep]->rxbuf, usbp->ep[ep]->rxsize);
- usbp->ep[ep]->rxbuf += n;
- usbp->ep[ep]->rxcnt += n;
- usbp->ep[ep]->rxsize -= n;
- usbp->ep[ep]->rxpkts -= 1;
- if (usbp->ep[ep]->rxpkts > 0) {
- /* Transfer not completed, there are more packets to receive.*/
- EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID);
+ if ((epr & EPR_SETUP) && (ep == 0)) {
+ /* Special case, setup packet for EP0, enforcing a reset of the
+ EP0 state machine for robustness.*/
+ usbp->ep0state = USB_EP0_WAITING_SETUP;
+ read_packet(0, usbp->setup, 8);
+ epcp->out_cb(usbp, ep);
}
else {
- /* Transfer completed, invoking the callback, if defined.*/
- (usbp)->ep[ep]->receiving = FALSE;
- if (epcp->out_cb)
+ n = read_packet(ep, usbp->ep[ep]->rxbuf, usbp->ep[ep]->rxsize);
+ usbp->ep[ep]->rxbuf += n;
+ usbp->ep[ep]->rxcnt += n;
+ usbp->ep[ep]->rxsize -= n;
+ usbp->ep[ep]->rxpkts -= 1;
+ if (usbp->ep[ep]->rxpkts > 0) {
+ /* Transfer not completed, there are more packets to receive.*/
+ EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID);
+ }
+ else {
+ /* Transfer completed, invokes the callback.*/
+ (usbp)->ep[ep]->receiving = FALSE;
epcp->out_cb(usbp, ep);
+ }
}
}
}
@@ -357,13 +371,43 @@ void usb_lld_set_address(USBDriver *usbp) { * @notapi
*/
void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
- uint16_t nblocks;
+ uint16_t nblocks, epr;
stm32_usb_descriptor_t *dp;
const USBEndpointConfig *epcp = usbp->ep[ep]->config;
+ /* Setting the endpoint type.*/
+ switch (epcp->ep_type) {
+ case EP_TYPE_ISOC:
+ epr = EPR_EP_TYPE_ISO;
+ break;
+ case EP_TYPE_BULK:
+ epr = EPR_EP_TYPE_BULK;
+ break;
+ case EP_TYPE_INTR:
+ epr = EPR_EP_TYPE_INTERRUPT;
+ break;
+ default:
+ epr = EPR_EP_TYPE_CONTROL;
+ }
+
+ /* IN endpoint settings, always in NAK mode initially.*/
+ if (epcp->in_cb)
+ epr |= EPR_STAT_TX_NAK;
+
+ /* OUT endpoint settings. If the endpoint is in packet mode then it must
+ start ready to accept data else it must start in NAK mode.*/
+ if (epcp->out_cb) {
+ if (epcp->flags & USB_EP_FLAGS_IN_PACKET_MODE) {
+ usbp->ep[ep]->receiving = TRUE;
+ epr |= EPR_STAT_RX_VALID;
+ }
+ else
+ epr |= EPR_STAT_RX_NAK;
+ }
+
/* EPxR register setup.*/
- EPR_SET(ep, epcp->epr | ep);
- EPR_TOGGLE(ep, epcp->epr);
+ EPR_SET(ep, epr | ep);
+ EPR_TOGGLE(ep, epr);
/* Endpoint size and address initialization.*/
if (epcp->out_maxsize > 62)
diff --git a/os/hal/platforms/STM32/usb_lld.h b/os/hal/platforms/STM32/usb_lld.h index d365521ee..d1e3169c2 100644 --- a/os/hal/platforms/STM32/usb_lld.h +++ b/os/hal/platforms/STM32/usb_lld.h @@ -46,6 +46,16 @@ */
#define USB_SET_ADDRESS_MODE USB_LATE_SET_ADDRESS
+/**
+ * @brief Enables the packet mode for an IN endpoint.
+ */
+#define USB_EP_FLAGS_IN_PACKET_MODE 1
+
+/**
+ * @brief Enables the packet mode for an OUT endpoint.
+ */
+#define USB_EP_FLAGS_OUT_PACKET_MODE 2
+
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
@@ -99,27 +109,38 @@ */
typedef struct {
/**
+ * @brief Type of the endpoint.
+ */
+ usbeptype_t ep_type;
+ /**
* @brief IN endpoint notification callback.
+ * @details This field must be set to @p NULL if the IN endpoint is not
+ * used.
*/
usbepcallback_t in_cb;
/**
* @brief OUT endpoint notification callback.
+ * @details This field must be set to @p NULL if the OUT endpoint is not
+ * used.
*/
usbepcallback_t out_cb;
/**
* @brief IN endpoint maximum packet size.
+ * @details This field must be set to zero if the IN endpoint is not
+ * used.
*/
uint16_t in_maxsize;
/**
* @brief OUT endpoint maximum packet size.
+ * @details This field must be set to zero if the OUT endpoint is not
+ * used.
*/
uint16_t out_maxsize;
/* End of the mandatory fields.*/
/**
- * @brief EPxR register initialization value.
- * @note Do not specify the EA field, leave it to zero.
+ * @bief Endpoint mode flags.
*/
- uint16_t epr;
+ uint16_t flags;
/**
* @brief Endpoint IN buffer address as offset in the PMA.
*/
|