diff --git a/targets/TARGET_NUVOTON/USBEndpoints_Nuvoton.cpp b/targets/TARGET_NUVOTON/USBEndpoints_Nuvoton.cpp index 6304a68cf6..2522e89284 100644 --- a/targets/TARGET_NUVOTON/USBEndpoints_Nuvoton.cpp +++ b/targets/TARGET_NUVOTON/USBEndpoints_Nuvoton.cpp @@ -20,33 +20,13 @@ static USBPhyHw *instance; -#if defined (TARGET_M451) #undef MBED_CONF_TARGET_USB_DEVICE_HSUSBD -#define MBED_CONF_TARGET_USB_DEVICE_HSUSBD 0 /* USB 1.1 Only */ -#elif defined (TARGET_M2351) -#undef MBED_CONF_TARGET_USB_DEVICE_HSUSBD -#define MBED_CONF_TARGET_USB_DEVICE_HSUSBD 0 /* USB 1.1 Only */ -#elif defined (TARGET_NANO100) -#undef MBED_CONF_TARGET_USB_DEVICE_HSUSBD -#define MBED_CONF_TARGET_USB_DEVICE_HSUSBD 0 /* USB 1.1 Only */ -#elif defined (TARGET_NUC472) -#define HSUSBD USBD -#undef MBED_CONF_TARGET_USB_DEVICE_HSUSBD -#define MBED_CONF_TARGET_USB_DEVICE_HSUSBD 1 /* USB 2.0 Only */ -#endif +#define MBED_CONF_TARGET_USB_DEVICE_HSUSBD 1 /* USB 1.1 Only */ + +uint32_t volatile g_ep_index, read_req = 0; void chip_config(void) { -#if defined(TARGET_M451) - /* Enable USBD module clock */ - CLK_EnableModuleClock(USBD_MODULE); - - CLK_SetModuleClock(USBD_MODULE, 0, CLK_CLKDIV0_USB(3)); - - /* Enable USB LDO33 */ - SYS->USBPHY = SYS_USBPHY_LDO33EN_Msk; - -#elif defined(TARGET_M480) #if (MBED_CONF_TARGET_USB_DEVICE_HSUSBD == 0) /* Configure USB to Device mode */ SYS->USBPHY = (SYS->USBPHY & ~SYS_USBPHY_USBROLE_Msk) | SYS_USBPHY_USBROLE_STD_USBD; @@ -77,615 +57,11 @@ void chip_config(void) /* Enable USBD module clock */ CLK_EnableModuleClock(HSUSBD_MODULE); #endif - -#elif defined (TARGET_M2351) - - /* Select USBD */ - SYS->USBPHY = (SYS->USBPHY & ~SYS_USBPHY_USBROLE_Msk) | SYS_USBPHY_OTGPHYEN_Msk | SYS_USBPHY_SBO_Msk; - - /* Enable IP clock */ - CLK_EnableModuleClock(USBD_MODULE); - - /* Select IP clock source */ - CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1)); - - /* USBD multi-function pins for VBUS, D+, D-, and ID pins */ - SYS->GPA_MFPH &= ~(SYS_GPA_MFPH_PA12MFP_Msk | SYS_GPA_MFPH_PA13MFP_Msk | SYS_GPA_MFPH_PA14MFP_Msk | SYS_GPA_MFPH_PA15MFP_Msk); - SYS->GPA_MFPH |= (SYS_GPA_MFPH_PA12MFP_USB_VBUS | SYS_GPA_MFPH_PA13MFP_USB_D_N | SYS_GPA_MFPH_PA14MFP_USB_D_P | SYS_GPA_MFPH_PA15MFP_USB_OTG_ID); - - -#elif defined (TARGET_NANO100) - - /* Select IP clock source */ - CLK_SetModuleClock(USBD_MODULE, 0, CLK_USB_CLK_DIVIDER(2)); - /* Enable IP clock */ - CLK_EnableModuleClock(USBD_MODULE); - -#elif defined (TARGET_NUC472) - - /* Enable USBD module clock */ - CLK_EnableModuleClock(USBD_MODULE); - - /* Enable USB PHY's LDO33. Run as USB device. */ - SYS->USBPHY = SYS_USBPHY_USBROLE_OTG_V33_EN | SYS_USBPHY_USBROLE_STD_USBD; - -#endif } -#if (MBED_CONF_TARGET_USB_DEVICE_HSUSBD == 0) - -// Conversion macros -#define DESC_TO_LOG(endpoint) ((endpoint) & 0xF) -#define NU_EPH2EPL(ep) ep -#define NU_EPL2EPH(ep) ep -#define HW_TO_DESC(endpoint) (endpoint|(((endpoint&1)?0x0:0x80))) - -/* Global variables for Control Pipe */ -extern uint8_t g_usbd_SetupPacket[]; /*!< Setup packet buffer */ -static volatile uint32_t s_ep_compl = 0; -static volatile uint32_t s_ep_buf_ind = 8; -static volatile uint32_t s_ep0_max_packet_size = 8; -static volatile uint8_t s_usb_addr = 0; -static volatile uint8_t s_ep_data_bit[NUMBER_OF_PHYSICAL_ENDPOINTS] = {1}; -static volatile uint8_t s_ep_mxp[NUMBER_OF_PHYSICAL_ENDPOINTS] = {0}; -extern volatile uint8_t *g_usbd_CtrlInPointer; -extern volatile uint32_t g_usbd_CtrlInSize; -extern volatile uint8_t *g_usbd_CtrlOutPointer; -extern volatile uint32_t g_usbd_CtrlOutSize; -extern volatile uint32_t g_usbd_CtrlOutSizeLimit; -extern volatile uint32_t g_usbd_UsbConfig; -extern volatile uint32_t g_usbd_CtrlMaxPktSize; -extern volatile uint32_t g_usbd_UsbAltInterface; -volatile uint32_t g_usbd_CepTransferLen = 0; -volatile uint32_t frame_cnt = 0; - -USBPhy *get_usb_phy() -{ - static USBPhyHw usbphy; - return &usbphy; -} - -USBPhyHw::USBPhyHw(): events(NULL) -{ - -} - -USBPhyHw::~USBPhyHw() -{ - -} - -/* - Initialize this USBPhy instance. - This function must be called before calling any other functions of this class, unless specifically noted. -*/ -void USBPhyHw::init(USBPhyEvents *events) -{ - if (this->events == NULL) { - sleep_manager_lock_deep_sleep(); - } - this->events = events; - - SYS_UnlockReg(); - - s_ep_buf_ind = 0; - - chip_config(); - - /* Initial USB engine */ - USBD->ATTR = 0x7D0; - - /* Set SE0 (disconnect) */ - USBD_SET_SE0(); - - NVIC_SetVector(USBD_IRQn, (uint32_t) &_usbisr); - NVIC_EnableIRQ(USBD_IRQn); - - instance = this; -} - -void USBPhyHw::deinit() -{ - NVIC_DisableIRQ(USBD_IRQn); - USBD_SET_SE0(); - USBD_DISABLE_PHY(); - - - if (events != NULL) - { - sleep_manager_unlock_deep_sleep(); - } - events = NULL; -} - -/* - Check if USB power is present. - Devices which don't support checking the USB power state must always return true. -*/ -bool USBPhyHw::powered() -{ - return true; -} - -void USBPhyHw::connect() -{ - USBD->STBUFSEG = 0; - - frame_cnt = 0; - - /* EP0 ==> control IN endpoint, address 0 */ - USBD_CONFIG_EP(EP0, USBD_CFG_CSTALL | USBD_CFG_EPMODE_IN | 0); - - /* Buffer range for EP0 */ - USBD_SET_EP_BUF_ADDR(EP0, s_ep_buf_ind); - - /* EP1 ==> control OUT endpoint, address 0 */ - USBD_CONFIG_EP(EP1, USBD_CFG_CSTALL | USBD_CFG_EPMODE_OUT | 0); - - /* Buffer range for EP1 */ - USBD_SET_EP_BUF_ADDR(EP1, s_ep_buf_ind); - - s_ep_buf_ind += s_ep0_max_packet_size; - - /* Disable software-disconnect function */ - USBD_CLR_SE0(); - - /* Clear USB-related interrupts before enable interrupt */ - USBD_CLR_INT_FLAG(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP); - - /* Enable USB-related interrupts. */ - USBD_ENABLE_INT(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP); -} - -/* Make the USB phy visible to the USB host. - Enable either the D+ or D- pullup so the host can detect the presence of this device. */ -void USBPhyHw::disconnect() -{ - /* Set SE0 (disconnect) */ - USBD_SET_SE0(); -} - -/* Set this device to the configured state. - Enable added endpoints if they are not enabled already. */ -void USBPhyHw::configure() -{ - // not needed -} - -/* - Leave the configured state. - This is a notification to the USBPhy indicating that the device is leaving the configured state. The USBPhy can disable all endpoints other than endpoint 0. -*/ -void USBPhyHw::unconfigure() -{ - s_ep_buf_ind = 8; -} - -/* Enable the start of frame interrupt. */ -void USBPhyHw::sof_enable() -{ - -} - -/* Disable the start of frame interrupt. */ -void USBPhyHw::sof_disable() -{ - -} - -/* Set the USBPhy's address. */ -void USBPhyHw::set_address(uint8_t address) -{ - s_usb_addr = address; -} - -/* Wake upstream devices */ -void USBPhyHw::remote_wakeup() -{ - USBD->ATTR |= USBD_ATTR_RWAKEUP_Msk; -} - -/* - Get the endpoint table. - This function returns a table which describes the endpoints can be used, the functionality of those endpoints and the resource cost. -*/ -const usb_ep_table_t *USBPhyHw::endpoint_table() -{ - static const usb_ep_table_t endpoint_table = { - 1, // No cost per endpoint - everything allocated up front - { - {USB_EP_ATTR_ALLOW_CTRL | USB_EP_ATTR_DIR_IN_AND_OUT, 0, 0}, - {USB_EP_ATTR_ALLOW_CTRL | USB_EP_ATTR_DIR_IN_AND_OUT, 0, 0}, - {ALLOW_ALL_EXCEPT_CRTL | USB_EP_ATTR_DIR_IN , 0, 0}, - {ALLOW_ALL_EXCEPT_CRTL | USB_EP_ATTR_DIR_OUT, 0, 0}, - {ALLOW_ALL_EXCEPT_CRTL | USB_EP_ATTR_DIR_IN , 0, 0}, - {ALLOW_ALL_EXCEPT_CRTL | USB_EP_ATTR_DIR_OUT, 0, 0}, - {ALLOW_ALL_EXCEPT_CRTL | USB_EP_ATTR_DIR_IN , 0, 0}, - {ALLOW_ALL_EXCEPT_CRTL | USB_EP_ATTR_DIR_OUT, 0, 0}, -#if (!TARGET_M451) - {ALLOW_ALL_EXCEPT_CRTL | USB_EP_ATTR_DIR_IN , 0, 0}, - {ALLOW_ALL_EXCEPT_CRTL | USB_EP_ATTR_DIR_OUT, 0, 0}, - {ALLOW_ALL_EXCEPT_CRTL | USB_EP_ATTR_DIR_IN , 0, 0}, - {ALLOW_ALL_EXCEPT_CRTL | USB_EP_ATTR_DIR_OUT, 0, 0}, - {ALLOW_ALL_EXCEPT_CRTL | USB_EP_ATTR_DIR_IN , 0, 0}, - {ALLOW_ALL_EXCEPT_CRTL | USB_EP_ATTR_DIR_OUT, 0, 0}, - {ALLOW_NO_ENDPOINTS | USB_EP_ATTR_DIR_IN, 0, 0}, - {ALLOW_NO_ENDPOINTS | USB_EP_ATTR_DIR_OUT, 0, 0}, -#endif - } - }; - return &endpoint_table; -} -/* - Set wMaxPacketSize of endpoint 0. - */ -uint32_t USBPhyHw::ep0_set_max_packet(uint32_t max_packet) -{ - s_ep0_max_packet_size = max_packet; - return s_ep0_max_packet_size; -} - -/* Read the contents of the SETUP packet. */ -void USBPhyHw::ep0_setup_read_result(uint8_t *buffer, uint32_t size) -{ - USBD_MemCopy(g_usbd_SetupPacket, (uint8_t *)USBD_BUF_BASE, 8); - if (buffer) - { - USBD_MemCopy(buffer, g_usbd_SetupPacket, 8); - } - USBD_SET_PAYLOAD_LEN(EP1, s_ep0_max_packet_size); -} - -/* - Start receiving a packet of up to wMaxPacketSize on endpoint 0. -*/ -void USBPhyHw::ep0_read(uint8_t *data, uint32_t size) -{ - read_buffers[0] = data; - read_sizes[0] = size; -} -/* - Read the contents of a received packet. -*/ -uint32_t USBPhyHw::ep0_read_result() -{ - uint32_t i; - uint8_t *buf = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP1)); - uint8_t *buffer = read_buffers[0]; - uint32_t ceprxcnt = USBD_GET_PAYLOAD_LEN(EP1); - for (i = 0; i < ceprxcnt; i ++) - buffer[i] = buf[i]; - USBD_SET_PAYLOAD_LEN(EP1, s_ep0_max_packet_size); - return ceprxcnt; -} - -/* Write a packet on endpoint 0. */ -void USBPhyHw::ep0_write(uint8_t *buffer, uint32_t size) -{ - if (buffer && size) - { - if(s_ep_data_bit[0] & 1) - USBD_SET_DATA1(EP0); - else - USBD_SET_DATA0(EP0); - s_ep_data_bit[0]++; - - USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), buffer, size); - USBD_SET_PAYLOAD_LEN(EP0, size); - if(size < s_ep0_max_packet_size) - s_ep_data_bit[0] = 1; - } - else - { - if(g_usbd_SetupPacket[0] & 0x80) - { - USBD_SET_PAYLOAD_LEN(EP1, 0); - } - else - { - USBD_SET_DATA1(EP0); - USBD_SET_PAYLOAD_LEN(EP0, 0); - } - } -} - -void stallEndpoint(uint8_t endpoint) -{ - uint32_t ep_hw_index = DESC_TO_LOG(endpoint); - if (ep_hw_index >= NUMBER_OF_PHYSICAL_ENDPOINTS) - return; - - USBD_SetStall(NU_EPL2EPH(ep_hw_index)); -} - -/* Protocol stall on endpoint 0. - Stall all IN and OUT packets on endpoint 0 until a setup packet is received. - Note The stall is cleared automatically when a setup packet is received -*/ -void USBPhyHw::ep0_stall() -{ - stallEndpoint(0); - stallEndpoint(1); -} - -/* Configure and enable an endpoint. */ -/* - endpoint Endpoint to configure and enable - max_packet The maximum packet size that can be sent or received - type The type of endpoint this should be configured as - USB_EP_TYPE_BULK, USB_EP_TYPE_INT or USB_EP_TYPE_ISO - This function cannot be used to configure endpoint 0. That must be done with ep0_set_max_packet -*/ -bool USBPhyHw::endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type) -{ - uint32_t ep_type = 0; - uint32_t ep_logic_index = DESC_TO_LOG(endpoint); - uint32_t ep_hw_index = NU_EPL2EPH(ep_logic_index); - uint32_t ep_dir = (endpoint & 0x80) ? USBD_CFG_EPMODE_IN : USBD_CFG_EPMODE_OUT; - - if(type == USB_EP_TYPE_ISO) - ep_type = USBD_CFG_TYPE_ISO; - - USBD_CONFIG_EP(ep_hw_index, ep_dir | ep_type | ep_logic_index); - - /* Buffer range */ - USBD_SET_EP_BUF_ADDR(ep_hw_index, s_ep_buf_ind); - - if(ep_dir == USBD_CFG_EPMODE_OUT) - USBD_SET_PAYLOAD_LEN(ep_hw_index, max_packet); - - s_ep_mxp[ep_logic_index] = max_packet; - - s_ep_buf_ind += max_packet; - - return true; -} - -void USBPhyHw::endpoint_remove(usb_ep_t endpoint) -{ - uint32_t ep_hw_index = NU_EPL2EPH(DESC_TO_LOG(endpoint)); - HSUSBD->EP[ep_hw_index].EPCFG = HSUSBD->EP[ep_hw_index].EPCFG & ~HSUSBD_EP_CFG_VALID; -} - -/* - Perform a functional stall on the given endpoint. - Set the HALT feature for this endpoint so that all further communication is aborted. -*/ -void USBPhyHw::endpoint_stall(usb_ep_t endpoint) -{ - USBD_SetStall(DESC_TO_LOG(endpoint)); -} - -/* - Unstall the endpoint. - Clear the HALT feature on this endpoint so communication can resume. - */ -void USBPhyHw::endpoint_unstall(usb_ep_t endpoint) -{ - uint32_t ep_hw_index = DESC_TO_LOG(endpoint); - if (ep_hw_index >= NUMBER_OF_PHYSICAL_ENDPOINTS) - return; - USBD_ClearStall(NU_EPL2EPH(ep_hw_index)); - -} - -/* Start a read on the given endpoint. */ -bool USBPhyHw::endpoint_read(usb_ep_t endpoint, uint8_t *data, uint32_t size) -{ -/* Store the buffer address & length */ - uint8_t log = NU_EPL2EPH(DESC_TO_LOG(endpoint)); - read_buffers[log] = data; - read_sizes[log] = size; - return true; -} - -/* - Finish a read on the given endpoint - Returns The number of bytes received -*/ -uint32_t USBPhyHw::endpoint_read_result(usb_ep_t endpoint) -{ - uint8_t log = NU_EPL2EPH(DESC_TO_LOG(endpoint)); - - uint32_t bytes_read = 0; - if(endpoint_read_result_core(endpoint, read_buffers[log], read_sizes[log], &bytes_read) == 0) - return 0; - else - { - read_buffers[log] = NULL; - read_sizes[log] = 0; - return bytes_read; - } -} - - -bool USBPhyHw::endpoint_read_result_core(usb_ep_t endpoint, uint8_t *data, uint32_t size, uint32_t *bytes_read) -{ - uint32_t i; - uint32_t ep_hw_index = NU_EPL2EPH(DESC_TO_LOG(endpoint)); - uint8_t *buf = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(ep_hw_index)); - uint32_t eprxcnt = USBD_GET_PAYLOAD_LEN(ep_hw_index); - for (i = 0; i < eprxcnt; i ++) - data[i] = buf[i]; - - *bytes_read = eprxcnt; - - USBD_SET_PAYLOAD_LEN(ep_hw_index,s_ep_mxp[DESC_TO_LOG(endpoint)]); - - return true; -} - -/* - Start a write on the given endpoint. - true if the data was prepared for transmit, false otherwise -*/ -bool USBPhyHw::endpoint_write(usb_ep_t endpoint, uint8_t *data, uint32_t size) -{ - uint32_t ep_logic_index = DESC_TO_LOG(endpoint); - if(ep_logic_index == 0) - return false; - else - { - uint8_t *buf; - uint32_t i=0; - uint32_t ep_hw_index = NU_EPL2EPH(ep_logic_index); - s_ep_compl |= (1 << ep_logic_index); - buf = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(ep_hw_index)); - for(i=0; ireset(); - } - if(u32State & USBD_ATTR_SUSPEND_Msk) - { - /* Enable USB but disable PHY */ - USBD_DISABLE_PHY(); - } - if(u32State & USBD_ATTR_RESUME_Msk) - { - /* Enable USB and enable PHY */ - USBD_ENABLE_USB(); - } - } - - if(u32IntSts & USBD_INTSTS_USBIF_Msk) - { - /* USB event */ - if(u32IntSts & USBD_INTSTS_SETUP_Msk) - { - /* Setup packet */ - /* Clear event flag */ - USBD_CLR_INT_FLAG(USBD_INTSTS_SETUP_Msk); - /* Clear the data IN/OUT ready flag of control end-points */ - USBD_STOP_TRANSACTION(EP0); - USBD_STOP_TRANSACTION(EP1); - events->ep0_setup(); - } - - /* EP events */ - if(u32IntSts & USBD_INTSTS_EP0) - { - /* Clear event flag */ - USBD_CLR_INT_FLAG(USBD_INTSTS_EP0); - /* control IN */ - events->ep0_in(); - - /* In ACK for Set address */ - if((g_usbd_SetupPacket[0] == REQ_STANDARD) && (g_usbd_SetupPacket[1] == USBD_SET_ADDRESS)) - { - if((USBD_GET_ADDR() != s_usb_addr) && (USBD_GET_ADDR() == 0)) - { - USBD_SET_ADDR(s_usb_addr); - } - } - } - if(u32IntSts & USBD_INTSTS_EP1) - { - /* Clear event flag */ - USBD_CLR_INT_FLAG(USBD_INTSTS_EP1); - - /* control OUT */ - events->ep0_out(); - } - - uint32_t gintsts_epx = (u32IntSts >> 18) & 0x3F; - uint32_t ep_hw_index = 2; - while (gintsts_epx) - { - if(gintsts_epx & 0x01) - { - uint32_t ep_status; -#if defined(TARGET_M451) - ep_status = (USBD->EPSTS >> (ep_hw_index * 3 + 8)) & 0x7; -#elif defined(TARGET_NANO100) - if(ep_hw_index < 5) - ep_status = (USBD->EPSTS >> (ep_hw_index * 4) + 8) & 0x7; - else - ep_status = (USBD->EPSTS2 >> ((ep_hw_index - 4) * 4)) & 0x7; -#elif defined(TARGET_M480) || defined(TARGET_M2351) - if(ep_hw_index < 8) - ep_status = (USBD->EPSTS0 >> (ep_hw_index * 4)) & 0x7; - else - ep_status = (USBD->EPSTS1 >> ((ep_hw_index - 8) * 4)) & 0x7; -#endif - /* Clear event flag */ - USBD_CLR_INT_FLAG(1 << (ep_hw_index + 16)); - - if(ep_status == 0x02 || ep_status == 0x06 || (ep_status == 0x07 && (ep_hw_index & 0x01) == 1)) - { /* RX */ - s_ep_compl &= ~(1 << (NU_EPH2EPL(ep_hw_index))); - events->out(HW_TO_DESC(ep_hw_index)); - USBD_SET_PAYLOAD_LEN(ep_hw_index,s_ep_mxp[NU_EPH2EPL(ep_hw_index)]); - } - else if(ep_status == 0x00 || ep_status == 0x07) - { /* TX */ - s_ep_compl &= ~(1 << (NU_EPH2EPL(ep_hw_index))); - events->in(HW_TO_DESC(ep_hw_index)); - } - } - - gintsts_epx = gintsts_epx >> 1; - ep_hw_index++; - } - } -} - -void USBPhyHw::_usbisr(void) -{ - instance->events->start_process(); -} -#else - static volatile int epComplete = 0; -// Conversion macros +/* Conversion macros */ #define DESC_TO_LOG(endpoint) ((endpoint) & 0xF) #define NU_EPH2EPL(ep) ((ep) + 1) #define NU_EPL2EPH(ep) (ep - 1) @@ -699,16 +75,22 @@ static volatile int epComplete = 0; #define HSUSBD_SET_EP_SHORT_PACKET(ep) HSUSBD->EP[ep].EPRSPCTL = ((HSUSBD->EP[ep].EPRSPCTL & 0x10) | 0x40) #define HSUSBD_GET_EP_INT_EN(ep) HSUSBD->EP[ep].EPINTEN +#define USBD_GET_EP_MAX_PAYLOAD(ep) *((__IO uint32_t *) ((uint32_t)&USBD->EPAMPS + (uint32_t)(ep*0x28))) +#define USBD_GET_EP_DATA_COUNT(ep) *((__IO uint32_t *) ((uint32_t)&USBD->EPADATCNT + (uint32_t)(ep*0x28))) +#define USBD_SET_EP_SHORT_PACKET(ep) *((__IO uint32_t *) ((uint32_t)&USBD->EPARSPCTL+(uint32_t)(ep*0x28)))=((*((__IO uint32_t *)((uint32_t)&USBD->EPARSPCTL+(uint32_t)(ep*0x28))) & 0x10) | 0x40) +#define USBD_GET_EP_INT_EN(ep) *((__IO uint32_t *) ((uint32_t)&USBD->EPAINTEN + (uint32_t)(ep*0x28))) + static volatile uint32_t s_ep_compl = 0; static volatile uint32_t s_ep_buf_ind = 0; static volatile uint32_t s_ep0_max_packet_size = 64; static volatile uint8_t s_usb_addr = 0; + static volatile S_HSUSBD_CMD_T s_setup; -static volatile uint16_t s_ctrlin_packetsize; + static volatile uint8_t *g_usbd_CtrlInPointer = 0; static uint32_t g_usbd_CtrlMaxPktSize = 64; -static volatile uint32_t g_usbd_CtrlInSize = 0; -static uint32_t g_usbd_ShortPacket = 0; +static volatile uint32_t g_usb_CtrlInSize = 0; +static uint32_t g_usb_ShortPacket = 0; static uint32_t gEpReadCnt = 0; static uint8_t set_addr = 0; @@ -716,32 +98,30 @@ void HSUSBD_CtrlInput(void) { unsigned volatile i; uint32_t volatile count; - - if(g_usbd_CtrlInSize >= g_usbd_CtrlMaxPktSize) + + if(g_usb_CtrlInSize >= g_usbd_CtrlMaxPktSize) { for (i=0; iCEPDAT_BYTE = *(uint8_t *)(g_usbd_CtrlInPointer++); - HSUSBD_START_CEP_IN(g_usbd_CtrlMaxPktSize); - g_usbd_CtrlInSize -= g_usbd_CtrlMaxPktSize; + HSUSBD->CEPTXCNT = g_usbd_CtrlMaxPktSize; + g_usb_CtrlInSize -= g_usbd_CtrlMaxPktSize; } else { - for (i=0; iCEPDAT_BYTE = *(uint8_t *)(g_usbd_CtrlInPointer++); - HSUSBD_START_CEP_IN(g_usbd_CtrlInSize); + HSUSBD->CEPTXCNT = g_usb_CtrlInSize; g_usbd_CtrlInPointer = 0; - g_usbd_CtrlInSize = 0; + g_usb_CtrlInSize = 0; } } - USBPhy *get_usb_phy() { static USBPhyHw usbphy; return &usbphy; } - USBPhyHw::USBPhyHw(): events(NULL) { } @@ -767,9 +147,8 @@ void USBPhyHw::init(USBPhyEvents *events) chip_config(); - /* Enable USB PHY and wait for it ready */ HSUSBD_ENABLE_PHY(); - + while (1) { HSUSBD->EP[0].EPMPS = 0x20; @@ -779,27 +158,21 @@ void USBPhyHw::init(USBPhyEvents *events) /* Set SE0 (disconnect) */ HSUSBD_SET_SE0(); - -#if defined (TARGET_M480) + NVIC_SetVector(USBD20_IRQn, (uint32_t) &_usbisr); NVIC_EnableIRQ(USBD20_IRQn); -#elif defined (TARGET_NUC472) - NVIC_SetVector(USBD_IRQn, (uint32_t) &_usbisr); - NVIC_EnableIRQ(USBD_IRQn); -#endif + instance = this; } void USBPhyHw::deinit() { -#if defined (TARGET_M480) - NVIC_DisableIRQ(USBD20_IRQn); -#elif defined (TARGET_NUC472) - NVIC_DisableIRQ(USBD_IRQn); -#endif + disconnect(); - USBD_SET_SE0(); - USBD_DISABLE_PHY(); + NVIC_DisableIRQ(USBD20_IRQn); + + HSUSBD_SET_SE0(); + HSUSBD_DISABLE_PHY(); if (events != NULL) { @@ -819,6 +192,9 @@ bool USBPhyHw::powered() void USBPhyHw::connect() { + memset(read_buffers, 0, sizeof(read_buffers)); + memset(read_sizes, 0, sizeof(read_sizes)); + HSUSBD_ResetDMA(); HSUSBD_SET_ADDR(0); @@ -838,11 +214,9 @@ void USBPhyHw::connect() /* Enable BUS interrupt */ HSUSBD_ENABLE_BUS_INT( - HSUSBD_BUSINTEN_DMADONEIEN_Msk | HSUSBD_BUSINTEN_RESUMEIEN_Msk | HSUSBD_BUSINTEN_RSTIEN_Msk | - HSUSBD_BUSINTEN_VBUSDETIEN_Msk | - HSUSBD_BUSINTEN_SOFIEN_Msk + HSUSBD_BUSINTEN_VBUSDETIEN_Msk ); /* Clear SE0 (connect) */ @@ -947,7 +321,7 @@ void USBPhyHw::ep0_setup_read_result(uint8_t *buffer, uint32_t size) s_setup.bRequest = (int8_t) (HSUSBD->SETUP1_0 >> 8) & 0xff; s_setup.wValue = (uint16_t) HSUSBD->SETUP3_2; s_setup.wIndex = (uint16_t) HSUSBD->SETUP5_4; - s_setup.wLength = (uint16_t) HSUSBD->SETUP7_6; + s_setup.wLength = (uint16_t) HSUSBD->SETUP7_6; } /* @@ -959,7 +333,7 @@ void USBPhyHw::ep0_read(uint8_t *data, uint32_t size) { /* Control OUT */ read_buffers[0] = data; - read_sizes[0] = size; + read_sizes[0] = size; HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_SETUPPKIEN_Msk | HSUSBD_CEPINTEN_RXPKIEN_Msk); } else @@ -967,7 +341,7 @@ void USBPhyHw::ep0_read(uint8_t *data, uint32_t size) /* Status stage */ HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk); HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR); - HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk|HSUSBD_CEPINTEN_INTKIEN_Msk); + HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk|HSUSBD_CEPINTEN_INTKIEN_Msk); } } /* @@ -977,10 +351,12 @@ uint32_t USBPhyHw::ep0_read_result() { uint32_t i; uint8_t *ep0_data = read_buffers[0]; + uint32_t ceprxcnt = HSUSBD->CEPRXCNT; for (i = 0; i < ceprxcnt; i ++) ep0_data[i] = HSUSBD->CEPDAT_BYTE; + return ceprxcnt; } @@ -990,14 +366,13 @@ void USBPhyHw::ep0_write(uint8_t *buffer, uint32_t size) if (buffer && size) { g_usbd_CtrlInPointer = buffer; - g_usbd_CtrlInSize = size; + g_usb_CtrlInSize = size; HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_INTKIF_Msk); HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_INTKIEN_Msk); } else { /* Status stage */ - s_ctrlin_packetsize = 0; HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk); HSUSBD_SET_CEP_STATE(HSUSBD_CEPCTL_NAKCLR); HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk); @@ -1006,7 +381,7 @@ void USBPhyHw::ep0_write(uint8_t *buffer, uint32_t size) void stallEndpoint(uint8_t endpoint) { - uint32_t ep_hw_index = NU_EPL2EPH(endpoint); + uint32_t ep_hw_index = NU_EPL2EPH(endpoint); if (ep_hw_index >= NUMBER_OF_PHYSICAL_ENDPOINTS) return; HSUSBD_SetStall(ep_hw_index); @@ -1032,7 +407,7 @@ bool USBPhyHw::endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_ { uint32_t ep_type; uint32_t ep_hw_index = NU_EPL2EPH(DESC_TO_LOG(endpoint)); - + HSUSBD_SetEpBufAddr(ep_hw_index, s_ep_buf_ind, max_packet); s_ep_buf_ind += max_packet; HSUSBD_SET_MAX_PAYLOAD(ep_hw_index, max_packet); @@ -1063,14 +438,15 @@ bool USBPhyHw::endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_ if (ep_dir == 0) HSUSBD_ENABLE_EP_INT(ep_hw_index, HSUSBD_EPINTEN_RXPKIEN_Msk); else - HSUSBD_ENABLE_EP_INT(ep_hw_index, HSUSBD_EPINTEN_TXPKIEN_Msk); + HSUSBD_ENABLE_EP_INT(ep_hw_index, HSUSBD_EPINTEN_TXPKIEN_Msk); return true; } void USBPhyHw::endpoint_remove(usb_ep_t endpoint) { - HSUSBD->EP[NU_EPL2EPH(DESC_TO_LOG(endpoint))].EPCFG = HSUSBD->EP[NU_EPL2EPH(DESC_TO_LOG(endpoint))].EPCFG & ~HSUSBD_EP_CFG_VALID; + uint32_t ep_hw_index = NU_EPL2EPH(DESC_TO_LOG(endpoint)); + HSUSBD->EP[ep_hw_index].EPCFG = HSUSBD->EP[ep_hw_index].EPCFG & ~HSUSBD_EP_CFG_VALID; } /* @@ -1095,7 +471,10 @@ void USBPhyHw::endpoint_unstall(usb_ep_t endpoint) bool USBPhyHw::endpoint_read(usb_ep_t endpoint, uint8_t *data, uint32_t size) { /* Store the buffer address & length */ - uint8_t log = NU_EPL2EPH(DESC_TO_LOG(endpoint)); + uint8_t log = DESC_TO_LOG(endpoint); + if(read_sizes[log]) + return false; + read_req++; read_buffers[log] = data; read_sizes[log] = size; return true; @@ -1107,47 +486,51 @@ bool USBPhyHw::endpoint_read(usb_ep_t endpoint, uint8_t *data, uint32_t size) */ uint32_t USBPhyHw::endpoint_read_result(usb_ep_t endpoint) { - uint8_t log = NU_EPL2EPH(DESC_TO_LOG(endpoint)); + uint8_t log = DESC_TO_LOG(endpoint); uint32_t bytes_read = 0; - if(endpoint_read_result_core(endpoint, read_buffers[log], read_sizes[log], &bytes_read) == 0) - return 0; - else - { - read_buffers[log] = NULL; - read_sizes[log] = 0; - return bytes_read; - } + core_util_critical_section_enter(); + endpoint_read_result_core(endpoint, read_buffers[log], read_sizes[log], &bytes_read); + + read_buffers[log] = 0; + read_sizes[log] = 0; + core_util_critical_section_exit(); + return bytes_read; } +uint32_t volatile buffer, len, i; + bool USBPhyHw::endpoint_read_result_core(usb_ep_t endpoint, uint8_t *data, uint32_t size, uint32_t *bytes_read) { uint8_t log = DESC_TO_LOG(endpoint); + uint32_t tmp; + uint8_t __attribute__((aligned(4))) tmp_buffer[4]; - if (!(s_ep_compl & (1 << DESC_TO_LOG(endpoint)))) +//core_util_critical_section_enter(); + gEpReadCnt = HSUSBD_GET_EP_DATA_COUNT(NU_EPL2EPH(DESC_TO_LOG(endpoint))); + + if(gEpReadCnt == 0) { - while(1) - { - if (!(HSUSBD->DMACTL & HSUSBD_DMACTL_DMAEN_Msk)) - break; - else if (!HSUSBD_IS_ATTACHED()) - break; - } - gEpReadCnt = HSUSBD_GET_EP_DATA_COUNT(NU_EPL2EPH(DESC_TO_LOG(endpoint))); - if(gEpReadCnt == 0) - { - *bytes_read = 0; - return true; - } - s_ep_compl |= (1 << DESC_TO_LOG(endpoint)); - HSUSBD_SET_DMA_LEN(gEpReadCnt); - HSUSBD_SET_DMA_ADDR((uint32_t)data); - HSUSBD_SET_DMA_WRITE(NU_EPL2EPH(DESC_TO_LOG(endpoint))); - HSUSBD_ENABLE_DMA(); + *bytes_read = 0; return true; - } - else + } +#if 0 + for(i=0;iEP[NU_EPL2EPH(DESC_TO_LOG(endpoint))].EPDAT_BYTE ; + else + tmp = HSUSBD->EP[NU_EPL2EPH(DESC_TO_LOG(endpoint))].EPDAT_BYTE ; + } +#else + buffer = (uint32_t)data; + + if(buffer % 4) + { + len = 4 - (buffer % 4); + if(gEpReadCnt <= len) + len = gEpReadCnt; + while(1) { if (!(HSUSBD->DMACTL & HSUSBD_DMACTL_DMAEN_Msk)) @@ -1155,10 +538,46 @@ bool USBPhyHw::endpoint_read_result_core(usb_ep_t endpoint, uint8_t *data, uint3 else if (!HSUSBD_IS_ATTACHED()) break; } - HSUSBD_CLR_BUS_INT_FLAG(HSUSBD_BUSINTSTS_DMADONEIF_Msk); - s_ep_compl &= ~(1 << DESC_TO_LOG(endpoint)); - *bytes_read = gEpReadCnt; + HSUSBD_SET_DMA_LEN(len); + HSUSBD_SET_DMA_ADDR((uint32_t)tmp_buffer); + HSUSBD_SET_DMA_WRITE(DESC_TO_LOG(endpoint)); + HSUSBD_ENABLE_DMA(); + + while(1) + { + if (!(HSUSBD->DMACTL & HSUSBD_DMACTL_DMAEN_Msk)) + break; + else if (!HSUSBD_IS_ATTACHED()) + break; + } + for(i=0;iDMACTL & HSUSBD_DMACTL_DMAEN_Msk)) + break; + else if (!HSUSBD_IS_ATTACHED()) + break; + } + } +#endif + s_ep_compl &= ~(1 << NU_EPL2EPH(DESC_TO_LOG(endpoint))); + *bytes_read = gEpReadCnt; + +//core_util_critical_section_exit(); return true; } @@ -1169,6 +588,7 @@ bool USBPhyHw::endpoint_read_result_core(usb_ep_t endpoint, uint8_t *data, uint3 bool USBPhyHw::endpoint_write(usb_ep_t endpoint, uint8_t *data, uint32_t size) { uint32_t ep_logic_index = DESC_TO_LOG(endpoint); + uint8_t __attribute__((aligned(4))) tmp_buffer[4]; if(ep_logic_index == 0) return false; @@ -1176,18 +596,51 @@ bool USBPhyHw::endpoint_write(usb_ep_t endpoint, uint8_t *data, uint32_t size) { uint32_t ep_hw_index = NU_EPL2EPH(DESC_TO_LOG(endpoint)); uint32_t mps = HSUSBD_GET_EP_MAX_PAYLOAD(ep_hw_index); + uint32_t buffer, len, i; if (size > mps) { return false; } + if(HSUSBD->EP[ep_hw_index].EPDATCNT & 0xFFFF) + { + HSUSBD_SET_EP_SHORT_PACKET(ep_hw_index); + return false; + } if(size < mps) - g_usbd_ShortPacket = 1; + g_usb_ShortPacket = 1; +#if 0 + for(i=0;iEP[ep_hw_index].EPDAT_BYTE = data[i]; +#else + while(1) + { + if (!(HSUSBD->DMACTL & HSUSBD_DMACTL_DMAEN_Msk)) + break; + else if (!HSUSBD_IS_ATTACHED()) + break; + } + buffer = (uint32_t)data; + if(buffer % 4) + { + len = 4 - (buffer % 4); + if(size <= len) + len = size; + for(i=0;iEP[ep_hw_index].EPDAT_BYTE = data[i]; + buffer = buffer + len; + len = size - len; + } + else + len = size; - if (!(s_ep_compl & (1 << ep_logic_index))) + if(len) { s_ep_compl |= (1 << ep_logic_index); - + HSUSBD_SET_DMA_LEN(len); + HSUSBD_SET_DMA_ADDR(buffer); + HSUSBD_SET_DMA_READ(ep_logic_index); + HSUSBD_ENABLE_DMA(); while(1) { if (!(HSUSBD->DMACTL & HSUSBD_DMACTL_DMAEN_Msk)) @@ -1195,11 +648,12 @@ bool USBPhyHw::endpoint_write(usb_ep_t endpoint, uint8_t *data, uint32_t size) else if (!HSUSBD_IS_ATTACHED()) break; } - HSUSBD_SET_DMA_LEN(size); - HSUSBD_SET_DMA_ADDR((uint32_t)data); - HSUSBD_SET_DMA_READ(ep_logic_index); - HSUSBD_ENABLE_DMA(); } +#endif + if(g_usb_ShortPacket) + HSUSBD_SET_EP_SHORT_PACKET(ep_hw_index); + +//core_util_critical_section_exit(); } return true; } @@ -1213,6 +667,9 @@ void USBPhyHw::endpoint_abort(usb_ep_t endpoint) Callback used for performing USB processing. USBPhy processing should be triggered by calling USBPhyEvents::start_process and done inside process. All USBPhyEvents callbacks aside from USBPhyEvents::start_process must be called in the context of process */ + + uint32_t volatile sp_debug = 0; + void USBPhyHw::process() { uint32_t gintsts = HSUSBD->GINTSTS & HSUSBD->GINTEN; @@ -1220,8 +677,9 @@ void USBPhyHw::process() uint32_t ep_hw_index = 0; if (! gintsts) + { return; - + } if (gintsts & HSUSBD_GINTSTS_USBIF_Msk) { uint32_t busintsts = HSUSBD->BUSINTSTS & HSUSBD->BUSINTEN; @@ -1268,16 +726,6 @@ void USBPhyHw::process() /* DMA */ if (busintsts & HSUSBD_BUSINTSTS_DMADONEIF_Msk) { - if(HSUSBD->DMACTL & 0x10) - { /* IN - Read */ - if(g_usbd_ShortPacket) - { - uint32_t ep_hw_index = NU_EPL2EPH((HSUSBD->DMACTL & 0xF)); - HSUSBD_SET_EP_SHORT_PACKET(ep_hw_index); - g_usbd_ShortPacket = 0; - } - s_ep_compl &= ~(1 << (HSUSBD->DMACTL & 0xF)); - } HSUSBD_CLR_BUS_INT_FLAG(HSUSBD_BUSINTSTS_DMADONEIF_Msk); } @@ -1313,6 +761,7 @@ void USBPhyHw::process() if (cepintsts & HSUSBD_CEPINTSTS_SETUPTKIF_Msk) { HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_SETUPTKIF_Msk); + return; } @@ -1321,6 +770,7 @@ void USBPhyHw::process() { HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_SETUPPKIF_Msk); events->ep0_setup(); + return; } @@ -1329,6 +779,7 @@ void USBPhyHw::process() { HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_OUTTKIF_Msk); HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_STSDONEIEN_Msk); + return; } @@ -1347,6 +798,7 @@ void USBPhyHw::process() HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_TXPKIF_Msk); HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_TXPKIEN_Msk|HSUSBD_CEPINTEN_STSDONEIEN_Msk); } + return; } @@ -1354,6 +806,7 @@ void USBPhyHw::process() if (cepintsts & HSUSBD_CEPINTSTS_PINGIF_Msk) { HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_PINGIF_Msk); + return; } @@ -1362,6 +815,7 @@ void USBPhyHw::process() { events->ep0_in(); HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_TXPKIF_Msk); + return; } @@ -1370,6 +824,7 @@ void USBPhyHw::process() { events->ep0_out(); HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_RXPKIF_Msk); + return; } @@ -1377,6 +832,7 @@ void USBPhyHw::process() if (cepintsts & HSUSBD_CEPINTSTS_NAKIF_Msk) { HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_NAKIF_Msk); + return; } @@ -1384,6 +840,7 @@ void USBPhyHw::process() if (cepintsts & HSUSBD_CEPINTSTS_STALLIF_Msk) { HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STALLIF_Msk); + return; } @@ -1391,6 +848,7 @@ void USBPhyHw::process() if (cepintsts & HSUSBD_CEPINTSTS_ERRIF_Msk) { HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_ERRIF_Msk); + return; } @@ -1404,6 +862,7 @@ void USBPhyHw::process() } HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_STSDONEIF_Msk); HSUSBD_ENABLE_CEP_INT(HSUSBD_CEPINTEN_SETUPPKIEN_Msk); + return; } @@ -1411,6 +870,7 @@ void USBPhyHw::process() if (cepintsts & HSUSBD_CEPINTSTS_BUFFULLIF_Msk) { HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_BUFFULLIF_Msk); + return; } @@ -1418,6 +878,7 @@ void USBPhyHw::process() if (cepintsts & HSUSBD_CEPINTSTS_BUFEMPTYIF_Msk) { HSUSBD_CLR_CEP_INT_FLAG(HSUSBD_CEPINTSTS_BUFEMPTYIF_Msk); + return; } } @@ -1426,7 +887,7 @@ void USBPhyHw::process() { if(gintsts_epx & 0x01) { - uint32_t epxintsts = HSUSBD_GET_EP_INT_FLAG(ep_hw_index) & HSUSBD_GET_EP_INT_EN(ep_hw_index); + uint32_t volatile epxintsts = HSUSBD_GET_EP_INT_FLAG(ep_hw_index) & HSUSBD_GET_EP_INT_EN(ep_hw_index); HSUSBD_CLR_EP_INT_FLAG(ep_hw_index, epxintsts); @@ -1448,20 +909,29 @@ void USBPhyHw::process() /* Data Packet Transmitted */ if (epxintsts & HSUSBD_EPINTSTS_TXPKIF_Msk) { - s_ep_compl &= ~(1 << (NU_EPH2EPL(ep_hw_index))); +// s_ep_compl &= ~(1 << (NU_EPH2EPL(ep_hw_index))); events->in(NU_EPH2EPL(ep_hw_index) | EP_DIR_Msk); } /* Data Packet Received */ if (epxintsts & HSUSBD_EPINTSTS_RXPKIF_Msk) { - s_ep_compl &= ~(1 << (NU_EPH2EPL(ep_hw_index))); - events->out(NU_EPH2EPL(ep_hw_index)); + g_ep_index = NU_EPH2EPL(ep_hw_index); + s_ep_compl |= (1 << ep_hw_index); + + if(read_req == 0)//read_buffers[g_ep_index] == 0 && read_sizes[g_ep_index] == 0) + endpoint_read_result(g_ep_index); + else + { + events->out(g_ep_index); + read_req--; + } } /* OUT token packet */ if (epxintsts & HSUSBD_EPINTSTS_OUTTKIF_Msk) - { + { + } /* IN token packet */ @@ -1495,7 +965,7 @@ void USBPhyHw::process() } /* Bulk Out Short Packet Received */ - if (epxintsts & HSUSBD_EPINTSTS_SHORTRXIF_Msk) + if (epxintsts & HSUSBD_EPINTSTS_SHORTRXIF_Msk) { } } @@ -1506,7 +976,11 @@ void USBPhyHw::process() void USBPhyHw::_usbisr(void) { + NVIC_DisableIRQ(USBD20_IRQn); + instance->events->start_process(); + + NVIC_ClearPendingIRQ(USBD20_IRQn); + NVIC_EnableIRQ(USBD20_IRQn); } -#endif