diff options
| author | sakumisu <[email protected]> | 2022-03-13 17:23:10 +0800 |
|---|---|---|
| committer | sakumisu <[email protected]> | 2022-03-13 22:05:03 +0800 |
| commit | 2fae577fae529ce2036d0ba93b3a4fd815e15f42 (patch) | |
| tree | fa0342b0aca72d65561acfc54ed1b5126b29bd09 | |
| parent | 2379619a4d6069501c8352cd4510ad743150dfff (diff) | |
update musb dcd driver
| -rw-r--r-- | port/musb/usb_dc_musb.c | 133 |
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: |
