diff options
| author | hathach <[email protected]> | 2013-11-20 12:03:04 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2013-11-20 12:03:04 +0700 |
| commit | d284ecaccbfc15b71dbca3e885fff1dc941fdfde (patch) | |
| tree | be245c65f205870dbe0556a3068cf98b8a8e9c47 /tinyusb/device | |
| parent | 2dafeee585e0a90675359e83de4e197c84cd3f5d (diff) | |
add sw int_on_complete support for dcd lpc17xx
Diffstat (limited to 'tinyusb/device')
| -rw-r--r-- | tinyusb/device/dcd_lpc175x_6x.c | 175 | ||||
| -rw-r--r-- | tinyusb/device/dcd_lpc175x_6x.h | 1 |
2 files changed, 91 insertions, 85 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; i<DCD_QTD_MAX; i++) + { + if (dcd_data.dd[i].used == 0) return i; + } + + return UINT8_MAX; +} + +static inline uint8_t dd_get_index(dcd_dma_descriptor_t const * const p_dd) ATTR_PURE ATTR_ALWAYS_INLINE; +static inline uint8_t dd_get_index(dcd_dma_descriptor_t const * const p_dd) +{ + return (p_dd - dcd_data.dd); } static inline dcd_dma_descriptor_t* qhd_get_fixed_dd(uint8_t ep_id) ATTR_PURE ATTR_ALWAYS_INLINE; @@ -130,12 +158,49 @@ static inline dcd_dma_descriptor_t* qhd_get_fixed_dd(uint8_t ep_id) return &dcd_data.dd[ dcd_data.ddat[ep_id] ]; } -static tusb_error_t pipe_control_write(void const * buffer, uint16_t length); -static tusb_error_t pipe_control_read(void * buffer, uint16_t length); - //--------------------------------------------------------------------+ -// IMPLEMENTATION +// USBD-DCD API //--------------------------------------------------------------------+ +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 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) ); + + 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 + 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); @@ -381,27 +411,6 @@ tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void * } //--------------------------------------------------------------------+ -// 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; i<DCD_QTD_MAX; i++) - { - if (dcd_data.dd[i].used == 0) return i; - } - - return UINT8_MAX; -} - -//--------------------------------------------------------------------+ // BULK/INTERRUPT/ISO PIPE API //--------------------------------------------------------------------+ endpoint_handle_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc, uint8_t class_code) @@ -477,21 +486,18 @@ void dd_xfer_init(dcd_dma_descriptor_t* p_dd, void* buffer, uint16_t total_bytes tusb_error_t dcd_pipe_queue_xfer(endpoint_handle_t edpt_hdl, void * buffer, uint16_t total_bytes) { // NOTE for sure the qhd has no dds - 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); // always queue with the fixed DD - dcd_dma_descriptor_t* const p_dd = qhd_get_fixed_dd(edpt_hdl.index); // always queue with the fixed DD + dd_xfer_init(p_fixed_dd, buffer, total_bytes); + p_fixed_dd->is_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 -------------// |
