/* * ------------------------------------------------------------------ Copyright (c) 2023 by Lattice Semiconductor Corporation ALL RIGHTS RESERVED ------------------------------------------------------------------ DISCLAIMER: LATTICE MAKES NO WARRANTIES ON THIS FILE OR ITS CONTENTS, WHETHER EXPRESSED, IMPLIED, STATUTORY, OR IN ANY PROVISION OF THE LATTICE PROPEL LICENSE AGREEMENT OR COMMUNICATION WITH LICENSEE, AND LATTICE SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. LATTICE DOES NOT WARRANT THAT THE FUNCTIONS CONTAINED HEREIN WILL MEET LICENSEE 'S REQUIREMENTS, OR THAT LICENSEE' S OPERATION OF ANY DEVICE, SOFTWARE OR SYSTEM USING THIS FILE OR ITS CONTENTS WILL BE UNINTERRUPTED OR ERROR FREE, OR THAT DEFECTS HEREIN WILL BE CORRECTED. LICENSEE ASSUMES RESPONSIBILITY FOR SELECTION OF MATERIALS TO ACHIEVE ITS INTENDED RESULTS, AND FOR THE PROPER INSTALLATION, USE, AND RESULTS OBTAINED THEREFROM. LICENSEE ASSUMES THE ENTIRE RISK OF THE FILE AND ITS CONTENTS PROVING DEFECTIVE OR FAILING TO PERFORM PROPERLY AND IN SUCH EVENT, LICENSEE SHALL ASSUME THE ENTIRE COST AND RISK OF ANY REPAIR, SERVICE, CORRECTION, OR ANY OTHER LIABILITIES OR DAMAGES CAUSED BY OR ASSOCIATED WITH THE SOFTWARE. IN NO EVENT SHALL LATTICE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS FILE OR ITS CONTENTS, EVEN IF LATTICE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. LATTICE 'S SOLE LIABILITY, AND LICENSEE' S SOLE REMEDY, IS SET FORTH ABOVE. LATTICE DOES NOT WARRANT OR REPRESENT THAT THIS FILE, ITS CONTENTS OR USE THEREOF DOES NOT INFRINGE ON THIRD PARTIES' INTELLECTUAL PROPERTY RIGHTS, INCLUDING ANY PATENT. IT IS THE USER' S RESPONSIBILITY TO VERIFY THE USER SOFTWARE DESIGN FOR CONSISTENCY AND FUNCTIONALITY THROUGH THE USE OF FORMAL SOFTWARE VALIDATION METHODS. ------------------------------------------------------------------ * */ #include "event_fifo.h" #include static int ltcusb_event_fifo_read (uint32_t* event_fifo_data_lower, uint32_t* event_fifo_data_higher); static int ltcusb_event_fifo_read (uint32_t* event_fifo_data_lower, uint32_t* event_fifo_data_higher) { if(ltcusb_fifo_read(EVENT_FIFO_ADDR_RV, event_fifo_data_lower) != 0) { return -1; } if(ltcusb_fifo_read(EVENT_FIFO_ADDR_RV, event_fifo_data_higher) != 0) { return -2; } return 0; } Events event(uint8_t* EvtInfo_LinkState, uint8_t* ep, uint32_t event_read) { *EvtInfo_LinkState = 0; *ep = 255; if(BIT_CHECK(event_read,0)) { DEVT_event* device_specific_event = (DEVT_event*)(&event_read); *EvtInfo_LinkState = device_specific_event->EvtInfo_Link_State; return device_specific_event->event_12_8; } else { DEPEVT_event* ep_specific_event = (DEPEVT_event*)(&event_read); *ep = ep_specific_event->physical_endpoint_number; return (0x14+ep_specific_event->event_9_6); } return event_invalid; } int Disconnect_Event() { /* * DCTL Value write. */ DCTL_data* dctl = dctl_setup(); /* * When the application receives a Disconnect event, it must set * DCTL[8:5] to 5. */ dctl-> ULSTCHNGREQ = 0x5; /* * LPM NYET Response Threshold. */ dctl->LPM_NYET_thres = 0xf; /* * This bit clears the interrupts and all the CSRs except GSTS, GSNPSID, * GGPIO, GUID, GUSB2PHYCFGn registers, GUSB3PIPECTLn registers, DCFG, * DCTL, DEVTEN, and DSTS registers. */ dctl->CSFTRST = 0; /* * The software writes 1 to this bit to start the device Controller * operation. */ dctl->RUN_STOP = 0x1; if(dctl_write() != 0) { return -1; } return 0; } int event_while(Events event_to_get,uint8_t EvtInfo_LinkState, uint8_t ep) { uint32_t event_low = 0; uint32_t event_high = 0; if(ltcusb_event_fifo_read(&event_low,&event_high) !=0) { return event_invalid; } Events event_obtained = event(&EvtInfo_LinkState,&ep,event_low); if(event_obtained != event_to_get) { event_obtained = event(&EvtInfo_LinkState,&ep,event_high); if(event_obtained == event_to_get) { if(g_connect_speed == full_speed_usb || g_connect_speed == high_speed_usb) { if(g_simulation_enable) { rv_delay_us(1); } else { rv_delay_us(100); } } return 0; } } while (event_obtained != event_to_get ) { if(ltcusb_event_fifo_read(&event_low,&event_high) !=0) { return event_invalid; } event_obtained = event(&EvtInfo_LinkState,&ep,event_low); if(event_obtained != event_to_get) { event_obtained = event(&EvtInfo_LinkState,&ep,event_high); if(event_obtained == event_to_get) { if(g_connect_speed == full_speed_usb || g_connect_speed == high_speed_usb) { if(g_simulation_enable) { rv_delay_us(1); } else { rv_delay_us(100); } } return 0; } } } if(g_connect_speed == full_speed_usb || g_connect_speed == high_speed_usb) { if(g_simulation_enable) { rv_delay_us(1); } else { rv_delay_us(100); } } return 0; } int event_buffer_size_clear() { uint32_t gevntcount_dev_number = 0; uint32_t event_hndlr_busy = 0; uint32_t event_count; if(gevntcount_get(gevntcount_dev_number, &event_count,&event_hndlr_busy) != 0) { return -1; } if(gevntcount_init(gevntcount_dev_number, event_count,event_hndlr_busy) != 0) { return -2; } return 0; } int event_check(uint32_t event_low, uint32_t event_high, Events event_to_get, uint8_t EvtInfo_LinkState, uint8_t ep) { Events event_obtained = event(&EvtInfo_LinkState,&ep,event_low); if(event_obtained != event_to_get) { event_obtained = event(&EvtInfo_LinkState,&ep,event_high); if(event_obtained != event_to_get) { return -1; } } return 0; } int bulk_interrupt_transfer() { uint32_t data_lower; uint32_t data_higher; /* Reading Data from Event buffer */ if(ltcusb_event_fifo_read(&data_lower,&data_higher)!=0) { return -1; } /*event buffer overflow*/ if (((data_lower & (0x00001F00)) == (0x00000B00)) | ((data_higher & (0x00001F00)) == (0x00000B00))) { if(g_uart_enable) { printf("O\r\n"); } /* Event Buffer Size Clearing */ if(event_buffer_size_clear()!=0) { return -2; } } else if(((data_lower & (0x00000FFF)) == (0x00000001)) | ((data_higher & (0x00000FFF)) == (0x00000001))) { if(g_uart_enable) { printf("X\r\n"); } if(Disconnect_Event()!=0) { return -3; } } /* Interrupt OUT EP 10 */ else if (((data_lower & (0x00000FFF)) == (0x000000D4)) | ((data_higher & (0x00000FFF)) == (0x000000D4))) { if(interrupt_out_ep_10()!=0) { return -4; } } /* Interrupt IN EP 11 */ else if (((data_lower & (0x00000FFF)) == (0x000000D6)) | ((data_higher & (0x00000FFF)) == (0x000000D6))) { if(interrupt_in_ep_11()!=0) { return -5; } } /* Bulk OUT EP 2 */ else if (((data_lower & (0x00000FFF)) == (0x000000C4)) | ((data_higher & (0x00000FFF)) == (0x000000C4))) { if(bulk_out_ep_2()!=0) { return -6; } } /* Bulk IN EP 3 */ else if (((data_lower & (0x00000FFF)) == (0x000000C6)) | ((data_higher & (0x00000FFF)) == (0x000000C6))) { if( bulk_in_ep_3()!=0) { return -7; } } /* Suspend_Resume Mode */ else if (((data_lower & (0x000FFFFF)) == (0x00050301)) | ((data_higher & (0x000FFFFF)) == (0x00050301))) { if(g_uart_enable) { printf("R"); } } /* USB Reset Event Sequence */ else if (((data_lower & (0x00000FFF)) == (0x00000101)) | ((data_higher & (0x00000FFF)) == (0x00000101))) { if(Initialization_on_USB_Reset() !=0) { return -10; } } /* USB Connect Done Event Sequence */ else if (((data_lower & (0x00000FFF)) == (0x00000201)) | ((data_higher & (0x00000FFF)) == (0x00000201))) { if(Initialization_onConnect_Done() !=0) { return -11; } if(g_uart_enable) { printf("C"); } } else { } if(event_buffer_size_clear()!=0) { return -9; } return 0; } int interrupt_out_ep_10() { if( DEPENDXFER_cmd(0) != 0) { return -1; } LtcUSB_TRB interrupt_out_ep10 = {0}; interrupt_out_ep10.BPTRL = INTERRUPT_ADDRESS_USB23; if(g_connect_speed == high_speed_usb) { interrupt_out_ep10.BUFSIZE = INTERRUPT_OUT_HS_DATA_SIZE; } else if (g_connect_speed == full_speed_usb) { interrupt_out_ep10.BUFSIZE = INTERRUPT_OUT_FS_DATA_SIZE; } else { interrupt_out_ep10.BUFSIZE = SS_DATA_SIZE; } interrupt_out_ep10.HWO = 1; interrupt_out_ep10.LST = 1; interrupt_out_ep10.TRBCTL = normal_trbctl; interrupt_out_ep10.IOC = 1; if(ltcusb_trb_write(&interrupt_out_ep10) !=0 ) { return -2; } DEPSTRTXFER_Par1 Depstrtxfer_par1_data = {0}; Depstrtxfer_par1_data.TDAddr_Low = TRB_FIFO_ADDR_USB23; DEPSTRTXFER_Par0 Depstrtxfer_par0_data = {0}; Depstrtxfer_par0_data.TDAddr_High = 0; if(DEPSTRTXFER_cmd(0xa, &Depstrtxfer_par1_data, &Depstrtxfer_par0_data) != 0) { return -3; } /* wait for XferComplete EP10 */ if(event_while(ep_event_XferComplete,0,0xa) != 0) { return -4; } if (g_uart_enable) { printf("IO"); } if(TRB_control_setup() != 0) { return -5; } return 0; } int interrupt_in_ep_11() { if( DEPENDXFER_cmd(0) != 0) { return -1; } LtcUSB_TRB interrupt_in_ep11 = {0}; interrupt_in_ep11.BPTRL = INTERRUPT_ADDRESS_USB23; if(g_connect_speed == high_speed_usb) { interrupt_in_ep11.BUFSIZE = INTERRUPT_IN_HS_DATA_SIZE; } else if(g_connect_speed == full_speed_usb) { interrupt_in_ep11.BUFSIZE = INTERRUPT_IN_FS_DATA_SIZE; } else { interrupt_in_ep11.BUFSIZE = SS_DATA_SIZE; } interrupt_in_ep11.HWO = 1; interrupt_in_ep11.LST = 1; interrupt_in_ep11.TRBCTL = normal_trbctl; interrupt_in_ep11.IOC = 1; if(ltcusb_trb_write(&interrupt_in_ep11) !=0 ) { return -2; } DEPSTRTXFER_Par1 Depstrtxfer_par1_data = {0}; Depstrtxfer_par1_data.TDAddr_Low = TRB_FIFO_ADDR_USB23; DEPSTRTXFER_Par0 Depstrtxfer_par0_data = {0}; Depstrtxfer_par0_data.TDAddr_High = 0; if(DEPSTRTXFER_cmd(0xb, &Depstrtxfer_par1_data, &Depstrtxfer_par0_data) != 0) { return -3; } /* wait for XferComplete EP11 */ if( event_while(ep_event_XferComplete,0,0xb) != 0) { return -4; } if (g_uart_enable) { printf("II"); } if(TRB_control_setup() != 0) { return -5; } return 0; } int bulk_out_ep_2() { if( DEPENDXFER_cmd(0) != 0) { return -1; } LtcUSB_TRB bulk_out_ep2 = {0}; bulk_out_ep2.BPTRL = BULK_ADDRESS_USB23; if(g_connect_speed == high_speed_usb) { bulk_out_ep2.BUFSIZE = BULK_OUT_HS_DATA_SIZE; } else if(g_connect_speed == full_speed_usb) { bulk_out_ep2.BUFSIZE = BULK_OUT_FS_DATA_SIZE; } else { bulk_out_ep2.BUFSIZE = SS_DATA_SIZE; } bulk_out_ep2.HWO = 1; bulk_out_ep2.LST = 1; bulk_out_ep2.TRBCTL = normal_trbctl; bulk_out_ep2.IOC = 1; if(ltcusb_trb_write(&bulk_out_ep2) !=0 ) { return -2; } DEPSTRTXFER_Par1 Depstrtxfer_par1_data = {0}; Depstrtxfer_par1_data.TDAddr_Low = TRB_FIFO_ADDR_USB23; DEPSTRTXFER_Par0 Depstrtxfer_par0_data = {0}; Depstrtxfer_par0_data.TDAddr_High = 0; if(DEPSTRTXFER_cmd(0x2, &Depstrtxfer_par1_data, &Depstrtxfer_par0_data) != 0) { return -3; } /* wait for XferComplete EP2 */ if(event_while(ep_event_XferComplete,0,0x2) != 0) { return -4; } if (g_uart_enable) { printf("BO"); } if(TRB_control_setup() != 0) { return -5; } return 0; } int bulk_in_ep_3() { if( DEPENDXFER_cmd(0) != 0) { return -1; } LtcUSB_TRB bulk_in_ep3 = {0}; bulk_in_ep3.BPTRL = BULK_ADDRESS_USB23; if(g_connect_speed == high_speed_usb) { bulk_in_ep3.BUFSIZE = BULK_IN_HS_DATA_SIZE; } else if(g_connect_speed == full_speed_usb) { bulk_in_ep3.BUFSIZE = BULK_IN_FS_DATA_SIZE; } else { bulk_in_ep3.BUFSIZE = SS_DATA_SIZE; } bulk_in_ep3.HWO = 1; bulk_in_ep3.LST = 1; bulk_in_ep3.TRBCTL = normal_trbctl; bulk_in_ep3.IOC = 1; if(ltcusb_trb_write(&bulk_in_ep3) !=0 ) { return -2; } DEPSTRTXFER_Par1 Depstrtxfer_par1_data = {0}; Depstrtxfer_par1_data.TDAddr_Low = TRB_FIFO_ADDR_USB23; DEPSTRTXFER_Par0 Depstrtxfer_par0_data = {0}; Depstrtxfer_par0_data.TDAddr_High = 0; if(DEPSTRTXFER_cmd(0x3, &Depstrtxfer_par1_data, &Depstrtxfer_par0_data) != 0) { return -3; } /* wait for XferComplete EP3 */ if( event_while(ep_event_XferComplete,0,0x3) != 0) { return -4; } if (g_uart_enable) { printf("BI"); } if(TRB_control_setup() != 0) { return -5; } return 0; }