summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsakumisu <[email protected]>2022-03-13 17:23:10 +0800
committersakumisu <[email protected]>2022-03-13 22:05:03 +0800
commit2fae577fae529ce2036d0ba93b3a4fd815e15f42 (patch)
treefa0342b0aca72d65561acfc54ed1b5126b29bd09
parent2379619a4d6069501c8352cd4510ad743150dfff (diff)
update musb dcd driver
-rw-r--r--port/musb/usb_dc_musb.c133
1 files changed, 77 insertions, 56 deletions
diff --git a/port/musb/usb_dc_musb.c b/port/musb/usb_dc_musb.c
index abd180cc..87bfc051 100644
--- a/port/musb/usb_dc_musb.c
+++ b/port/musb/usb_dc_musb.c
@@ -22,13 +22,10 @@
#define HWREGB(x) \
(*((volatile uint8_t *)(x)))
-#define USB_CSRL0_BASE (&USB->CSRL0)
#define USB_TXCSRLx_BASE(ep_idx) (&USB->TXCSRL1 + 0x10 * (ep_idx - 1))
#define USB_RXCSRLx_BASE(ep_idx) (&USB->RXCSRL1 + 0x10 * (ep_idx - 1))
#define USB_TXCSRHx_BASE(ep_idx) (&USB->TXCSRH1 + 0x10 * (ep_idx - 1))
#define USB_RXCSRHx_BASE(ep_idx) (&USB->RXCSRH1 + 0x10 * (ep_idx - 1))
-#define USB_TXMAPx_BASE(ep_idx) ((uint8_t *)&USB->TXMAXP1 + 0x10 * (ep_idx - 1))
-#define USB_RXMAPx_BASE(ep_idx) ((uint8_t *)&USB->RXMAXP1 + 0x10 * (ep_idx - 1))
#define USB_RXCOUNTx_BASE(ep_idx) ((uint8_t *)&USB->RXCOUNT1 + 0x10 * (ep_idx - 1))
#define USB_FIFO_BASE(ep_idx) (&USB->FIFO0_BYTE + 0x4 * ep_idx)
@@ -61,12 +58,13 @@ struct usb_dc_config_priv {
} usb_dc_cfg;
volatile uint8_t usb_ep0_state = USB_EP0_STATE_SETUP;
+volatile uint16_t ep0_last_size = 0;
static void usb_musb_data_ack(uint8_t ep_idx, bool bIsLastPacket)
{
if (ep_idx == 0) {
// Clear RxPktRdy, and optionally DataEnd, on endpoint zero.
- HWREGB(USB_CSRL0_BASE) = USB_CSRL0_RXRDYC | (bIsLastPacket ? USB_CSRL0_DATAEND : 0);
+ USB->CSRL0 = USB_CSRL0_RXRDYC | (bIsLastPacket ? USB_CSRL0_DATAEND : 0);
} else {
// Clear RxPktRdy on all other endpoints.
HWREGB(USB_RXCSRLx_BASE(ep_idx)) &= ~(USB_RXCSRL1_RXRDY);
@@ -76,7 +74,7 @@ static void usb_musb_data_ack(uint8_t ep_idx, bool bIsLastPacket)
static void usb_musb_data_send(uint8_t ep_idx, bool bIsLastPacket)
{
if (ep_idx == 0) {
- HWREGB(USB_CSRL0_BASE) = USB_CSRL0_TXRDY | (bIsLastPacket ? USB_CSRL0_DATAEND : 0);
+ USB->CSRL0 = USB_CSRL0_TXRDY | (bIsLastPacket ? USB_CSRL0_DATAEND : 0);
} else {
HWREGB(USB_TXCSRLx_BASE(ep_idx)) = USB_TXCSRL1_TXRDY;
}
@@ -209,13 +207,18 @@ int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
if (ep_idx == 0) {
return 0;
}
+
+ uint32_t old_ep_idx = USB->EPIDX;
+
+ USB->EPIDX = ep_idx;
+
if (USB_EP_DIR_IS_OUT(ep_cfg->ep_addr)) {
usb_dc_cfg.out_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
usb_dc_cfg.out_ep[ep_idx].ep_type = ep_cfg->ep_type;
USB->RXIE |= (1 << ep_idx);
- HWREGH(USB_RXMAPx_BASE(ep_idx)) = ep_cfg->ep_mps;
+ USB->RXMAXP1 = ep_cfg->ep_mps;
//
// Allow auto clearing of RxPktRdy when packet of size max packet
@@ -257,14 +260,9 @@ int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
fifo_size = usb_musb_get_fifo_size(ep_cfg->ep_mps, &used);
- uint32_t index = USB->EPIDX;
-
- USB->EPIDX = ep_idx;
USB->RXFIFOSZ = fifo_size & 0x0f;
USB->RXFIFOADD = (usb_dc_cfg.fifo_size_offset >> 3);
- USB->EPIDX = index;
-
usb_dc_cfg.fifo_size_offset += used;
} else {
usb_dc_cfg.in_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
@@ -272,7 +270,7 @@ int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
USB->TXIE |= (1 << ep_idx);
- HWREGH(USB_TXMAPx_BASE(ep_idx)) = ep_cfg->ep_mps;
+ USB->TXMAXP1 = ep_cfg->ep_mps;
//
// Allow auto setting of TxPktRdy when max packet size has been loaded
@@ -307,17 +305,14 @@ int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
fifo_size = usb_musb_get_fifo_size(ep_cfg->ep_mps, &used);
- uint32_t index = USB->EPIDX;
-
- USB->EPIDX = ep_idx;
USB->TXFIFOSZ = fifo_size & 0x0f;
USB->TXFIFOADD = (usb_dc_cfg.fifo_size_offset >> 3);
- USB->EPIDX = index;
-
usb_dc_cfg.fifo_size_offset += used;
}
+ USB->EPIDX = old_ep_idx;
+
return 0;
}
@@ -332,13 +327,13 @@ int usbd_ep_set_stall(const uint8_t ep)
if (USB_EP_DIR_IS_OUT(ep)) {
if (ep_idx == 0x00) {
- HWREGB(USB_CSRL0_BASE) |= (USB_CSRL0_STALL | USB_CSRL0_RXRDYC);
+ USB->CSRL0 |= (USB_CSRL0_STALL | USB_CSRL0_RXRDYC);
} else {
HWREGB(USB_RXCSRLx_BASE(ep_idx)) |= USB_RXCSRL1_STALL;
}
} else {
if (ep_idx == 0x00) {
- HWREGB(USB_CSRL0_BASE) |= (USB_CSRL0_STALL | USB_CSRL0_RXRDYC);
+ USB->CSRL0 |= (USB_CSRL0_STALL | USB_CSRL0_RXRDYC);
} else {
HWREGB(USB_TXCSRLx_BASE(ep_idx)) |= USB_TXCSRL1_STALL;
}
@@ -353,7 +348,7 @@ int usbd_ep_clear_stall(const uint8_t ep)
if (USB_EP_DIR_IS_OUT(ep)) {
if (ep_idx == 0x00) {
- HWREGB(USB_CSRL0_BASE) &= ~USB_CSRL0_STALLED;
+ USB->CSRL0 &= ~USB_CSRL0_STALLED;
} else {
// Clear the stall on an OUT endpoint.
HWREGB(USB_RXCSRLx_BASE(ep_idx)) &= ~(USB_RXCSRL1_STALL | USB_RXCSRL1_STALLED);
@@ -362,7 +357,7 @@ int usbd_ep_clear_stall(const uint8_t ep)
}
} else {
if (ep_idx == 0x00) {
- HWREGB(USB_CSRL0_BASE) &= ~USB_CSRL0_STALLED;
+ USB->CSRL0 &= ~USB_CSRL0_STALLED;
} else {
// Clear the stall on an IN endpoint.
HWREGB(USB_TXCSRLx_BASE(ep_idx)) &= ~(USB_TXCSRL1_STALL | USB_TXCSRL1_STALLED);
@@ -389,8 +384,8 @@ int usbd_ep_write(const uint8_t ep, const uint8_t *data, uint32_t data_len, uint
}
if (ep_idx == 0x00) {
- while (HWREGB(USB_CSRL0_BASE) & USB_CSRL0_TXRDY) {
- if (HWREGB(USB_CSRL0_BASE) & USB_CSRL0_ERROR) {
+ while (USB->CSRL0 & USB_CSRL0_TXRDY) {
+ if (USB->CSRL0 & USB_CSRL0_ERROR) {
return -2;
}
if (!(timeout--)) {
@@ -409,30 +404,18 @@ int usbd_ep_write(const uint8_t ep, const uint8_t *data, uint32_t data_len, uint
}
if (!data_len) {
- if (ep_idx == 0x00) {
- usb_ep0_state = USB_EP0_STATE_IN_STATUS;
- usb_musb_data_ack(ep_idx, true);
- } else {
- usb_musb_data_send(ep_idx, true);
- }
return 0;
}
+ ep0_last_size = data_len;
+
if (data_len > usb_dc_cfg.in_ep[ep_idx].ep_mps) {
data_len = usb_dc_cfg.in_ep[ep_idx].ep_mps;
}
ret = usb_musb_write_packet(ep_idx, (uint8_t *)data, data_len);
- if (data_len == usb_dc_cfg.in_ep[ep_idx].ep_mps) {
- if (ep_idx == 0) {
- usb_ep0_state = USB_EP0_STATE_IN_DATA;
- }
- usb_musb_data_send(ep_idx, false);
- } else {
- if (ep_idx == 0) {
- usb_ep0_state = USB_EP0_STATE_OUT_STATUS;
- }
+ if (ep_idx != 0) {
usb_musb_data_send(ep_idx, true);
}
if (ret_bytes) {
@@ -460,11 +443,12 @@ int usbd_ep_read(const uint8_t ep, uint8_t *data, uint32_t max_data_len, uint32_
}
if (ep_idx == 0x00) {
- read_count = USB->COUNT0;
- usb_musb_read_packet(0, data, read_count);
if (usb_ep0_state == USB_EP0_STATE_SETUP) {
- memcpy((uint8_t *)&usb_dc_cfg.setup, data, 8);
- usb_musb_data_ack(0, false);
+ memcpy(data, (uint8_t *)&usb_dc_cfg.setup, 8);
+ } else {
+ read_count = USB->COUNT0;
+ read_count = MIN(read_count, max_data_len);
+ usb_musb_read_packet(0, data, read_count);
}
} else {
read_count = HWREGH(USB_RXCOUNTx_BASE(ep_idx));
@@ -481,43 +465,80 @@ int usbd_ep_read(const uint8_t ep, uint8_t *data, uint32_t max_data_len, uint32_
static void handle_ep0(void)
{
- uint8_t ep0_status = HWREGB(USB_CSRL0_BASE);
- uint8_t req = usb_dc_cfg.setup.bmRequestType;
+ uint8_t ep0_status = USB->CSRL0;
if (ep0_status & USB_CSRL0_STALLED) {
- HWREGB(USB_CSRL0_BASE) &= ~USB_CSRL0_STALLED;
+ USB->CSRL0 &= ~USB_CSRL0_STALLED;
return;
}
if (ep0_status & USB_CSRL0_SETEND) {
- HWREGB(USB_CSRL0_BASE) = USB_CSRL0_SETENDC;
+ USB->CSRL0 = USB_CSRL0_SETENDC;
+ }
+
+ if (usb_dc_cfg.dev_addr > 0) {
+ USB->FADDR = usb_dc_cfg.dev_addr;
+ usb_dc_cfg.dev_addr = 0;
}
switch (usb_ep0_state) {
- case USB_EP0_STATE_SETUP: {
+ case USB_EP0_STATE_SETUP:
if (ep0_status & USB_CSRL0_RXRDY) {
+ uint32_t read_count = USB->COUNT0;
+
+ if (read_count != 8) {
+ return;
+ }
+
+ usb_musb_read_packet(0, (uint8_t *)&usb_dc_cfg.setup, 8);
+ if (usb_dc_cfg.setup.wLength) {
+ usb_musb_data_ack(0, false);
+ } else {
+ usb_musb_data_ack(0, true);
+ }
+
usbd_event_notify_handler(USBD_EVENT_SETUP_NOTIFY, NULL);
- if (usb_dc_cfg.setup.wLength && !(usb_dc_cfg.setup.bmRequestType & 0x80)) {
- usb_ep0_state = USB_EP0_STATE_OUT_DATA;
+
+ if (usb_dc_cfg.setup.wLength) {
+ if (usb_dc_cfg.setup.bmRequestType & 0x80) {
+ usb_ep0_state = USB_EP0_STATE_IN_DATA;
+ if (ep0_last_size > usb_dc_cfg.in_ep[0].ep_mps) {
+ usb_musb_data_send(0, false);
+ } else {
+ usb_musb_data_send(0, true);
+ usb_ep0_state = USB_EP0_STATE_OUT_STATUS;
+ }
+ } else {
+ usb_ep0_state = USB_EP0_STATE_OUT_DATA;
+ }
+ } else {
+ usb_musb_data_send(0, true);
+ usb_ep0_state = USB_EP0_STATE_IN_STATUS;
}
}
- } break;
+ break;
case USB_EP0_STATE_IN_DATA:
usbd_event_notify_handler(USBD_EVENT_EP0_IN_NOTIFY, NULL);
+ if (ep0_last_size > usb_dc_cfg.in_ep[0].ep_mps) {
+ usb_musb_data_send(0, false);
+ } else {
+ usb_musb_data_send(0, true);
+ usb_ep0_state = USB_EP0_STATE_OUT_STATUS;
+ }
break;
case USB_EP0_STATE_IN_STATUS:
- if (usb_dc_cfg.dev_addr > 0) {
- USB->FADDR = usb_dc_cfg.dev_addr;
- usb_dc_cfg.dev_addr = 0;
- }
usb_ep0_state = USB_EP0_STATE_SETUP;
break;
case USB_EP0_STATE_OUT_DATA:
if (ep0_status & USB_CSRL0_RXRDY) {
usbd_event_notify_handler(USBD_EVENT_EP0_OUT_NOTIFY, NULL);
- usb_ep0_state = USB_EP0_STATE_IN_STATUS;
- usb_musb_data_ack(0, true);
+ if (usb_dc_cfg.setup.wLength > usb_dc_cfg.out_ep[0].ep_mps) {
+ usb_musb_data_ack(0, false);
+ } else {
+ usb_ep0_state = USB_EP0_STATE_IN_STATUS;
+ usb_musb_data_ack(0, true);
+ }
}
break;
case USB_EP0_STATE_OUT_STATUS: