summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsakumisu <[email protected]>2021-11-30 21:57:25 +0800
committersakumisu <[email protected]>2021-11-30 21:57:25 +0800
commite332f6c2e3eab2f2d197ea31fe03d980c9b26a6a (patch)
treefb005d1203c76485fca1e60a07a8d18e7636457f
parent2acc65105234ab1f4ef251c87a39586c3dddd7fe (diff)
add ch32 port(not release)
-rw-r--r--port/ch32/usb_dc.c314
1 files changed, 314 insertions, 0 deletions
diff --git a/port/ch32/usb_dc.c b/port/ch32/usb_dc.c
new file mode 100644
index 00000000..c77f8f42
--- /dev/null
+++ b/port/ch32/usb_dc.c
@@ -0,0 +1,314 @@
+#include "usbd_core.h"
+#include "ch32f10x.h"
+
+#ifndef USB_NUM_BIDIR_ENDPOINTS
+#define USB_NUM_BIDIR_ENDPOINTS 5
+#endif
+
+/* Endpoint state */
+struct usb_dc_ep_state {
+ /** Endpoint max packet size */
+ uint16_t ep_mps;
+ /** Endpoint Transfer Type.
+ * May be Bulk, Interrupt, Control or Isochronous
+ */
+ uint8_t ep_type;
+ uint8_t ep_stalled; /** Endpoint stall flag */
+};
+
+/* Driver state */
+struct usb_dc_config_priv {
+ uint8_t dev_addr;
+ struct usb_dc_ep_state in_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< IN endpoint parameters*/
+ struct usb_dc_ep_state out_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< OUT endpoint parameters */
+} usb_dc_cfg;
+
+/* Endpoint Buffer */
+// clang-format off
+__ALIGNED(4) uint8_t EP0_Databuf[64+64+64]; //ep0(64)+ep4_out(64)+ep4_in(64)
+__ALIGNED(4) uint8_t EP1_Databuf[64+64]; //ep1_out(64)+ep1_in(64)
+__ALIGNED(4) uint8_t EP2_Databuf[64+64]; //ep2_out(64)+ep2_in(64)
+__ALIGNED(4) uint8_t EP3_Databuf[64+64]; //ep3_out(64)+ep3_in(64)
+// clang-format on
+
+int usb_dc_init(void)
+{
+ memset(&usb_dc_cfg, 0, sizeof(struct usb_dc_config_priv));
+
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
+ EXTEN->EXTEN_CTR |= EXTEN_USBHD_IO_EN;
+ RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5); //USBclk=PLLclk/1.5=48Mhz
+ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHD, ENABLE);
+
+ R8_USB_CTRL = 0x00;
+
+ R8_UEP4_1_MOD = RB_UEP4_RX_EN | RB_UEP4_TX_EN | RB_UEP1_RX_EN | RB_UEP1_TX_EN;
+ R8_UEP2_3_MOD = RB_UEP2_RX_EN | RB_UEP2_TX_EN | RB_UEP3_RX_EN | RB_UEP3_TX_EN;
+
+ R8_USB_INT_FG = 0xFF;
+ R8_USB_INT_EN = RB_UIE_SUSPEND | RB_UIE_BUS_RST | RB_UIE_TRANSFER;
+
+ R8_USB_DEV_AD = 0x00;
+ usb_dc_cfg.dev_addr = 0;
+ R8_USB_CTRL = RB_UC_DEV_PU_EN | RB_UC_INT_BUSY | RB_UC_DMA_EN;
+ R8_UDEV_CTRL = RB_UD_PD_DIS | RB_UD_PORT_EN;
+
+ NVIC_EnableIRQ(USBHD_IRQn);
+ return 0;
+}
+
+void usb_dc_deinit(void)
+{
+}
+
+int usbd_set_address(const uint8_t addr)
+{
+ if (addr == 0) {
+ R8_USB_DEV_AD = 0x00;
+ }
+ usb_dc_cfg.dev_addr = addr;
+ return 0;
+}
+
+int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg)
+{
+ uint8_t ep_idx = USB_EP_GET_IDX(ep_cfg->ep_addr);
+
+ 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;
+ } else {
+ usb_dc_cfg.in_ep[ep_idx].ep_mps = ep_cfg->ep_mps;
+ usb_dc_cfg.in_ep[ep_idx].ep_type = ep_cfg->ep_type;
+ }
+
+ switch (ep_idx) {
+ case 0:
+ R16_UEP0_DMA = (UINT16)(UINT32)EP0_Databuf;
+ R8_UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
+ break;
+ case 1:
+ R16_UEP1_DMA = (UINT16)(UINT32)EP1_Databuf;
+ R8_UEP1_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
+ break;
+ case 2:
+ R16_UEP2_DMA = (UINT16)(UINT32)EP2_Databuf;
+ R8_UEP2_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
+ break;
+ case 3:
+ R16_UEP3_DMA = (UINT16)(UINT32)EP3_Databuf;
+ R8_UEP3_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+int usbd_ep_close(const uint8_t ep)
+{
+ return 0;
+}
+int usbd_ep_set_stall(const uint8_t ep)
+{
+ return 0;
+}
+int usbd_ep_clear_stall(const uint8_t ep)
+{
+ return 0;
+}
+int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled)
+{
+ return 0;
+}
+
+int usbd_ep_write(const uint8_t ep, const uint8_t *data, uint32_t data_len, uint32_t *ret_bytes)
+{
+ uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+ if (!data && data_len) {
+ return -1;
+ }
+
+ if (!data_len) {
+ return 0;
+ }
+
+ if (data_len > usb_dc_cfg.in_ep[ep_idx].ep_mps) {
+ data_len = usb_dc_cfg.in_ep[ep_idx].ep_mps;
+ }
+
+ if (ep_idx == 0) {
+ memcpy(&EP0_Databuf[0], data, data_len);
+ } else if (ep_idx == 1) {
+ memcpy(&EP1_Databuf[64], data, data_len);
+ R8_UEP1_T_LEN = data_len;
+ R8_UEP1_CTRL = (R8_UEP1_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_ACK;
+ } else if (ep_idx == 2) {
+ memcpy(&EP2_Databuf[64], data, data_len);
+ R8_UEP2_T_LEN = data_len;
+ R8_UEP2_CTRL = (R8_UEP2_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_ACK;
+ } else if (ep_idx == 3) {
+ memcpy(&EP3_Databuf[64], data, data_len);
+ R8_UEP3_T_LEN = data_len;
+ R8_UEP3_CTRL = (R8_UEP3_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_ACK;
+ } else if (ep_idx == 4) {
+ memcpy(&EP0_Databuf[128], data, data_len);
+ R8_UEP4_T_LEN = data_len;
+ R8_UEP4_CTRL = (R8_UEP4_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_ACK;
+ }
+
+ if (ret_bytes) {
+ *ret_bytes = data_len;
+ }
+
+ return 0;
+}
+
+int usbd_ep_read(const uint8_t ep, uint8_t *data, uint32_t max_data_len, uint32_t *read_bytes)
+{
+ uint8_t ep_idx = USB_EP_GET_IDX(ep);
+ uint32_t read_count;
+
+ if (!data && max_data_len) {
+ return -1;
+ }
+
+ if (!max_data_len) {
+ return 0;
+ }
+
+ read_count = R8_USB_RX_LEN;
+ read_count = MIN(read_count, max_data_len);
+ if (ep_idx == 0) {
+ memcpy(data, &EP0_Databuf[0], read_count);
+ } else if (ep_idx == 1) {
+ memcpy(data, &EP1_Databuf[0], read_count);
+ } else if (ep_idx == 2) {
+ memcpy(data, &EP2_Databuf[0], read_count);
+ } else if (ep_idx == 3) {
+ memcpy(data, &EP3_Databuf[0], read_count);
+ } else if (ep_idx == 4) {
+ memcpy(data, &EP0_Databuf[64], read_count);
+ }
+ if (read_bytes) {
+ *read_bytes = read_count;
+ }
+
+ return 0;
+}
+
+/**
+ * @brief This function handles PCD interrupt request.
+ * @param hpcd PCD handle
+ * @retval HAL status
+ */
+void USBD_IRQHandler(void)
+{
+ UINT8 len, chtype;
+ UINT8 intflag, errflag = 0;
+
+ intflag = R8_USB_INT_FG;
+
+ if (intflag & RB_UIF_TRANSFER) {
+ switch (R8_USB_INT_ST & MASK_UIS_TOKEN) {
+ case UIS_TOKEN_SETUP:
+ usbd_event_notify_handler(USBD_EVENT_SETUP_NOTIFY, NULL);
+ R8_UEP0_CTRL = RB_UEP_R_TOG | RB_UEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_NAK;
+ break;
+
+ case UIS_TOKEN_IN:
+ switch (R8_USB_INT_ST & (MASK_UIS_TOKEN | MASK_UIS_ENDP)) {
+ case UIS_TOKEN_IN:
+ usbd_event_notify_handler(USBD_EVENT_EP0_IN_NOTIFY, NULL);
+ if (usb_dc_cfg.dev_addr > 0) {
+ R8_USB_DEV_AD = (R8_USB_DEV_AD & RB_UDA_GP_BIT) | usb_dc_cfg.dev_addr;
+ usb_dc_cfg.dev_addr = 0;
+ }
+ R8_UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
+ break;
+
+ case UIS_TOKEN_IN | 1:
+ usbd_event_notify_handler(USBD_EVENT_EP_IN_NOTIFY, (void *)(1 | 0x80));
+ R8_UEP1_CTRL ^= RB_UEP_T_TOG;
+ R8_UEP1_CTRL = (R8_UEP1_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;
+ break;
+
+ case UIS_TOKEN_IN | 2:
+ usbd_event_notify_handler(USBD_EVENT_EP_IN_NOTIFY, (void *)(2 | 0x80));
+ R8_UEP2_CTRL ^= RB_UEP_T_TOG;
+ R8_UEP2_CTRL = (R8_UEP2_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;
+ break;
+
+ case UIS_TOKEN_IN | 3:
+ usbd_event_notify_handler(USBD_EVENT_EP_IN_NOTIFY, (void *)(3 | 0x80));
+ R8_UEP3_CTRL ^= RB_UEP_T_TOG;
+ R8_UEP3_CTRL = (R8_UEP3_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;
+ break;
+
+ case UIS_TOKEN_IN | 4:
+ usbd_event_notify_handler(USBD_EVENT_EP_IN_NOTIFY, (void *)(4 | 0x80));
+ R8_UEP4_CTRL ^= RB_UEP_T_TOG;
+ R8_UEP4_CTRL = (R8_UEP4_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case UIS_TOKEN_OUT:
+ switch (R8_USB_INT_ST & (MASK_UIS_TOKEN | MASK_UIS_ENDP)) {
+ case UIS_TOKEN_OUT:
+ usbd_event_notify_handler(USBD_EVENT_EP0_OUT_NOTIFY, NULL);
+ break;
+
+ case UIS_TOKEN_OUT | 1:
+ if (R8_USB_INT_ST & RB_UIS_TOG_OK) {
+ usbd_event_notify_handler(USBD_EVENT_EP_OUT_NOTIFY, (void *)(1 & 0x7f));
+ R8_UEP1_CTRL ^= RB_UEP_R_TOG;
+ }
+ break;
+
+ case UIS_TOKEN_OUT | 2:
+ if (R8_USB_INT_ST & RB_UIS_TOG_OK) {
+ usbd_event_notify_handler(USBD_EVENT_EP_OUT_NOTIFY, (void *)(2 & 0x7f));
+ R8_UEP2_CTRL ^= RB_UEP_R_TOG;
+ }
+ break;
+
+ case UIS_TOKEN_OUT | 3:
+ if (R8_USB_INT_ST & RB_UIS_TOG_OK) {
+ usbd_event_notify_handler(USBD_EVENT_EP_OUT_NOTIFY, (void *)(3 & 0x7f));
+ R8_UEP3_CTRL ^= RB_UEP_R_TOG;
+ }
+ break;
+
+ case UIS_TOKEN_OUT | 4:
+ if (R8_USB_INT_ST & RB_UIS_TOG_OK) {
+ usbd_event_notify_handler(USBD_EVENT_EP_OUT_NOTIFY, (void *)(4 & 0x7f));
+ R8_UEP4_CTRL ^= RB_UEP_R_TOG;
+ }
+ break;
+ }
+
+ break;
+
+ case UIS_TOKEN_SOF:
+
+ break;
+
+ default:
+ break;
+ }
+ R8_USB_INT_FG = RB_UIF_TRANSFER;
+ } else if (intflag & RB_UIF_BUS_RST) {
+ R8_USB_DEV_AD = 0;
+ usbd_event_notify_handler(USBD_EVENT_RESET, NULL);
+ R8_USB_INT_FG |= RB_UIF_BUS_RST;
+ } else if (intflag & RB_UIF_SUSPEND) {
+ R8_USB_INT_FG = RB_UIF_SUSPEND;
+ } else {
+ R8_USB_INT_FG = intflag;
+ }
+}