Działająca myszka
Fork of USBDevice by
USBDevice/USBHAL_RZ_A1H.cpp
- Committer:
- mbed_official
- Date:
- 2014-11-06
- Revision:
- 36:4d3e7f3d5211
- Parent:
- 35:a8484e16c2f3
- Child:
- 40:3b1c43ac045c
File content as of revision 36:4d3e7f3d5211:
/* Copyright (c) 2010-2011 mbed.org, MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if defined(TARGET_RZ_A1H) /* This class can use the pipe1, pipe3 and pipe6 only. You should re-program this class if you wanted to use other pipe. */ /*************************************************************************/ extern "C" { #include "r_typedefs.h" #include "iodefine.h" } #include "USBHAL.h" #include "devdrv_usb_function_api.h" #include "usb0_function.h" #include "usb_iobitmask.h" #include "rza_io_regrw.h" #include "USBDevice_Types.h" /*************************************************************************/ /* constants */ const struct PIPECFGREC { uint16_t endpoint; uint16_t pipesel; uint16_t pipecfg; uint16_t pipebuf; uint16_t pipemaxp; uint16_t pipeperi; } def_pipecfg[] = { /*EP0OUT and EP0IN are configured by USB IP*/ { EP1OUT, /*EP1: Host -> Func, INT*/ 6 | USB_FUNCTION_D0FIFO_USE, USB_FUNCTION_INTERRUPT | USB_FUNCTION_BFREOFF | USB_FUNCTION_DBLBOFF | USB_FUNCTION_CNTMDON | USB_FUNCTION_SHTNAKOFF | USB_FUNCTION_DIR_P_OUT | USB_FUNCTION_EP1, ( ( ( 64) / 64 - 1 ) << 10 ) | 0x04u, 64, DEVDRV_USBF_OFF | 0, }, { EP1IN, /*EP1: Host <- Func, INT*/ 7 | USB_FUNCTION_D1FIFO_USE, USB_FUNCTION_INTERRUPT | USB_FUNCTION_BFREOFF | USB_FUNCTION_DBLBOFF | USB_FUNCTION_CNTMDOFF | USB_FUNCTION_SHTNAKOFF | USB_FUNCTION_DIR_P_IN | USB_FUNCTION_EP1, ( ( ( 64) / 64 - 1 ) << 10 ) | 0x05u, 64, DEVDRV_USBF_OFF | 0, }, { EP2OUT, /*EP2: Host -> Func, BULK*/ 3 | USB_FUNCTION_D0FIFO_USE, USB_FUNCTION_BULK | USB_FUNCTION_BFREOFF | USB_FUNCTION_DBLBON | USB_FUNCTION_CNTMDON | USB_FUNCTION_SHTNAKON | USB_FUNCTION_DIR_P_OUT | USB_FUNCTION_EP2, ( ( (2048) / 64 - 1 ) << 10 ) | 0x30u, 512, DEVDRV_USBF_OFF | 0, }, { EP2IN, /*EP2: Host <- Func, BULK*/ 4 | USB_FUNCTION_D1FIFO_USE, USB_FUNCTION_BULK | USB_FUNCTION_BFREOFF | USB_FUNCTION_DBLBOFF | USB_FUNCTION_CNTMDON | USB_FUNCTION_SHTNAKOFF | USB_FUNCTION_DIR_P_IN | USB_FUNCTION_EP2, ( ( (2048) / 64 - 1 ) << 10 ) | 0x50u, 512, DEVDRV_USBF_OFF | 0, }, { EP3OUT, /*EP3: Host -> Func, ISO*/ 1 | USB_FUNCTION_D0FIFO_USE, USB_FUNCTION_ISO | USB_FUNCTION_BFREOFF | USB_FUNCTION_DBLBON | USB_FUNCTION_CNTMDON | USB_FUNCTION_SHTNAKON | USB_FUNCTION_DIR_P_OUT | USB_FUNCTION_EP3, ( ( (1024) / 64 - 1 ) << 10 ) | 0x10u, 192, DEVDRV_USBF_OFF | 1, }, { EP3IN, /*EP3: Host <- Func, ISO*/ 2 | USB_FUNCTION_D1FIFO_USE, USB_FUNCTION_ISO | USB_FUNCTION_BFREOFF | USB_FUNCTION_DBLBON | USB_FUNCTION_CNTMDON | USB_FUNCTION_SHTNAKOFF | USB_FUNCTION_DIR_P_IN | USB_FUNCTION_EP3, ( ( (1024) / 64 - 1 ) << 10 ) | 0x20u, 192, DEVDRV_USBF_OFF | 1, }, { /*terminator*/ 0, 0, 0, 0, 0, }, }; /*************************************************************************/ /* workareas */ USBHAL * USBHAL::instance; static IRQn_Type int_id; /* interrupt ID */ static uint16_t int_level; /* initerrupt level */ static uint16_t clock_mode; /* input clock selector */ static uint16_t mode; /* USB speed (HIGH/FULL) */ static DigitalOut *usb0_en; static uint16_t EP0_read_status; static uint16_t EPx_read_status; static uint16_t setup_buffer[MAX_PACKET_SIZE_EP0 / 2]; /* 0: not used / other: a pipe number to use recv_buffer*/ static uint8_t recv_buffer[MAX_PACKET_SIZE_EPBULK]; volatile static uint16_t recv_error; /*************************************************************************/ /* prototypes for C */ /* This C++ functions changed to macro functions. static uint32_t EP2PIPE(uint8_t endpoint); static void usb0_function_save_request(void); void usb0_function_BRDYInterrupt(uint16_t status, uint16_t intenb); void usb0_function_NRDYInterrupt (uint16_t status, uint16_t intenb); void usb0_function_BEMPInterrupt (uint16_t status, uint16_t intenb); */ /*************************************************************************/ /* macros */ /****************************************************************************** * Function Name: usb0_function_BRDYInterruptPIPE0 * Description : Executes BRDY interrupt for pipe0. * Arguments : uint16_t status ; BRDYSTS Register Value * : uint16_t intenb ; BRDYENB Register Value * Return Value : none *****************************************************************************/ #define usb0_function_BRDYInterruptPIPE0(status, intenb) \ { \ volatile uint16_t dumy_sts; \ uint16_t read_status; \ \ USB200.BRDYSTS = \ (uint16_t)~g_usb0_function_bit_set[USB_FUNCTION_PIPE0]; \ RZA_IO_RegWrite_16( \ &USB200.CFIFOSEL, USB_FUNCTION_PIPE0, \ USB_CFIFOSEL_CURPIPE_SHIFT, USB_CFIFOSEL_CURPIPE); \ \ g_usb0_function_PipeDataSize[USB_FUNCTION_PIPE0] = \ g_usb0_function_data_count[USB_FUNCTION_PIPE0]; \ \ read_status = usb0_function_read_buffer_c(USB_FUNCTION_PIPE0); \ \ g_usb0_function_PipeDataSize[USB_FUNCTION_PIPE0] -= \ g_usb0_function_data_count[USB_FUNCTION_PIPE0]; \ \ switch (read_status) { \ case USB_FUNCTION_READING: /* Continue of data read */ \ case USB_FUNCTION_READEND: /* End of data read */ \ /* PID = BUF */ \ usb0_function_set_pid_buf(USB_FUNCTION_PIPE0); \ \ /*callback*/ \ EP0out(); \ break; \ \ case USB_FUNCTION_READSHRT: /* End of data read */ \ usb0_function_disable_brdy_int(USB_FUNCTION_PIPE0); \ /* PID = BUF */ \ usb0_function_set_pid_buf(USB_FUNCTION_PIPE0); \ \ /*callback*/ \ EP0out(); \ break; \ \ case USB_FUNCTION_READOVER: /* FIFO access error */ \ /* Buffer Clear */ \ USB200.CFIFOCTR = USB_FUNCTION_BITBCLR; \ usb0_function_disable_brdy_int(USB_FUNCTION_PIPE0); \ /* Req Error */ \ usb0_function_set_pid_stall(USB_FUNCTION_PIPE0); \ \ /*callback*/ \ EP0out(); \ break; \ \ case DEVDRV_USBF_FIFOERROR: /* FIFO access error */ \ default: \ usb0_function_disable_brdy_int(USB_FUNCTION_PIPE0); \ /* Req Error */ \ usb0_function_set_pid_stall(USB_FUNCTION_PIPE0); \ break; \ } \ /* Three dummy reads for clearing interrupt requests */ \ dumy_sts = USB200.BRDYSTS; \ } /****************************************************************************** * Function Name: usb0_function_BRDYInterrupt * Description : Executes BRDY interrupt uxclude pipe0. * Arguments : uint16_t status ; BRDYSTS Register Value * : uint16_t intenb ; BRDYENB Register Value * Return Value : none *****************************************************************************/ #define usb0_function_BRDYInterrupt(status, intenb) \ { \ volatile uint16_t dumy_sts; \ \ /************************************************************** \ * Function Name: usb0_function_brdy_int \ * Description : Executes BRDY interrupt(USB_FUNCTION_PIPE1-9). \ * : According to the pipe that interrupt is generated in, \ * : reads/writes buffer allocated in the pipe. \ * : This function is executed in the BRDY \ * : interrupt handler. This function \ * : clears BRDY interrupt status and BEMP \ * : interrupt status. \ * Arguments : uint16_t Status ; BRDYSTS Register Value \ * : uint16_t Int_enbl ; BRDYENB Register Value \ * Return Value : none \ *************************************************************/ \ /* copied from usb0_function_intrn.c */ \ uint32_t int_sense = 0; \ uint16_t pipe; \ uint16_t pipebit; \ uint16_t ep; \ \ for (pipe = USB_FUNCTION_PIPE1; pipe <= USB_FUNCTION_MAX_PIPE_NO; pipe++) { \ pipebit = g_usb0_function_bit_set[pipe]; \ \ if ((status & pipebit) && (intenb & pipebit)) { \ USB200.BRDYSTS = (uint16_t)~pipebit; \ USB200.BEMPSTS = (uint16_t)~pipebit; \ \ switch (g_usb0_function_PipeTbl[pipe] & USB_FUNCTION_FIFO_USE) { \ case USB_FUNCTION_D0FIFO_DMA: \ if (g_usb0_function_DmaStatus[USB_FUNCTION_D0FIFO] != USB_FUNCTION_DMA_READY) { \ /*now, DMA is not supported*/ \ usb0_function_dma_interrupt_d0fifo(int_sense); \ } \ \ if (RZA_IO_RegRead_16( \ &g_usb0_function_pipecfg[pipe], USB_PIPECFG_BFRE_SHIFT, USB_PIPECFG_BFRE) == 0) { \ /*now, DMA is not supported*/ \ usb0_function_read_dma(pipe); \ usb0_function_disable_brdy_int(pipe); \ } else { \ USB200.D0FIFOCTR = USB_FUNCTION_BITBCLR; \ g_usb0_function_pipe_status[pipe] = DEVDRV_USBF_PIPE_DONE; \ } \ break; \ \ case USB_FUNCTION_D1FIFO_DMA: \ if (g_usb0_function_DmaStatus[USB_FUNCTION_D1FIFO] != USB_FUNCTION_DMA_READY) { \ /*now, DMA is not supported*/ \ usb0_function_dma_interrupt_d1fifo(int_sense); \ } \ \ if (RZA_IO_RegRead_16( \ &g_usb0_function_pipecfg[pipe], USB_PIPECFG_BFRE_SHIFT, USB_PIPECFG_BFRE) == 0) { \ /*now, DMA is not supported*/ \ usb0_function_read_dma(pipe); \ usb0_function_disable_brdy_int(pipe); \ } else { \ USB200.D1FIFOCTR = USB_FUNCTION_BITBCLR; \ g_usb0_function_pipe_status[pipe] = DEVDRV_USBF_PIPE_DONE; \ } \ break; \ \ default: \ ep = (g_usb0_function_pipecfg[pipe] & USB_PIPECFG_EPNUM) >> USB_PIPECFG_EPNUM_SHIFT; \ ep <<= 1; \ ep += (RZA_IO_RegRead_16(&g_usb0_function_pipecfg[pipe], USB_PIPECFG_DIR_SHIFT, USB_PIPECFG_DIR) == 0)? \ (0): (1); \ EPx_read_status = DEVDRV_USBF_PIPE_WAIT; \ (instance->*(epCallback[ep - 2])) (); \ EPx_read_status = DEVDRV_USBF_PIPE_DONE; \ } \ } \ } \ /* Three dummy reads for clearing interrupt requests */ \ dumy_sts = USB200.BRDYSTS; \ } /****************************************************************************** * Function Name: usb0_function_NRDYInterruptPIPE0 * Description : Executes NRDY interrupt for pipe0. * Arguments : uint16_t status ; NRDYSTS Register Value * : uint16_t intenb ; NRDYENB Register Value * Return Value : none *****************************************************************************/ #define usb0_function_NRDYInterruptPIPE0(status, intenb) \ { \ volatile uint16_t dumy_sts; \ \ USB200.NRDYSTS = \ (uint16_t)~g_usb0_function_bit_set[USB_FUNCTION_PIPE0]; \ \ /* Three dummy reads for clearing interrupt requests */ \ dumy_sts = USB200.NRDYSTS; \ } /****************************************************************************** * Function Name: usb0_function_NRDYInterrupt * Description : Executes NRDY interrupt exclude pipe0. * Arguments : uint16_t status ; NRDYSTS Register Value * : uint16_t intenb ; NRDYENB Register Value * Return Value : none *****************************************************************************/ #define usb0_function_NRDYInterrupt(status, intenb) \ { \ volatile uint16_t dumy_sts; \ \ usb0_function_nrdy_int(status, intenb); \ \ /* Three dummy reads for clearing interrupt requests */ \ dumy_sts = USB200.NRDYSTS; \ } /****************************************************************************** * Function Name: usb0_function_BEMPInterruptPIPE0 * Description : Executes BEMP interrupt for pipe0. * Arguments : uint16_t status ; BEMPSTS Register Value * : uint16_t intenb ; BEMPENB Register Value * Return Value : none *****************************************************************************/ #define usb0_function_BEMPInterruptPIPE0(status, intenb) \ { \ volatile uint16_t dumy_sts; \ \ USB200.BEMPSTS = \ (uint16_t)~g_usb0_function_bit_set[USB_FUNCTION_PIPE0]; \ RZA_IO_RegWrite_16( \ &USB200.CFIFOSEL, USB_FUNCTION_PIPE0, \ USB_CFIFOSEL_CURPIPE_SHIFT, USB_CFIFOSEL_CURPIPE); \ \ /*usb0_function_write_buffer_c(USB_FUNCTION_PIPE0);*/ \ EP0in(); \ \ /* Three dummy reads for clearing interrupt requests */ \ dumy_sts = USB200.BEMPSTS; \ } /****************************************************************************** * Function Name: usb0_function_BEMPInterrupt * Description : Executes BEMP interrupt exclude pipe0. * Arguments : uint16_t status ; BEMPSTS Register Value * : uint16_t intenb ; BEMPENB Register Value * Return Value : none *****************************************************************************/ #define usb0_function_BEMPInterrupt(status, intenb) \ { \ volatile uint16_t dumy_sts; \ \ usb0_function_bemp_int(status, intenb); \ \ /* Three dummy reads for clearing interrupt requests */ \ dumy_sts = USB200.BEMPSTS; \ } /****************************************************************************** * Function Name: EP2PIPE * Description : Converts from endpoint to pipe * Arguments : number of endpoint * Return Value : number of pipe *****************************************************************************/ /*EP2PIPE converter is for pipe1, pipe3 and pipe6 only.*/ #define EP2PIPE(endpoint) ((uint32_t)usb0_function_EpToPipe(endpoint)) /****************************************************************************** * Function Name: usb0_function_save_request * Description : Retains the USB request information in variables. * Arguments : none * Return Value : none *****************************************************************************/ #define usb0_function_save_request() \ { \ uint16_t *bufO = &setup_buffer[0]; \ \ USB200.INTSTS0 = (uint16_t)~USB_FUNCTION_BITVALID; \ /*data[0] <= bmRequest, data[1] <= bmRequestType */ \ *bufO++ = USB200.USBREQ; \ /*data[2] data[3] <= wValue*/ \ *bufO++ = USB200.USBVAL; \ /*data[4] data[5] <= wIndex*/ \ *bufO++ = USB200.USBINDX; \ /*data[6] data[6] <= wIndex*/ \ *bufO++ = USB200.USBLENG; \ } /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* constructor */ USBHAL::USBHAL(void) { /* ---- P4_1 : P4_1 (USB0_EN for GR-PEACH) ---- */ usb0_en = new DigitalOut(P4_1, 1); /* some constants */ int_id = USBI0_IRQn; int_level = ( 2 << 3 ); clock_mode = USBFCLOCK_X1_48MHZ; mode = USB_FUNCTION_HIGH_SPEED; EP0_read_status = DEVDRV_USBF_WRITEEND; EPx_read_status = DEVDRV_USBF_PIPE_DONE; /* Disables interrupt for usb */ GIC_DisableIRQ(int_id); /* Setup the end point */ epCallback[ 0] = &USBHAL::EP1_OUT_callback; epCallback[ 1] = &USBHAL::EP1_IN_callback; epCallback[ 2] = &USBHAL::EP2_OUT_callback; epCallback[ 3] = &USBHAL::EP2_IN_callback; epCallback[ 4] = &USBHAL::EP3_OUT_callback; epCallback[ 5] = &USBHAL::EP3_IN_callback; epCallback[ 6] = &USBHAL::EP4_OUT_callback; epCallback[ 7] = &USBHAL::EP4_IN_callback; epCallback[ 8] = &USBHAL::EP5_OUT_callback; epCallback[ 9] = &USBHAL::EP5_IN_callback; epCallback[10] = &USBHAL::EP6_OUT_callback; epCallback[11] = &USBHAL::EP6_IN_callback; epCallback[12] = &USBHAL::EP7_OUT_callback; epCallback[13] = &USBHAL::EP7_IN_callback; epCallback[14] = &USBHAL::EP8_OUT_callback; epCallback[15] = &USBHAL::EP8_IN_callback; epCallback[16] = &USBHAL::EP9_OUT_callback; epCallback[17] = &USBHAL::EP9_IN_callback; epCallback[18] = &USBHAL::EP10_OUT_callback; epCallback[19] = &USBHAL::EP10_IN_callback; epCallback[20] = &USBHAL::EP11_OUT_callback; epCallback[21] = &USBHAL::EP11_IN_callback; epCallback[22] = &USBHAL::EP12_OUT_callback; epCallback[23] = &USBHAL::EP12_IN_callback; epCallback[24] = &USBHAL::EP13_OUT_callback; epCallback[25] = &USBHAL::EP13_IN_callback; epCallback[26] = &USBHAL::EP14_OUT_callback; epCallback[27] = &USBHAL::EP14_IN_callback; epCallback[28] = &USBHAL::EP15_OUT_callback; epCallback[29] = &USBHAL::EP15_IN_callback; /* registers me */ instance = this; /* Clear pipe table */ usb0_function_clear_pipe_tbl(); /****************************************************************************** * Function Name: usb0_api_function_init * Description : Initializes the USB module in the USB function mode. *****************************************************************************/ /* The clock of USB0 modules is permitted */ CPG.STBCR7 &= ~(CPG_STBCR7_MSTP71); volatile uint8_t dummy8; dummy8 = CPG.STBCR7; { /****************************************************************************** * Function Name: usb0_function_setting_interrupt * Description : Sets the USB module interrupt level. *****************************************************************************/ #if 0 /*DMA is not supported*/ IRQn_Type d0fifo_dmaintid; IRQn_Type d1fifo_dmaintid; #endif InterruptHandlerRegister(int_id, &_usbisr); GIC_SetPriority(int_id, int_level); GIC_EnableIRQ(int_id); #if 0 /*DMA is not supported*/ d0fifo_dmaintid = Userdef_USB_usb0_function_d0fifo_dmaintid(); if (d0fifo_dmaintid != 0xFFFF) { InterruptHandlerRegister(d0fifo_dmaintid, usb0_function_dma_interrupt_d0fifo); GIC_SetPriority(d0fifo_dmaintid, int_level); GIC_EnableIRQ(d0fifo_dmaintid); } #endif #if 0 /*DMA is not supported*/ d1fifo_dmaintid = Userdef_USB_usb0_function_d1fifo_dmaintid(); if (d1fifo_dmaintid != 0xFFFF) { InterruptHandlerRegister(d1fifo_dmaintid, usb0_function_dma_interrupt_d1fifo); GIC_SetPriority(d1fifo_dmaintid, int_level); GIC_EnableIRQ(d1fifo_dmaintid); } #endif /*****************************************************************************/ } /* reset USB module with setting tranciever and HSE=1 */ usb0_function_reset_module(clock_mode); /* clear variables */ usb0_function_init_status(); /* select USB Function and Interrupt Enable */ /* Detect USB Device to attach or detach */ usb0_function_InitModule(mode); { uint16_t buf; buf = USB200.INTENB0; buf |= USB_INTENB0_SOFE; USB200.INTENB0 = buf; } } /*************************************************************************/ USBHAL::~USBHAL(void) { /* Disables interrupt for usb */ GIC_DisableIRQ( int_id ); /* Unregisters interrupt function and priority */ InterruptHandlerRegister( int_id, (uint32_t)NULL ); usb0_en = NULL; instance = NULL; } /*************************************************************************/ void USBHAL::connect(void) { /* Activates USB0_EN */ (*usb0_en) = 0; } /*************************************************************************/ void USBHAL::disconnect(void) { /* Deactivates USB0_EN */ (*usb0_en) = 1; } /*************************************************************************/ void USBHAL::configureDevice(void) { /*The pipes set up in USBHAL::realiseEndpoint*/ /*usb0_function_clear_alt();*/ /* Alternate setting clear */ /*usb0_function_set_pid_buf(USB_FUNCTION_PIPE0);*/ } /*************************************************************************/ void USBHAL::unconfigureDevice(void) { /* The Interface would be managed by USBDevice */ /*usb0_function_clear_alt();*/ /* Alternate setting clear */ /*usb0_function_set_pid_buf(USB_FUNCTION_PIPE0);*/ } /*************************************************************************/ void USBHAL::setAddress(uint8_t address) { if (address <= 127) { usb0_function_set_pid_buf(USB_FUNCTION_PIPE0); /* OK */ } else { usb0_function_set_pid_stall(USB_FUNCTION_PIPE0); /* Not Spec */ } } /*************************************************************************/ bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) { const struct PIPECFGREC *cfg; uint16_t pipe; uint16_t buf; if ( (EP0OUT == endpoint) || (EP0IN == endpoint) ) { return true; } for (cfg = &def_pipecfg[0]; cfg->pipesel != 0; cfg++) { if (cfg->endpoint == endpoint) { break; } } if (cfg->pipesel == 0) { return false; } pipe = ((cfg->pipesel & USB_PIPESEL_PIPESEL) >> USB_PIPESEL_PIPESEL_SHIFT); g_usb0_function_PipeTbl[ pipe ] = (uint16_t)(endpoint | ((cfg->pipesel & USB_FUNCTION_FIFO_USE) << 0)); /* There are maintenance routine of SHTNAK and BFRE bits * in original sample program. This sample is not * programmed. Do maintenance the "def_pipecfg" array if * you want it. */ /* Interrupt Disable */ buf = USB200.BRDYENB; buf &= (uint16_t)~g_usb0_function_bit_set[pipe]; USB200.BRDYENB = buf; buf = USB200.NRDYENB; buf &= (uint16_t)~g_usb0_function_bit_set[pipe]; USB200.NRDYENB = buf; buf = USB200.BEMPENB; buf &= (uint16_t)~g_usb0_function_bit_set[pipe]; USB200.BEMPENB = buf; usb0_function_set_pid_nak(pipe); /* CurrentPIPE Clear */ if (RZA_IO_RegRead_16(&USB200.CFIFOSEL, USB_CFIFOSEL_CURPIPE_SHIFT, USB_CFIFOSEL_CURPIPE) == pipe) { RZA_IO_RegWrite_16(&USB200.CFIFOSEL, 0, USB_CFIFOSEL_CURPIPE_SHIFT, USB_CFIFOSEL_CURPIPE); } if (RZA_IO_RegRead_16(&USB200.D0FIFOSEL, USB_DnFIFOSEL_CURPIPE_SHIFT, USB_DnFIFOSEL_CURPIPE) == pipe) { RZA_IO_RegWrite_16(&USB200.D0FIFOSEL, 0, USB_DnFIFOSEL_CURPIPE_SHIFT, USB_DnFIFOSEL_CURPIPE); } if (RZA_IO_RegRead_16(&USB200.D1FIFOSEL, USB_DnFIFOSEL_CURPIPE_SHIFT, USB_DnFIFOSEL_CURPIPE) == pipe) { RZA_IO_RegWrite_16(&USB200.D1FIFOSEL, 0, USB_DnFIFOSEL_CURPIPE_SHIFT, USB_DnFIFOSEL_CURPIPE); } /* PIPE Configuration */ USB200.PIPESEL = pipe; USB200.PIPECFG = cfg->pipecfg; USB200.PIPEBUF = cfg->pipebuf; USB200.PIPEMAXP = cfg->pipemaxp; USB200.PIPEPERI = cfg->pipeperi; g_usb0_function_pipecfg[pipe] = cfg->pipecfg; g_usb0_function_pipebuf[pipe] = cfg->pipebuf; g_usb0_function_pipemaxp[pipe] = cfg->pipemaxp; g_usb0_function_pipeperi[pipe] = cfg->pipeperi; /* Buffer Clear */ usb0_function_set_sqclr(pipe); usb0_function_aclrm(pipe); /* init Global */ g_usb0_function_pipe_status[pipe] = DEVDRV_USBF_PIPE_IDLE; g_usb0_function_PipeDataSize[pipe] = 0; return true; } /*************************************************************************/ // read setup packet void USBHAL::EP0setup(uint8_t *buffer) { memcpy(buffer, setup_buffer, MAX_PACKET_SIZE_EP0); } /*************************************************************************/ void USBHAL::EP0readStage(void) { // No implements } /*************************************************************************/ void USBHAL::EP0read(void) { uint8_t *buffer; uint32_t size; /* remain of last writing */ while (EP0_read_status != DEVDRV_USBF_WRITEEND) { static uint8_t bbb[2] = { 255, 255 }; EP0write(&bbb[0], 0); } buffer = (uint8_t*)(&setup_buffer[4]); size = (MAX_PACKET_SIZE_EP0 / 2) - 8; usb0_api_function_CtrlWriteStart(size, buffer); } /*************************************************************************/ uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { memcpy(buffer, (uint8_t*)(&setup_buffer[4]), g_usb0_function_PipeDataSize[USB_FUNCTION_PIPE0]); return g_usb0_function_PipeDataSize[USB_FUNCTION_PIPE0]; } /*************************************************************************/ void USBHAL::EP0write(uint8_t *buffer, uint32_t size) { /* zero byte writing */ if ( (size == 0) && (EP0_read_status == DEVDRV_USBF_WRITEEND) ) { return; } if (EP0_read_status == DEVDRV_USBF_WRITEEND) { /*1st block*/ EP0_read_status = usb0_api_function_CtrlReadStart(size, buffer); } else { /* waits the last transmission */ /*other blocks*/ g_usb0_function_data_count[ USB_FUNCTION_PIPE0 ] = size; g_usb0_function_data_pointer [ USB_FUNCTION_PIPE0 ] = buffer; EP0_read_status = usb0_function_write_buffer_c(USB_FUNCTION_PIPE0); } /*max size may be deblocking outside*/ if (size == MAX_PACKET_SIZE_EP0) { EP0_read_status = DEVDRV_USBF_WRITING; } } /*************************************************************************/ #if 0 // No implements void USBHAL::EP0getWriteResult(void) { } #endif /*************************************************************************/ void USBHAL::EP0stall(void) { stallEndpoint( 0 ); } /*************************************************************************/ EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t max_size) { uint32_t pipe = EP2PIPE(endpoint); uint32_t pipe_size; uint16_t pipe_status; EP_STATUS status = EP_COMPLETED; pipe_status = usb0_api_function_check_pipe_status(pipe, &pipe_size); pipe_size = (max_size < pipe_size)? (max_size): (pipe_size); if (pipe_status == DEVDRV_USBF_PIPE_IDLE) { usb0_api_function_set_pid_nak(pipe); usb0_api_function_clear_pipe_status(pipe); usb0_api_function_start_receive_transfer(pipe, pipe_size, recv_buffer); } else { status = EP_PENDING; } return status; } /*************************************************************************/ EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *buffer, uint32_t *bytes_read ) { uint32_t pipe = EP2PIPE(endpoint); uint16_t pipe_status; uint16_t err; EP_STATUS status = EP_PENDING; if (EPx_read_status != DEVDRV_USBF_PIPE_WAIT) { return status; } pipe_status = usb0_api_function_check_pipe_status(pipe, bytes_read); if (pipe_status == DEVDRV_USBF_PIPE_IDLE) { return EP_COMPLETED; } if (pipe_status == DEVDRV_USBF_PIPE_DONE) { return EP_COMPLETED; } if (pipe_status != DEVDRV_USBF_PIPE_WAIT) { return status; } /* sets the output buffer and size */ g_usb0_function_data_pointer[pipe] = buffer; /* receives data from pipe */ err = usb0_function_read_buffer(pipe); recv_error = err; pipe_status = usb0_api_function_check_pipe_status(pipe, bytes_read); if (pipe_status == DEVDRV_USBF_PIPE_DONE) { status = EP_COMPLETED; } return status; } /*************************************************************************/ EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) { uint32_t pipe = EP2PIPE(endpoint); uint32_t pipe_size; uint16_t pipe_status; uint16_t err; uint16_t count; EP_STATUS status = EP_PENDING; pipe_status = usb0_api_function_check_pipe_status(pipe, &pipe_size); /* waits the last transmission */ count = 30000; while ((pipe_status == DEVDRV_USBF_PIPE_WAIT) || (pipe_status == DEVDRV_USBF_PIPE_DONE)) { pipe_status = usb0_api_function_check_pipe_status(pipe, &pipe_size); if( --count == 0 ) { pipe_status = DEVDRV_USBF_PIPE_STALL; break; } } switch (pipe_status) { case DEVDRV_USBF_PIPE_IDLE: err = usb0_api_function_start_send_transfer(pipe, size, data); switch (err) { /* finish to write */ case DEVDRV_USBF_WRITEEND: /* finish to write, but data is short */ case DEVDRV_USBF_WRITESHRT: /* continue to write */ case DEVDRV_USBF_WRITING: /* use DMA */ case DEVDRV_USBF_WRITEDMA: /* error */ case DEVDRV_USBF_FIFOERROR: status = EP_PENDING; break; } break; case DEVDRV_USBF_PIPE_WAIT: case DEVDRV_USBF_PIPE_DONE: status = EP_PENDING; break; case DEVDRV_USBF_PIPE_NORES: case DEVDRV_USBF_PIPE_STALL: default: status = EP_STALLED; break; } return status; } /*************************************************************************/ EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { uint32_t pipe = EP2PIPE(endpoint); uint32_t pipe_size; uint16_t pipe_status; EP_STATUS status = EP_PENDING; pipe_status = usb0_api_function_check_pipe_status(pipe, &pipe_size); switch (pipe_status) { case DEVDRV_USBF_PIPE_IDLE: status = EP_COMPLETED; break; case DEVDRV_USBF_PIPE_WAIT: status = EP_PENDING; break; case DEVDRV_USBF_PIPE_DONE: usb0_function_stop_transfer(pipe); status = EP_COMPLETED; break; case DEVDRV_USBF_PIPE_NORES: status = EP_STALLED; break; case DEVDRV_USBF_PIPE_STALL: status = EP_STALLED; break; default: status = EP_PENDING; } return status; } /*************************************************************************/ void USBHAL::stallEndpoint(uint8_t endpoint) { uint32_t pipe = EP2PIPE(endpoint); usb0_function_clear_pid_stall(pipe); } /*************************************************************************/ void USBHAL::unstallEndpoint(uint8_t endpoint) { uint32_t pipe = EP2PIPE(endpoint); usb0_function_set_pid_stall( pipe ); } /*************************************************************************/ bool USBHAL::getEndpointStallState(uint8_t endpoint) { // No implemens return false; } /*************************************************************************/ #if 0 // No implements void USBHAL::remoteWakeup(void) { } #endif /*************************************************************************/ void USBHAL::_usbisr(void) { instance->usbisr(); } /*************************************************************************/ void USBHAL::usbisr(void) { uint16_t int_sts0; uint16_t int_sts1; uint16_t int_sts2; uint16_t int_sts3; uint16_t int_enb0; uint16_t int_enb2; uint16_t int_enb3; uint16_t int_enb4; volatile uint16_t dumy_sts; int_sts0 = USB200.INTSTS0; if (!(int_sts0 & ( USB_FUNCTION_BITVBINT | USB_FUNCTION_BITRESM | USB_FUNCTION_BITSOFR | USB_FUNCTION_BITDVST | USB_FUNCTION_BITCTRT | USB_FUNCTION_BITBEMP | USB_FUNCTION_BITNRDY | USB_FUNCTION_BITBRDY ))) { return; } int_sts1 = USB200.BRDYSTS; int_sts2 = USB200.NRDYSTS; int_sts3 = USB200.BEMPSTS; int_enb0 = USB200.INTENB0; int_enb2 = USB200.BRDYENB; int_enb3 = USB200.NRDYENB; int_enb4 = USB200.BEMPENB; if ((int_sts0 & USB_FUNCTION_BITRESM) && (int_enb0 & USB_FUNCTION_BITRSME)) { USB200.INTSTS0 = (uint16_t)~USB_FUNCTION_BITRESM; RZA_IO_RegWrite_16(&USB200.INTENB0, 0, USB_INTENB0_RSME_SHIFT, USB_INTENB0_RSME); /*usb0_function_USB_FUNCTION_Resume();*/ suspendStateChanged(1); } else if ( (int_sts0 & USB_FUNCTION_BITVBINT) && (int_enb0 & USB_FUNCTION_BITVBSE)) { USB200.INTSTS0 = (uint16_t)~USB_FUNCTION_BITVBINT; if (usb0_function_CheckVBUStaus() == DEVDRV_USBF_ON) { usb0_function_USB_FUNCTION_Attach(); } else { usb0_function_USB_FUNCTION_Detach(); } } else if ( (int_sts0 & USB_FUNCTION_BITSOFR) && (int_enb0 & USB_FUNCTION_BITSOFE)) { USB200.INTSTS0 = (uint16_t)~USB_FUNCTION_BITSOFR; SOF((USB200.FRMNUM & USB_FRMNUM_FRNM) >> USB_FRMNUM_FRNM_SHIFT); } else if ( (int_sts0 & USB_FUNCTION_BITDVST) && (int_enb0 & USB_FUNCTION_BITDVSE)) { USB200.INTSTS0 = (uint16_t)~USB_FUNCTION_BITDVST; switch (int_sts0 & USB_FUNCTION_BITDVSQ) { case USB_FUNCTION_DS_POWR: break; case USB_FUNCTION_DS_DFLT: /***************************************************************************** * Function Name: usb0_function_USB_FUNCTION_BusReset * Description : This function is executed when the USB device is transitioned * : to POWERD_STATE. Sets the device descriptor according to the * : connection speed determined by the USB reset hand shake. * Arguments : none * Return Value : none *****************************************************************************/ usb0_function_init_status(); /* memory clear */ #if 0 /* You would program those steps in USBCallback_busReset * if the system need the comment out steps. */ if (usb0_function_is_hispeed() == USB_FUNCTION_HIGH_SPEED) { /* Device Descriptor reset */ usb0_function_ResetDescriptor(USB_FUNCTION_HIGH_SPEED); } else { /* Device Descriptor reset */ usb0_function_ResetDescriptor(USB_FUNCTION_FULL_SPEED); } #endif /* Default Control PIPE reset */ /***************************************************************************** * Function Name: usb0_function_ResetDCP * Description : Initializes the default control pipe(DCP). * Outline : Reset default control pipe * Arguments : none * Return Value : none *****************************************************************************/ USB200.DCPCFG = 0; USB200.DCPMAXP = 64; /*TODO: This value is copied from sample*/ USB200.CFIFOSEL = (uint16_t)(USB_FUNCTION_BITMBW_8 | USB_FUNCTION_BITBYTE_LITTLE); USB200.D0FIFOSEL = (uint16_t)(USB_FUNCTION_BITMBW_8 | USB_FUNCTION_BITBYTE_LITTLE); USB200.D1FIFOSEL = (uint16_t)(USB_FUNCTION_BITMBW_8 | USB_FUNCTION_BITBYTE_LITTLE); busReset(); break; case USB_FUNCTION_DS_ADDS: break; case USB_FUNCTION_DS_CNFG: break; case USB_FUNCTION_DS_SPD_POWR: case USB_FUNCTION_DS_SPD_DFLT: case USB_FUNCTION_DS_SPD_ADDR: case USB_FUNCTION_DS_SPD_CNFG: suspendStateChanged(0); /*usb0_function_USB_FUNCTION_Suspend();*/ break; default: break; } } else if ( (int_sts0 & USB_FUNCTION_BITBEMP) && (int_enb0 & USB_FUNCTION_BITBEMP) && ((int_sts3 & int_enb4) & g_usb0_function_bit_set[USB_FUNCTION_PIPE0])) { /* ==== BEMP PIPE0 ==== */ usb0_function_BEMPInterruptPIPE0(int_sts3, int_enb4); } else if ( (int_sts0 & USB_FUNCTION_BITBRDY) && (int_enb0 & USB_FUNCTION_BITBRDY) && ((int_sts1 & int_enb2) & g_usb0_function_bit_set[USB_FUNCTION_PIPE0])) { /* ==== BRDY PIPE0 ==== */ usb0_function_BRDYInterruptPIPE0(int_sts1, int_enb2); } else if ( (int_sts0 & USB_FUNCTION_BITNRDY) && (int_enb0 & USB_FUNCTION_BITNRDY) && ((int_sts2 & int_enb3) & g_usb0_function_bit_set[USB_FUNCTION_PIPE0])) { /* ==== NRDY PIPE0 ==== */ usb0_function_NRDYInterruptPIPE0(int_sts2, int_enb3); } else if ( (int_sts0 & USB_FUNCTION_BITCTRT) && (int_enb0 & USB_FUNCTION_BITCTRE)) { int_sts0 = USB200.INTSTS0; USB200.INTSTS0 = (uint16_t)~USB_FUNCTION_BITCTRT; if (((int_sts0 & USB_FUNCTION_BITCTSQ) == USB_FUNCTION_CS_RDDS) || ((int_sts0 & USB_FUNCTION_BITCTSQ) == USB_FUNCTION_CS_WRDS) || ((int_sts0 & USB_FUNCTION_BITCTSQ) == USB_FUNCTION_CS_WRND)) { /* remake EP0 into buffer */ usb0_function_save_request(); if ((USB200.INTSTS0 & USB_FUNCTION_BITVALID) && ( ((int_sts0 & USB_FUNCTION_BITCTSQ) == USB_FUNCTION_CS_RDDS) || ((int_sts0 & USB_FUNCTION_BITCTSQ) == USB_FUNCTION_CS_WRDS) || ((int_sts0 & USB_FUNCTION_BITCTSQ) == USB_FUNCTION_CS_WRND))) { /* New SETUP token received */ /* Three dummy reads for cleearing interrupt requests */ dumy_sts = USB200.INTSTS0; dumy_sts = USB200.INTSTS0; dumy_sts = USB200.INTSTS0; return; } } switch (int_sts0 & USB_FUNCTION_BITCTSQ) { case USB_FUNCTION_CS_IDST: if (g_usb0_function_TestModeFlag == DEVDRV_USBF_YES) { /* ==== Test Mode ==== */ usb0_function_USB_FUNCTION_TestMode(); } /* Needs not procedure in this state */ break; case USB_FUNCTION_CS_RDDS: /* Reads a setup packet */ EP0setupCallback(); break; case USB_FUNCTION_CS_WRDS: /* Original code was the SetDescriptor was called */ EP0setupCallback(); break; case USB_FUNCTION_CS_WRND: EP0setupCallback(); /*The EP0setupCallback should finish in successful */ usb0_function_set_pid_buf(USB_FUNCTION_PIPE0); RZA_IO_RegWrite_16(&USB200.DCPCTR, 1, USB_DCPCTR_CCPL_SHIFT, USB_DCPCTR_CCPL); break; case USB_FUNCTION_CS_RDSS: RZA_IO_RegWrite_16(&USB200.DCPCTR, 1, USB_DCPCTR_CCPL_SHIFT, USB_DCPCTR_CCPL); break; case USB_FUNCTION_CS_WRSS: RZA_IO_RegWrite_16(&USB200.DCPCTR, 1, USB_DCPCTR_CCPL_SHIFT, USB_DCPCTR_CCPL); break; case USB_FUNCTION_CS_SQER: usb0_function_set_pid_stall(USB_FUNCTION_PIPE0); break; default: usb0_function_set_pid_stall(USB_FUNCTION_PIPE0); break; } } else if ( (int_sts0 & USB_FUNCTION_BITBEMP) && (int_enb0 & USB_FUNCTION_BITBEMP) && (int_sts3 & int_enb4) ) { /* ==== BEMP PIPEx ==== */ usb0_function_BEMPInterrupt(int_sts3, int_enb4); } else if ( (int_sts0 & USB_FUNCTION_BITBRDY) && (int_enb0 & USB_FUNCTION_BITBRDY) && (int_sts1 & int_enb2) ) { /* ==== BRDY PIPEx ==== */ usb0_function_BRDYInterrupt(int_sts1, int_enb2); } else if ( (int_sts0 & USB_FUNCTION_BITNRDY) && (int_enb0 & USB_FUNCTION_BITNRDY) && (int_sts2 & int_enb3)) { /* ==== NRDY PIPEx ==== */ usb0_function_NRDYInterrupt(int_sts2, int_enb3); } else { /* Do Nothing */ } /* Three dummy reads for cleearing interrupt requests */ dumy_sts = USB200.INTSTS0; dumy_sts = USB200.INTSTS1; } /*************************************************************************/ #endif /*************************************************************************/ /*EOF*/