USB device stack; Added getter method for terminal_connected;
Fork of USBDevice by
Example of use:
#include "mbed.h" #include "USBSerial.h" USBSerial pc; DigitalOut blue_led(P0_20); int main() { blue_led = 1; while(!pc.getTerminal_connected()); //Wait for serial terminal to connect... while(1) { blue_led = 0; wait(0.2); blue_led = 1; wait(0.2); } }
Diff: USBDevice/USBHAL_RZ_A1H.cpp
- Revision:
- 35:a8484e16c2f3
- Child:
- 36:4d3e7f3d5211
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBDevice/USBHAL_RZ_A1H.cpp Thu Nov 06 11:01:12 2014 +0000 @@ -0,0 +1,1226 @@ +/* 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 "iobitmasks/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*/