cherry-embedded / CherryUSB

CherryUSB is a tiny, beautiful and portable USB host and device stack for embedded system with USB IP
https://cherryusb.readthedocs.io/
Apache License 2.0
1.21k stars 256 forks source link

移植到CH57X上使用cdc_acm_template.c,无法成功进行USB通信 #232

Closed wdfk-prog closed 1 month ago

wdfk-prog commented 1 month ago

硬件是否正常,是否使用杜邦线连接,如果正常,请说明正常原因

USB 中断,时钟,引脚,寄存器地址是否正确,截图

是否能进 USB 中断

芯片是否带有 cache功能,是否做了 no cache 处理,截图

打开 CONFGI_USBDEV_SETUP_LOG_PRINT,并提供 log

/**
 * @brief            USB interrupt processing function
 * @pre              None
 * @param[in]        None
 * @retval           None
 */
__attribute__((interrupt("WCH-Interrupt-fast")))
__attribute__((section(".highcode"))) void
USBD_IRQHandler(void)
{
    volatile uint8_t intflag = 0;
    intflag = CH58x_USBFS_DEV->USB_INT_FG;
    if (intflag & RB_UIF_TRANSFER) {
        printf("RB_UIF_TRANSFER: %x\r\n", CH58x_USBFS_DEV->USB_INT_ST);
        if ((CH58x_USBFS_DEV->USB_INT_ST & MASK_UIS_TOKEN) != MASK_UIS_TOKEN) {
            printf("RB_UIF_TRANSFER: %x\r\n", CH58x_USBFS_DEV->USB_INT_ST);
            uint8_t epid = ((CH58x_USBFS_DEV->USB_INT_ST & (MASK_UIS_TOKEN | MASK_UIS_ENDP)) & 0x0f);
            printf("epid: 0x%x\r\n", epid);
            printf("UIS_TOKEN %x\r\n", (CH58x_USBFS_DEV->USB_INT_ST & (MASK_UIS_TOKEN | MASK_UIS_ENDP)) & 0xf0);
            switch ((CH58x_USBFS_DEV->USB_INT_ST & (MASK_UIS_TOKEN | MASK_UIS_ENDP)) & 0xf0) {
                case UIS_TOKEN_IN:
                    if (epid == 0) {
                        /**
                         * IN  The host takes away the data that has been stored in FIFO
                         */
                        printf("FIFO: 0x%x\r\n", usb_dc_cfg.setup.bmRequestType >> USB_REQUEST_DIR_SHIFT);
                        switch (usb_dc_cfg.setup.bmRequestType >> USB_REQUEST_DIR_SHIFT) {
                            case 1:
                                /*!< Get */
                                CH58x_USBFS_DEV->UEP0_CTRL ^= RB_UEP_T_TOG;
                                /**
                                 * Here is to take away the last data, and the IN interrupt will be triggered only after it is successfully taken away.
                                 * Therefore, the status of the in endpoint is set to NAK here. If there is data transmission,
                                 * the endpoint status will be set to ack again in the in handler of EP0.
                                 */
                                EPn_SET_TX_NAK(0);

                                /*!< IN */
                                if (usb_dc_cfg.ep_in[0].xfer_len > usb_dc_cfg.ep_in[0].mps) {
                                    usb_dc_cfg.ep_in[0].xfer_len -= usb_dc_cfg.ep_in[0].mps;
                                    usb_dc_cfg.ep_in[0].actual_xfer_len += usb_dc_cfg.ep_in[0].mps;
                                    usbd_event_ep_in_complete_handler(0, 0 | 0x80, usb_dc_cfg.ep_in[0].actual_xfer_len);
                                } else {
                                    usb_dc_cfg.ep_in[0].actual_xfer_len += usb_dc_cfg.ep_in[0].xfer_len;
                                    usb_dc_cfg.ep_in[0].xfer_len = 0;
                                    usbd_event_ep_in_complete_handler(0, 0 | 0x80, usb_dc_cfg.ep_in[0].actual_xfer_len);
                                }
                                break;
                            case 0:
                                /*!< Set */
                                switch (usb_dc_cfg.setup.bRequest) {
                                    case USB_REQUEST_SET_ADDRESS:
                                        /*!< Fill in the equipment address */
                                        CH58x_USBFS_DEV->USB_DEV_AD = (CH58x_USBFS_DEV->USB_DEV_AD & RB_UDA_GP_BIT) | usb_dc_cfg.address;
                                        /**
                                         * In the state phase after setting the address, the host has sent an in token packet of data1 to take the packet of 0 length,
                                         * Ch58x USB IP needs to manually set the status of the in endpoint to NAK
                                         */
                                        EPn_SET_TX_NAK(0);
                                        EPn_SET_RX_VALID(0);
                                        break;
                                    default:
                                        /*!< Normal out state phase */
                                        /**
                                         * The host has sent an in token packet of data1 and taken the packet of 0 length.
                                         * Here, you only need to set the status of the in endpoint to NAK and out endpoint ACK
                                         */
                                        EPn_SET_TX_NAK(0);
                                        EPn_SET_RX_VALID(0);
                                        break;
                                }
                                break;
                        }
                    } else {
                        if (epid == 4) {
                            CH58x_USBFS_DEV->UEP4_CTRL ^= RB_UEP_T_TOG;
                        }
                        EPn_SET_TX_NAK(epid);
                        if (usb_dc_cfg.ep_in[epid].xfer_len > usb_dc_cfg.ep_in[epid].mps) {
                            /*!< Need start in again */
                            usb_dc_cfg.ep_in[epid].xfer_buf += usb_dc_cfg.ep_in[epid].mps;
                            usb_dc_cfg.ep_in[epid].xfer_len -= usb_dc_cfg.ep_in[epid].mps;
                            usb_dc_cfg.ep_in[epid].actual_xfer_len += usb_dc_cfg.ep_in[epid].mps;
                            if (usb_dc_cfg.ep_in[epid].xfer_len > usb_dc_cfg.ep_in[epid].mps) {
                                memcpy(usb_dc_cfg.ep_in[epid].ep_ram_addr, usb_dc_cfg.ep_in[epid].xfer_buf, usb_dc_cfg.ep_in[epid].mps);
                            } else {
                                memcpy(usb_dc_cfg.ep_in[epid].ep_ram_addr, usb_dc_cfg.ep_in[epid].xfer_buf, usb_dc_cfg.ep_in[epid].xfer_len);
                            }
                            if (usb_dc_cfg.ep_in[epid].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
                                EPn_SET_TX_VALID(epid);
                            } else {
                                EPn_SET_TX_ISO_VALID(epid);
                            }
                        } else {
                            usb_dc_cfg.ep_in[epid].actual_xfer_len += usb_dc_cfg.ep_in[epid].xfer_len;
                            usb_dc_cfg.ep_in[epid].xfer_len = 0;
                            usbd_event_ep_in_complete_handler(0, epid | 0x80, usb_dc_cfg.ep_in[epid].actual_xfer_len);
                        }
                    }
                    break;
                case UIS_TOKEN_OUT:
                    EPn_SET_RX_NAK(epid);

                    if (epid == 0) {
                        /*!< ep0 out */
                        CH58x_USBFS_DEV->UEP0_CTRL ^= RB_UEP_R_TOG;
                        uint32_t read_count = EPn_GET_RX_LEN(0);
                        memcpy(usb_dc_cfg.ep_out[epid].xfer_buf, usb_dc_cfg.ep_out[epid].ep_ram_addr, read_count);

                        usb_dc_cfg.ep_out[0].actual_xfer_len += read_count;
                        usb_dc_cfg.ep_out[0].xfer_len -= read_count;
                        usbd_event_ep_out_complete_handler(0, 0x00, usb_dc_cfg.ep_out[0].actual_xfer_len);
                        if (read_count == 0) {
                            /*!< Out status, start reading setup */
                            EPn_SET_RX_VALID(0);
                        }
                    } else {
                        if ((CH58x_USBFS_DEV->USB_INT_ST) & RB_UIS_TOG_OK) {
                            if (epid == 4) {
                                CH58x_USBFS_DEV->UEP4_CTRL ^= RB_UEP_R_TOG;
                            }
                            uint32_t read_count = EPn_GET_RX_LEN(epid);
                            memcpy(usb_dc_cfg.ep_out[epid].xfer_buf, usb_dc_cfg.ep_out[epid].ep_ram_addr, read_count);
                            usb_dc_cfg.ep_out[epid].xfer_buf += read_count;
                            usb_dc_cfg.ep_out[epid].actual_xfer_len += read_count;
                            usb_dc_cfg.ep_out[epid].xfer_len -= read_count;

                            if ((read_count < usb_dc_cfg.ep_out[epid].mps) || (usb_dc_cfg.ep_out[epid].xfer_len == 0)) {
                                usbd_event_ep_out_complete_handler(0, ((epid)&0x7f), usb_dc_cfg.ep_out[epid].actual_xfer_len);
                            } else {
                                if (usb_dc_cfg.ep_out[epid].eptype != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
                                    EPn_SET_RX_VALID(epid);
                                } else {
                                    EPn_SET_RX_ISO_VALID(epid);
                                }
                            }
                        }
                    }
                    break;
                default:
                    break;
            }
            CH58x_USBFS_DEV->USB_INT_FG = RB_UIF_TRANSFER;
        }

        if (CH58x_USBFS_DEV->USB_INT_ST & RB_UIS_SETUP_ACT) {
            printf("RB_UIS_SETUP_ACT: %x\r\n", CH58x_USBFS_DEV->USB_INT_ST);
            /*!< Setup */
            /**
             * Setup the device must respond with ACK, and the next data phase is DATA1
             * If it is sent, the data1 packet will be sent.
             * If it is received, the data1 packet is expected to be received.
             * If it is in, the host will send the data1 out packet to complete the status phase after the in completes.
             * If it is out, the host will send the data1 in packet to complete the status phase after the out completes.
             */
            CH58x_USBFS_DEV->UEP0_CTRL = RB_UEP_R_TOG | RB_UEP_T_TOG | UEP_T_RES_NAK;
            /*!< get setup packet */
            usb_dc_cfg.setup = GET_SETUP_PACKET(usb_dc_cfg.ep_out[0].ep_ram_addr);
            if (usb_dc_cfg.setup.bmRequestType >> USB_REQUEST_DIR_SHIFT == 0) {
                /**
                 * Ep0 The next in must be the status stage.
                 * The device must reply to the host data 0 length packet.
                 * Here, set the transmission length to 0 and the transmission status to ACK,
                 * and wait for the host to send the in token to retrieve
                 */
                EPn_SET_TX_LEN(0, 0);
                EPn_SET_TX_VALID(0);
            }
            EPn_SET_RX_NAK(0);
            usbd_event_ep0_setup_complete_handler(0, (uint8_t *)&(usb_dc_cfg.setup));
            CH58x_USBFS_DEV->USB_INT_FG = RB_UIF_TRANSFER;
        }
    } else if (intflag & RB_UIF_BUS_RST) {
        /*!< Reset */
        CH58x_USBFS_DEV->USB_DEV_AD = 0;
        usbd_event_reset_handler(0);
        /*!< Set ep0 rx vaild to start receive setup packet */
        EPn_SET_RX_VALID(0);
        CH58x_USBFS_DEV->USB_INT_FG = RB_UIF_BUS_RST;
    } else if (intflag & RB_UIF_SUSPEND) {
        if (CH58x_USBFS_DEV->USB_MIS_ST & RB_UMS_SUSPEND) {
            /*!< Suspend */
        } else {
            /*!< Wake up */
        }
        CH58x_USBFS_DEV->USB_INT_FG = RB_UIF_SUSPEND;
    } else {
        CH58x_USBFS_DEV->USB_INT_FG = intflag;
    }
}
CherryUSB device cdc acm example
rx_msg id = 2
rx_msg id = 1
usb_dc_low_level_init
RB_UIF_TRANSFER: b2
RB_UIS_SETUP_ACT: b2
RB_UIF_TRANSFER: 60
RB_UIF_TRANSFER: 60
epid: 0x0
UIS_TOKEN 20
FIFO: 0x0
RB_UIF_TRANSFER: 40
RB_UIF_TRANSFER: 40
epid: 0x0
UIS_TOKEN 0
usbd_event_ep_out_complete_handler: busid=0, ep=0, nbytes=0
[D/USB] EP0 recv out status
RB_UIF_TRANSFER: f0
RB_UIS_SETUP_ACT: f0
RB_UIF_TRANSFER: 60
RB_UIF_TRANSFER: 60
epid: 0x0
UIS_TOKEN 20
FIFO: 0x0
RB_UIF_TRANSFER: 40
RB_UIF_TRANSFER: 40
epid: 0x0
UIS_TOKEN 0
usbd_event_ep_out_complete_handler: busid=0, ep=0, nbytes=0
[D/USB] EP0 recv out status
RB_UIF_TRANSFER: f0
RB_UIS_SETUP_ACT: f0
RB_UIF_TRANSFER: 60
RB_UIF_TRANSFER: 60
epid: 0x0
UIS_TOKEN 20
FIFO: 0x0
RB_UIF_TRANSFER: 40
RB_UIF_TRANSFER: 40
epid: 0x0
UIS_TOKEN 0
usbd_event_ep_out_complete_handler: busid=0, ep=0, nbytes=0
[D/USB] EP0 recv out status
RB_UIF_TRANSFER: f0
RB_UIS_SETUP_ACT: f0
RB_UIF_TRANSFER: 60
RB_UIF_TRANSFER: 60
epid: 0x0
UIS_TOKEN 20
FIFO: 0x0
RB_UIF_TRANSFER: 40
RB_UIF_TRANSFER: 40
epid: 0x0
UIS_TOKEN 0
usbd_event_ep_out_complete_handler: busid=0, ep=0, nbytes=0
[D/USB] EP0 recv out status

是否流片并销售

其他

sakumisu commented 1 month ago

1,禁止中断中打印,2,ch不做支持,自行解决

wdfk-prog commented 1 month ago

1,禁止中断中打印,2,ch不做支持,自行解决

^_^,好吧

sakumisu commented 1 month ago

还有,你dc low level 里面就一行开中断,应该是不对的,参考我们 ch32 ch58x demo,时钟这些应该都要配置的

sakumisu commented 1 month ago

至于剩下的,不清楚了,建议找 ch32做支持 or 更换芯片

sakumisu commented 1 month ago

最后,中断里加打印,影响usb时序,就不要想着能用了

wdfk-prog commented 1 month ago