From d284ecaccbfc15b71dbca3e885fff1dc941fdfde Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 20 Nov 2013 12:03:04 +0700 Subject: [PATCH] add sw int_on_complete support for dcd lpc17xx --- tinyusb/device/dcd_lpc175x_6x.c | 177 +++++++++++++++++--------------- tinyusb/device/dcd_lpc175x_6x.h | 1 - 2 files changed, 92 insertions(+), 86 deletions(-) diff --git a/tinyusb/device/dcd_lpc175x_6x.c b/tinyusb/device/dcd_lpc175x_6x.c index 1be282ae5..b14fc9e1a 100644 --- a/tinyusb/device/dcd_lpc175x_6x.c +++ b/tinyusb/device/dcd_lpc175x_6x.c @@ -41,7 +41,6 @@ #if MODE_DEVICE_SUPPORTED && (MCU == MCU_LPC175X_6X) #define _TINY_USB_SOURCE_FILE_ - //--------------------------------------------------------------------+ // INCLUDE //--------------------------------------------------------------------+ @@ -62,6 +61,8 @@ typedef struct { uint8_t ddat[DCD_QHD_MAX]; ///< DMA Descriptor Allocation Table. A fixed DD will be allocated for a UDCA pointer up on endpoint open uint8_t class_code[DCD_QHD_MAX]; + volatile uint32_t ioc_dd; ///< each bit for each DD + }dcd_data_t; STATIC_ dcd_data_t dcd_data TUSB_CFG_ATTR_USBRAM; @@ -70,6 +71,7 @@ STATIC_ dcd_data_t dcd_data TUSB_CFG_ATTR_USBRAM; // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ static void bus_reset(void); +static tusb_error_t pipe_control_read(void * buffer, uint16_t length); //--------------------------------------------------------------------+ // SIE Command @@ -107,6 +109,15 @@ static inline uint32_t sie_read (uint8_t cmd_code, uint8_t data_len) return LPC_USB->USBCmdData; } +//--------------------------------------------------------------------+ +// PIPE HELPER +//--------------------------------------------------------------------+ +static inline uint8_t edpt_addr2phy(uint8_t endpoint_addr) ATTR_CONST ATTR_ALWAYS_INLINE; +static inline uint8_t edpt_addr2phy(uint8_t endpoint_addr) +{ + return 2*(endpoint_addr & 0x0F) + ((endpoint_addr & TUSB_DIR_DEV_TO_HOST_MASK) ? 1 : 0); +} + static inline void edpt_set_max_packet_size(uint8_t ep_id, uint16_t max_packet_size) ATTR_ALWAYS_INLINE; static inline void edpt_set_max_packet_size(uint8_t ep_id, uint16_t max_packet_size) { // follows example in 11.10.4.2 @@ -121,7 +132,24 @@ static inline void edpt_set_max_packet_size(uint8_t ep_id, uint16_t max_packet_s LPC_USB->USBDevIntClr = DEV_INT_ENDPOINT_REALIZED_MASK; } #endif +} +// retval UINT8_MAX: invalid +static inline uint8_t dd_find_free(void) ATTR_PURE ATTR_ALWAYS_INLINE; +static inline uint8_t dd_find_free(void) +{ + for(uint8_t i=0; iUSBEpIntClr = 0xFFFFFFFF; // clear all pending interrupt + LPC_USB->USBDevIntClr = 0xFFFFFFFF; // clear all pending interrupt + LPC_USB->USBEpIntEn = (uint32_t) BIN8(11); // control endpoint cannot use DMA, non-control all use DMA + LPC_USB->USBEpIntPri = 0; // same priority for all endpoint + + // step 8 : DMA set up + LPC_USB->USBEpDMADis = 0xFFFFFFFF; // firstly disable all dma + LPC_USB->USBDMARClr = 0xFFFFFFFF; // clear all pending interrupt + LPC_USB->USBEoTIntClr = 0xFFFFFFFF; + LPC_USB->USBNDDRIntClr = 0xFFFFFFFF; + LPC_USB->USBSysErrIntClr = 0xFFFFFFFF; + + memclr_(&dcd_data, sizeof(dcd_data_t)); +} + +tusb_error_t dcd_init(void) +{ + //------------- user manual 11.13 usb device controller initialization -------------// LPC_USB->USBEpInd = 0; + // step 6 : set up control endpoint + edpt_set_max_packet_size(0, TUSB_CFG_DEVICE_CONTROL_ENDOINT_SIZE); + edpt_set_max_packet_size(1, TUSB_CFG_DEVICE_CONTROL_ENDOINT_SIZE); + + bus_reset(); + + LPC_USB->USBDevIntEn = (DEV_INT_DEVICE_STATUS_MASK | DEV_INT_ENDPOINT_SLOW_MASK | DEV_INT_ERROR_MASK); + LPC_USB->USBUDCAH = (uint32_t) dcd_data.udca; + LPC_USB->USBDMAIntEn = (DMA_INT_END_OF_XFER_MASK | DMA_INT_ERROR_MASK ); + + // clear all stall on control endpoint IN & OUT if any + sie_write(SIE_CMDCODE_ENDPOINT_SET_STATUS , 1, 0); + sie_write(SIE_CMDCODE_ENDPOINT_SET_STATUS+1, 1, 0); + + sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, 1); // connect + + return TUSB_ERROR_NONE; +} -//--------------------------------------------------------------------+ -// IMPLEMENTATION -//--------------------------------------------------------------------+ void endpoint_control_isr(void) { uint32_t const endpoint_int_status = LPC_USB->USBEpIntSt & LPC_USB->USBEpIntEn; @@ -231,15 +296,20 @@ void dcd_isr(uint8_t coreid) p_dd = p_fixed_dd; } - endpoint_handle_t edpt_hdl = + if ( BIT_TEST_(dcd_data.ioc_dd, dd_get_index(p_dd) ) ) { - .coreid = 0, - .index = ep_id, - .class_code = dcd_data.class_code[ep_id] - }; - tusb_event_t event = (p_dd->status == DD_STATUS_NORMAL || p_dd->status == DD_STATUS_DATA_UNDERUN) ? TUSB_EVENT_XFER_COMPLETE : TUSB_EVENT_XFER_ERROR; + dcd_data.ioc_dd = BIT_CLR_(dcd_data.ioc_dd, dd_get_index(p_dd) ); - usbd_xfer_isr(edpt_hdl, event, p_dd->present_count); // only number of bytes in the IOC qtd + endpoint_handle_t edpt_hdl = + { + .coreid = 0, + .index = ep_id, + .class_code = dcd_data.class_code[ep_id] + }; + tusb_event_t event = (p_dd->status == DD_STATUS_NORMAL || p_dd->status == DD_STATUS_DATA_UNDERUN) ? TUSB_EVENT_XFER_COMPLETE : TUSB_EVENT_XFER_ERROR; + + usbd_xfer_isr(edpt_hdl, event, p_dd->present_count); // only number of bytes in the IOC qtd + } } } } @@ -253,48 +323,8 @@ void dcd_isr(uint8_t coreid) } //--------------------------------------------------------------------+ -// USBD-DCD API +// USBD API - CONTROLLER //--------------------------------------------------------------------+ -static void bus_reset(void) -{ - // step 7 : slave mode set up - LPC_USB->USBEpIntClr = 0xFFFFFFFF; // clear all pending interrupt - LPC_USB->USBDevIntClr = 0xFFFFFFFF; // clear all pending interrupt - LPC_USB->USBEpIntEn = (uint32_t) BIN8(11); // control endpoint cannot use DMA, non-control all use DMA - LPC_USB->USBEpIntPri = 0; // same priority for all endpoint - - // step 8 : DMA set up - LPC_USB->USBEpDMADis = 0xFFFFFFFF; // firstly disable all dma - LPC_USB->USBDMARClr = 0xFFFFFFFF; // clear all pending interrupt - LPC_USB->USBEoTIntClr = 0xFFFFFFFF; - LPC_USB->USBNDDRIntClr = 0xFFFFFFFF; - LPC_USB->USBSysErrIntClr = 0xFFFFFFFF; - - memclr_(&dcd_data, sizeof(dcd_data_t)); -} - -tusb_error_t dcd_init(void) -{ - //------------- user manual 11.13 usb device controller initialization -------------// LPC_USB->USBEpInd = 0; - // step 6 : set up control endpoint - edpt_set_max_packet_size(0, TUSB_CFG_DEVICE_CONTROL_ENDOINT_SIZE); - edpt_set_max_packet_size(1, TUSB_CFG_DEVICE_CONTROL_ENDOINT_SIZE); - - bus_reset(); - - LPC_USB->USBDevIntEn = (DEV_INT_DEVICE_STATUS_MASK | DEV_INT_ENDPOINT_SLOW_MASK | DEV_INT_ERROR_MASK); - LPC_USB->USBUDCAH = (uint32_t) dcd_data.udca; - LPC_USB->USBDMAIntEn = (DMA_INT_END_OF_XFER_MASK | DMA_INT_ERROR_MASK ); - - // clear all stall on control endpoint IN & OUT if any - sie_write(SIE_CMDCODE_ENDPOINT_SET_STATUS , 1, 0); - sie_write(SIE_CMDCODE_ENDPOINT_SET_STATUS + 1, 1, 0); - - sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, 1); // connect - - return TUSB_ERROR_NONE; -} - void dcd_controller_connect(uint8_t coreid) { sie_write(SIE_CMDCODE_DEVICE_STATUS, 1, 1); @@ -380,27 +410,6 @@ tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void * return TUSB_ERROR_NONE; } -//--------------------------------------------------------------------+ -// PIPE HELPER -//--------------------------------------------------------------------+ -static inline uint8_t edpt_addr2phy(uint8_t endpoint_addr) ATTR_CONST ATTR_ALWAYS_INLINE; -static inline uint8_t edpt_addr2phy(uint8_t endpoint_addr) -{ - return 2*(endpoint_addr & 0x0F) + ((endpoint_addr & TUSB_DIR_DEV_TO_HOST_MASK) ? 1 : 0); -} - -// retval UINT8_MAX: invalid -static inline uint8_t dd_find_free(void) ATTR_PURE ATTR_ALWAYS_INLINE; -static inline uint8_t dd_find_free(void) -{ - for(uint8_t i=0; iis_retired = 1; - dd_xfer_init(p_dd, buffer, total_bytes); -// p_dd->int_on_complete = 0; - p_dd->is_retired = 1; + dcd_data.ioc_dd = BIT_CLR_(dcd_data.ioc_dd, dcd_data.ddat[edpt_hdl.index] ); // fixed index is stored in ddat return TUSB_ERROR_NONE; } tusb_error_t dcd_pipe_xfer(endpoint_handle_t edpt_hdl, void * buffer, uint16_t total_bytes, bool int_on_complete) { - ASSERT( !dcd_pipe_is_busy(edpt_hdl), TUSB_ERROR_INTERFACE_IS_BUSY); // endpoint must not in transferring - dcd_dma_descriptor_t* const p_fixed_dd = qhd_get_fixed_dd(edpt_hdl.index); if ( p_fixed_dd->buffer_length ) @@ -508,7 +514,7 @@ tusb_error_t dcd_pipe_xfer(endpoint_handle_t edpt_hdl, void * buffer, uint16_t t p_dd->used = 1; p_dd->max_packet_size = p_fixed_dd->max_packet_size; p_dd->is_isochronous = p_fixed_dd->is_isochronous; -// p_dd->int_on_complete = int_on_complete; + dcd_data.ioc_dd = int_on_complete ? BIT_SET_(dcd_data.ioc_dd, dd_idx) : BIT_CLR_(dcd_data.ioc_dd, dd_idx); //------------- hook to fixed dd -------------// p_fixed_dd->next = (uint32_t) p_dd; @@ -516,7 +522,8 @@ tusb_error_t dcd_pipe_xfer(endpoint_handle_t edpt_hdl, void * buffer, uint16_t t } else { // fixed DD is free dd_xfer_init(p_fixed_dd, buffer, total_bytes); -// p_fixed_dd->int_on_complete = int_on_complete; + dcd_data.ioc_dd = int_on_complete ? BIT_SET_(dcd_data.ioc_dd, dcd_data.ddat[edpt_hdl.index]) : + BIT_CLR_(dcd_data.ioc_dd, dcd_data.ddat[edpt_hdl.index]); } p_fixed_dd->is_retired = 0; @@ -526,7 +533,7 @@ tusb_error_t dcd_pipe_xfer(endpoint_handle_t edpt_hdl, void * buffer, uint16_t t LPC_USB->USBEpDMAEn = BIT_(edpt_hdl.index); if ( edpt_hdl.index % 2 ) - { // endpoint IN + { // endpoint IN need to actively raise DMA request LPC_USB->USBDMARSet = BIT_(edpt_hdl.index); } diff --git a/tinyusb/device/dcd_lpc175x_6x.h b/tinyusb/device/dcd_lpc175x_6x.h index 3ee97105d..5ea83b580 100644 --- a/tinyusb/device/dcd_lpc175x_6x.h +++ b/tinyusb/device/dcd_lpc175x_6x.h @@ -77,7 +77,6 @@ typedef struct volatile uint16_t atle_is_msb_extracted : 1; // used in ATLE mode volatile uint16_t atle_message_length_position : 6; // used in ATLE mode uint16_t : 2; -// uint16_t int_on_complete : 1; ///< make use of reserved bit volatile uint16_t present_count; // The number of bytes transferred by the DMA engine. The DMA engine updates this field after completing each packet transfer. //------------- Word 4 -------------//