diff options
Diffstat (limited to 'tinyusb/device/dcd_lpc175x_6x.c')
| -rw-r--r-- | tinyusb/device/dcd_lpc175x_6x.c | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/tinyusb/device/dcd_lpc175x_6x.c b/tinyusb/device/dcd_lpc175x_6x.c index 88ecb1529..19367a88f 100644 --- a/tinyusb/device/dcd_lpc175x_6x.c +++ b/tinyusb/device/dcd_lpc175x_6x.c @@ -47,6 +47,7 @@ //--------------------------------------------------------------------+ #include "dcd.h" #include "dcd_lpc175x_6x.h" +#include "usbd_dcd.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF @@ -56,22 +57,192 @@ STATIC_ dcd_dma_descriptor_t* dcd_udca[32] ATTR_ALIGNED(128) TUSB_CFG_ATTR_USBRA //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ +static inline void endpoint_set_max_packet_size(uint8_t endpoint_idx, uint16_t max_packet_size) ATTR_ALWAYS_INLINE; +static inline void endpoint_set_max_packet_size(uint8_t endpoint_idx, uint16_t max_packet_size) +{ + LPC_USB->USBEpInd = endpoint_idx; // select index before setting packet size + LPC_USB->USBMaxPSize = max_packet_size; +} + +static inline void sie_commamd_code (uint8_t phase, uint8_t code_data) ATTR_ALWAYS_INLINE; +static inline void sie_commamd_code (uint8_t phase, uint8_t code_data) +{ + LPC_USB->USBDevIntClr = (DEV_INT_COMMAND_CODE_EMPTY_MASK | DEV_INT_COMMAND_DATA_FULL_MASK); + LPC_USB->USBCmdCode = (phase << 8) | (code_data << 16); + + uint32_t const wait_flag = (phase == SIE_CMDPHASE_READ) ? DEV_INT_COMMAND_DATA_FULL_MASK : DEV_INT_COMMAND_CODE_EMPTY_MASK; + while ((LPC_USB->USBDevIntSt & wait_flag) == 0); // TODO blocking forever potential + LPC_USB->USBDevIntClr = wait_flag; +} + +static inline void sie_command_write (uint8_t cmd_code, uint8_t data_len, uint8_t data) ATTR_ALWAYS_INLINE; +static inline void sie_command_write (uint8_t cmd_code, uint8_t data_len, uint8_t data) +{ + sie_commamd_code(SIE_CMDPHASE_COMMAND, cmd_code); + + if (data_len) + { + sie_commamd_code(SIE_CMDPHASE_WRITE, data); + } +} + +static inline uint32_t sie_command_read (uint8_t cmd_code, uint8_t data_len) ATTR_ALWAYS_INLINE; +static inline uint32_t sie_command_read (uint8_t cmd_code, uint8_t data_len) +{ + // TODO multiple read + sie_commamd_code(SIE_CMDPHASE_READ, cmd_code); + return LPC_USB->USBCmdData; +} //--------------------------------------------------------------------+ // IMPLEMENTATION //--------------------------------------------------------------------+ +void endpoint_control_isr(uint8_t coreid) +{ + (void) coreid; // suppress compiler warning + uint32_t const endpoint_int_status = LPC_USB->USBEpIntSt & LPC_USB->USBEpIntEn; + + // control OUT + if (endpoint_int_status & BIT_(0)) + { + uint32_t const endpoint_status = sie_command_read(SIE_CMDCODE_ENDPOINT_SELECT+0, 1); + if (endpoint_status & SIE_ENDPOINT_STATUS_SETUP_RECEIVED_MASK) + { + (void) sie_command_read(SIE_CMDCODE_ENDPOINT_SELECT_CLEAR_INTERRUPT+0, 1); // clear setup bit + + // read endpoint + LPC_USB->USBCtrl = SLAVE_CONTROL_READ_ENABLE_MASK; // logical endpoint = 0 + while ((LPC_USB->USBRxPLen & SLAVE_RXPLEN_PACKET_READY_MASK) == 0) {} + + ASSERT_INT(8, LPC_USB->USBRxPLen & SLAVE_RXPLEN_PACKET_LENGTH_MASK, (void) 0); + + uint32_t *p_setup = (uint32_t*) &usbd_devices[0].setup_packet; + *p_setup = LPC_USB->USBRxData; + p_setup += 4; + *p_setup = LPC_USB->USBRxData; + // TODO setup received callback + usbd_isr(0, TUSB_EVENT_SETUP_RECEIVED); + }else + { +// ASSERT(false, (void) 0); // not current supported + } + + sie_command_write(SIE_CMDCODE_BUFFER_CLEAR, 0, 0); + } + + // control IN + if (endpoint_int_status & BIT_(1)) + { + + } + + LPC_USB->USBEpIntClr = endpoint_int_status; // acknowledge interrupt +} + void dcd_isr(uint8_t coreid) { + uint32_t device_int_status = LPC_USB->USBDevIntSt & LPC_USB->USBDevIntEn & DEV_INT_ALL_MASK; + LPC_USB->USBDevIntClr = device_int_status;// Acknowledge handled interrupt + + //------------- usb bus event -------------// + if (device_int_status & DEV_INT_DEVICE_STATUS_MASK) + { + uint32_t dev_status_reg = sie_command_read(SIE_CMDCODE_DEVICE_STATUS, 1); + if (dev_status_reg & SIE_DEV_STATUS_RESET_MASK) + { + usbd_isr(coreid, TUSB_EVENT_BUS_RESET); + } + + // TODO invoke some callbacks + if (dev_status_reg & SIE_DEV_STATUS_CONNECT_CHANGE_MASK) + { + + } + if (dev_status_reg & SIE_DEV_STATUS_SUSPEND_CHANGE_MASK) + { + + } + } + + //------------- slave mode, control endpoint -------------// + if (device_int_status & DEV_INT_ENDPOINT_SLOW_MASK) + { + // only occur on control endpoint, all other use DMA + endpoint_control_isr(coreid); + } + + if (device_int_status & DEV_INT_ERROR_MASK) + { + ASSERT(false, (void) 0); + } } +//--------------------------------------------------------------------+ +// USBD-DCD API +//--------------------------------------------------------------------+ tusb_error_t dcd_init(void) { + //------------- user manual 11.13 usb device controller initialization -------------// LPC_USB->USBEpInd = 0; + // step 6 : set up control endpoint + endpoint_set_max_packet_size(0, TUSB_CFG_DEVICE_CONTROL_PACKET_SIZE); + endpoint_set_max_packet_size(1, TUSB_CFG_DEVICE_CONTROL_PACKET_SIZE); + while ((LPC_USB->USBDevIntSt & DEV_INT_ENDPOINT_REALIZED_MASK) == 0); + + // step 7 : slave mode set up + LPC_USB->USBEpIntEn = (uint32_t) BIN8(11); // control endpoint cannot use DMA, non-control all use DMA + + LPC_USB->USBDevIntEn = (DEV_INT_DEVICE_STATUS_MASK | DEV_INT_ENDPOINT_SLOW_MASK | DEV_INT_ERROR_MASK); + LPC_USB->USBDevIntClr = 0xFFFFFFFF; // clear all pending interrupt + + LPC_USB->USBEpIntClr = 0xFFFFFFFF; // clear all pending interrupt + 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; + + for (uint8_t index = 0; index < DCD_MAX_DD; index++) + { + dcd_udca[index] = 0; + } + LPC_USB->USBUDCAH = (uint32_t) dcd_udca; + LPC_USB->USBDMAIntEn = (DMA_INT_END_OF_XFER_MASK | DMA_INT_NEW_DD_REQUEST_MASK | DMA_INT_ERROR_MASK ); + + // clear all stall on control endpoint IN & OUT if any + sie_command_write(SIE_CMDCODE_ENDPOINT_SET_STATUS , 0, 0); + sie_command_write(SIE_CMDCODE_ENDPOINT_SET_STATUS + 1, 0, 0); + + return TUSB_ERROR_NONE; +} + +tusb_error_t dcd_endpoint_configure(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc) +{ return TUSB_ERROR_NONE; } void dcd_controller_connect(uint8_t coreid) { + sie_command_write(SIE_CMDCODE_DEVICE_STATUS, 1, 1); +} + +void dcd_device_set_address(uint8_t coreid, uint8_t dev_addr) +{ + sie_command_write(SIE_CMDCODE_SET_ADDRESS, 1, 0x80 | dev_addr); // 7th bit is : device_enable +} + +void dcd_pipe_control_write_zero_length(uint8_t coreid) +{ + LPC_USB->USBCtrl = SLAVE_CONTROL_WRITE_ENABLE_MASK; // logical endpoint = 0 + LPC_USB->USBTxPLen = 0; + + LPC_USB->USBCtrl = 0; + sie_command_write(SIE_CMDCODE_ENDPOINT_SELECT+1, 0, 0); // select control IN endpoint + sie_command_write(SIE_CMDCODE_BUFFER_VALIDATE, 0, 0); } + #endif |
