1498 wiersze
51 KiB
C++
1498 wiersze
51 KiB
C++
/* 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 "usb_iobitmask.h"
|
|
#include "rza_io_regrw.h"
|
|
#include "USBDevice_Types.h"
|
|
#include "usb_function_setting.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,
|
|
MAX_PACKET_SIZE_EP1,
|
|
DEVDRV_USBF_OFF |
|
|
( 3 << USB_PIPEPERI_IITV_SHIFT ),
|
|
},
|
|
{
|
|
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,
|
|
MAX_PACKET_SIZE_EP1,
|
|
DEVDRV_USBF_OFF |
|
|
( 3 << USB_PIPEPERI_IITV_SHIFT ),
|
|
},
|
|
{
|
|
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,
|
|
MAX_PACKET_SIZE_EP2,
|
|
DEVDRV_USBF_OFF |
|
|
( 0 << USB_PIPEPERI_IITV_SHIFT ),
|
|
},
|
|
{
|
|
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,
|
|
MAX_PACKET_SIZE_EP2,
|
|
DEVDRV_USBF_OFF |
|
|
( 0 << USB_PIPEPERI_IITV_SHIFT ),
|
|
},
|
|
{
|
|
EP3OUT, /*EP3: Host -> Func, ISO*/
|
|
1 | USB_FUNCTION_D0FIFO_USE,
|
|
USB_FUNCTION_ISO |
|
|
USB_FUNCTION_BFREOFF |
|
|
USB_FUNCTION_DBLBON |
|
|
USB_FUNCTION_CNTMDOFF |
|
|
USB_FUNCTION_SHTNAKON |
|
|
USB_FUNCTION_DIR_P_OUT |
|
|
USB_FUNCTION_EP3,
|
|
( ( ( 512) / 64 - 1 ) << 10 ) | 0x10u,
|
|
MAX_PACKET_SIZE_EP3,
|
|
DEVDRV_USBF_OFF |
|
|
( 0 << USB_PIPEPERI_IITV_SHIFT ),
|
|
},
|
|
{
|
|
EP3IN, /*EP3: Host <- Func, ISO*/
|
|
2 | USB_FUNCTION_D1FIFO_USE,
|
|
USB_FUNCTION_ISO |
|
|
USB_FUNCTION_BFREOFF |
|
|
USB_FUNCTION_DBLBON |
|
|
USB_FUNCTION_CNTMDOFF |
|
|
USB_FUNCTION_SHTNAKOFF |
|
|
USB_FUNCTION_DIR_P_IN |
|
|
USB_FUNCTION_EP3,
|
|
( ( ( 512) / 64 - 1 ) << 10 ) | 0x20u,
|
|
MAX_PACKET_SIZE_EP3,
|
|
DEVDRV_USBF_OFF |
|
|
( 0 << USB_PIPEPERI_IITV_SHIFT ),
|
|
},
|
|
{ /*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 *usbx_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 */
|
|
extern "C" {
|
|
void usbx_function_BRDYInterruptPIPE0 (uint16_t status, uint16_t intenb,
|
|
USBHAL *object, void (USBHAL::*EP0func)(void));
|
|
|
|
void usbx_function_BRDYInterrupt (uint16_t status, uint16_t intenb,
|
|
USBHAL *object, bool (USBHAL::*epCallback[])(void));
|
|
|
|
void usbx_function_NRDYInterruptPIPE0(uint16_t status, uint16_t intenb,
|
|
USBHAL *object, void (USBHAL::*EP0func)(void));
|
|
|
|
void usbx_function_NRDYInterrupt (uint16_t status, uint16_t intenb,
|
|
USBHAL *object, bool (USBHAL::*epCallback[])(void));
|
|
|
|
void usbx_function_BEMPInterruptPIPE0(uint16_t status, uint16_t intenb,
|
|
USBHAL *object, void (USBHAL::*EP0func)(void));
|
|
|
|
void usbx_function_BEMPInterrupt (uint16_t status, uint16_t intenb,
|
|
USBHAL *object, bool (USBHAL::*epCallback[])(void));
|
|
}
|
|
|
|
|
|
/*************************************************************************/
|
|
/* macros */
|
|
|
|
/******************************************************************************
|
|
* Function Name: usbx_function_BRDYInterruptPIPE0
|
|
* Description : Executes BRDY interrupt for pipe0.
|
|
* Arguments : uint16_t status ; BRDYSTS Register Value
|
|
* : uint16_t intenb ; BRDYENB Register Value
|
|
* Return Value : none
|
|
*****************************************************************************/
|
|
extern "C" {
|
|
void usbx_function_BRDYInterruptPIPE0 (
|
|
uint16_t status,
|
|
uint16_t intenb,
|
|
USBHAL *object,
|
|
void (USBHAL::*EP0func)(void)
|
|
)
|
|
{
|
|
volatile uint16_t dumy_sts;
|
|
uint16_t read_status;
|
|
|
|
USB20X.BRDYSTS =
|
|
(uint16_t)~g_usbx_function_bit_set[USB_FUNCTION_PIPE0];
|
|
RZA_IO_RegWrite_16(
|
|
&USB20X.CFIFOSEL, USB_FUNCTION_PIPE0,
|
|
USB_CFIFOSEL_CURPIPE_SHIFT, USB_CFIFOSEL_CURPIPE);
|
|
|
|
g_usbx_function_PipeDataSize[USB_FUNCTION_PIPE0] =
|
|
g_usbx_function_data_count[USB_FUNCTION_PIPE0];
|
|
|
|
read_status = usbx_function_read_buffer_c(USB_FUNCTION_PIPE0);
|
|
|
|
g_usbx_function_PipeDataSize[USB_FUNCTION_PIPE0] -=
|
|
g_usbx_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 */
|
|
usbx_function_set_pid_buf(USB_FUNCTION_PIPE0);
|
|
|
|
/*callback*/
|
|
(object->*EP0func)();
|
|
break;
|
|
|
|
case USB_FUNCTION_READSHRT: /* End of data read */
|
|
usbx_function_disable_brdy_int(USB_FUNCTION_PIPE0);
|
|
/* PID = BUF */
|
|
usbx_function_set_pid_buf(USB_FUNCTION_PIPE0);
|
|
|
|
/*callback*/
|
|
(object->*EP0func)();
|
|
break;
|
|
|
|
case USB_FUNCTION_READOVER: /* FIFO access error */
|
|
/* Buffer Clear */
|
|
USB20X.CFIFOCTR = USB_FUNCTION_BITBCLR;
|
|
usbx_function_disable_brdy_int(USB_FUNCTION_PIPE0);
|
|
/* Req Error */
|
|
usbx_function_set_pid_stall(USB_FUNCTION_PIPE0);
|
|
|
|
/*callback*/
|
|
(object->*EP0func)();
|
|
break;
|
|
|
|
case DEVDRV_USBF_FIFOERROR: /* FIFO access error */
|
|
default:
|
|
usbx_function_disable_brdy_int(USB_FUNCTION_PIPE0);
|
|
/* Req Error */
|
|
usbx_function_set_pid_stall(USB_FUNCTION_PIPE0);
|
|
break;
|
|
}
|
|
/* Three dummy reads for clearing interrupt requests */
|
|
dumy_sts = USB20X.BRDYSTS;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* Function Name: usbx_function_BRDYInterrupt
|
|
* Description : Executes BRDY interrupt uxclude pipe0.
|
|
* Arguments : uint16_t status ; BRDYSTS Register Value
|
|
* : uint16_t intenb ; BRDYENB Register Value
|
|
* Return Value : none
|
|
*****************************************************************************/
|
|
extern "C" {
|
|
void usbx_function_BRDYInterrupt(
|
|
uint16_t status,
|
|
uint16_t intenb,
|
|
USBHAL *object,
|
|
bool (USBHAL::*epCallback[])(void)
|
|
)
|
|
{
|
|
volatile uint16_t dumy_sts;
|
|
|
|
/**************************************************************
|
|
* Function Name: usbx_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 usbx_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_usbx_function_bit_set[pipe];
|
|
|
|
if ((status & pipebit) && (intenb & pipebit)) {
|
|
USB20X.BRDYSTS = (uint16_t)~pipebit;
|
|
USB20X.BEMPSTS = (uint16_t)~pipebit;
|
|
|
|
switch (g_usbx_function_PipeTbl[pipe] & USB_FUNCTION_FIFO_USE) {
|
|
case USB_FUNCTION_D0FIFO_DMA:
|
|
if (g_usbx_function_DmaStatus[USB_FUNCTION_D0FIFO] != USB_FUNCTION_DMA_READY) {
|
|
/*now, DMA is not supported*/
|
|
usbx_function_dma_interrupt_d0fifo(int_sense);
|
|
}
|
|
|
|
if (RZA_IO_RegRead_16(
|
|
&g_usbx_function_pipecfg[pipe], USB_PIPECFG_BFRE_SHIFT, USB_PIPECFG_BFRE) == 0) {
|
|
/*now, DMA is not supported*/
|
|
usbx_function_read_dma(pipe);
|
|
usbx_function_disable_brdy_int(pipe);
|
|
} else {
|
|
USB20X.D0FIFOCTR = USB_FUNCTION_BITBCLR;
|
|
g_usbx_function_pipe_status[pipe] = DEVDRV_USBF_PIPE_DONE;
|
|
}
|
|
break;
|
|
|
|
case USB_FUNCTION_D1FIFO_DMA:
|
|
if (g_usbx_function_DmaStatus[USB_FUNCTION_D1FIFO] != USB_FUNCTION_DMA_READY) {
|
|
/*now, DMA is not supported*/
|
|
usbx_function_dma_interrupt_d1fifo(int_sense);
|
|
}
|
|
|
|
if (RZA_IO_RegRead_16(
|
|
&g_usbx_function_pipecfg[pipe], USB_PIPECFG_BFRE_SHIFT, USB_PIPECFG_BFRE) == 0) {
|
|
/*now, DMA is not supported*/
|
|
usbx_function_read_dma(pipe);
|
|
usbx_function_disable_brdy_int(pipe);
|
|
} else {
|
|
USB20X.D1FIFOCTR = USB_FUNCTION_BITBCLR;
|
|
g_usbx_function_pipe_status[pipe] = DEVDRV_USBF_PIPE_DONE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ep = (g_usbx_function_pipecfg[pipe] & USB_PIPECFG_EPNUM) >> USB_PIPECFG_EPNUM_SHIFT;
|
|
ep <<= 1;
|
|
if (RZA_IO_RegRead_16(
|
|
&g_usbx_function_pipecfg[pipe], USB_PIPECFG_DIR_SHIFT, USB_PIPECFG_DIR) == 0) {
|
|
/* read */
|
|
EPx_read_status = DEVDRV_USBF_PIPE_WAIT;
|
|
(object->*(epCallback[ep - 2])) ();
|
|
EPx_read_status = DEVDRV_USBF_PIPE_DONE;
|
|
} else {
|
|
/* write */
|
|
EPx_read_status = DEVDRV_USBF_PIPE_WAIT;
|
|
(object->*(epCallback[ep - 2 + 1])) ();
|
|
EPx_read_status = DEVDRV_USBF_PIPE_DONE;
|
|
usbx_function_write_buffer(pipe);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* Three dummy reads for clearing interrupt requests */
|
|
dumy_sts = USB20X.BRDYSTS;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* Function Name: usbx_function_NRDYInterruptPIPE0
|
|
* Description : Executes NRDY interrupt for pipe0.
|
|
* Arguments : uint16_t status ; NRDYSTS Register Value
|
|
* : uint16_t intenb ; NRDYENB Register Value
|
|
* Return Value : none
|
|
*****************************************************************************/
|
|
extern "C" {
|
|
void usbx_function_NRDYInterruptPIPE0(
|
|
uint16_t status,
|
|
uint16_t intenb,
|
|
USBHAL *object,
|
|
void (USBHAL::*EP0func)(void)
|
|
)
|
|
{
|
|
volatile uint16_t dumy_sts;
|
|
|
|
USB20X.NRDYSTS =
|
|
(uint16_t)~g_usbx_function_bit_set[USB_FUNCTION_PIPE0];
|
|
|
|
/* Three dummy reads for clearing interrupt requests */
|
|
dumy_sts = USB20X.NRDYSTS;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* Function Name: usbx_function_NRDYInterrupt
|
|
* Description : Executes NRDY interrupt exclude pipe0.
|
|
* Arguments : uint16_t status ; NRDYSTS Register Value
|
|
* : uint16_t intenb ; NRDYENB Register Value
|
|
* Return Value : none
|
|
*****************************************************************************/
|
|
extern "C" {
|
|
void usbx_function_NRDYInterrupt(
|
|
uint16_t status,
|
|
uint16_t intenb,
|
|
USBHAL *object,
|
|
bool (USBHAL::*epCallback[])(void)
|
|
)
|
|
{
|
|
volatile uint16_t dumy_sts;
|
|
|
|
/**************************************************************
|
|
* Function Name: usbx_function_nrdy_int
|
|
* Description : Executes NRDY interrupt(USB_FUNCTION_PIPE1-9).
|
|
* : Checks NRDY interrupt cause by PID. When the cause if STALL,
|
|
* : regards the pipe state as STALL and ends the processing.
|
|
* : Then the cause is not STALL, increments the error count to
|
|
* : communicate again. When the error count is 3, determines
|
|
* : the pipe state as DEVDRV_USBF_PIPE_NORES and ends the processing.
|
|
* : This function is executed in the NRDY interrupt handler.
|
|
* : This function clears NRDY interrupt status.
|
|
* Arguments : uint16_t status ; NRDYSTS Register Value
|
|
* : uint16_t int_enb ; NRDYENB Register Value
|
|
* Return Value : none
|
|
*************************************************************/
|
|
/* copied from usbx_function_intrn.c */
|
|
#if 0
|
|
uint16_t usefifo;
|
|
#endif
|
|
uint16_t pid;
|
|
uint16_t pipe;
|
|
uint16_t bitcheck;
|
|
#if 0
|
|
uint16_t mbw;
|
|
uint32_t size;
|
|
#endif
|
|
uint16_t ep;
|
|
|
|
bitcheck = (uint16_t)(status & intenb);
|
|
|
|
USB20X.NRDYSTS = (uint16_t)~status;
|
|
|
|
|
|
if (RZA_IO_RegRead_16(&USB20X.SYSCFG0, USB_SYSCFG_DCFM_SHIFT, USB_SYSCFG_DCFM) == 1) {
|
|
/* USB HOST */
|
|
/* not support */
|
|
|
|
} else {
|
|
/* USB Function */
|
|
for (pipe = USB_FUNCTION_PIPE1; pipe <= USB_FUNCTION_MAX_PIPE_NO; pipe++) {
|
|
if ((bitcheck&g_usbx_function_bit_set[pipe]) != g_usbx_function_bit_set[pipe]) {
|
|
continue;
|
|
}
|
|
|
|
if (g_usbx_function_pipe_status[pipe] != DEVDRV_USBF_PIPE_WAIT) {
|
|
continue;
|
|
}
|
|
|
|
#if 0
|
|
usbx_function_set_pid_nak(pipe);
|
|
|
|
size = (uint32_t)g_usbx_function_data_count[pipe];
|
|
mbw = usbx_function_get_mbw(
|
|
size, (uint32_t)g_usbx_function_data_pointer[pipe]);
|
|
|
|
usefifo = (uint16_t)(g_usbx_function_PipeTbl[pipe] & USB_FUNCTION_FIFO_USE);
|
|
switch (usefifo) {
|
|
|
|
case USB_FUNCTION_D0FIFO_USE:
|
|
usbx_function_set_curpipe(
|
|
pipe, USB_FUNCTION_D0USE, DEVDRV_USBF_NO, mbw);
|
|
USB20X.D0FIFOCTR = USB_FUNCTION_BITBCLR;
|
|
break;
|
|
|
|
case USB_FUNCTION_D1FIFO_USE:
|
|
usbx_function_set_curpipe(
|
|
pipe, USB_FUNCTION_D1USE, DEVDRV_USBF_NO, mbw);
|
|
USB20X.D1FIFOCTR = USB_FUNCTION_BITBCLR;
|
|
break;
|
|
|
|
default:
|
|
usbx_function_set_curpipe(
|
|
pipe, USB_FUNCTION_CUSE, USB_FUNCTION_CFIFO_READ, mbw);
|
|
USB20X.CFIFOCTR = USB_FUNCTION_BITBCLR;
|
|
break;
|
|
}
|
|
|
|
usbx_function_aclrm(pipe);
|
|
|
|
usbx_function_enable_nrdy_int(pipe);
|
|
usbx_function_enable_brdy_int(pipe);
|
|
|
|
usbx_function_set_pid_buf(pipe);
|
|
#endif
|
|
|
|
pid = usbx_function_get_pid(pipe);
|
|
if ((pid == DEVDRV_USBF_PID_STALL) || (pid == DEVDRV_USBF_PID_STALL2)) {
|
|
g_usbx_function_pipe_status[pipe] = DEVDRV_USBF_PIPE_STALL;
|
|
} else {
|
|
usbx_function_set_pid_buf(pipe);
|
|
}
|
|
|
|
ep = (g_usbx_function_pipecfg[pipe] & USB_PIPECFG_EPNUM) >> USB_PIPECFG_EPNUM_SHIFT;
|
|
ep <<= 1;
|
|
if (RZA_IO_RegRead_16(
|
|
&g_usbx_function_pipecfg[pipe], USB_PIPECFG_DIR_SHIFT, USB_PIPECFG_DIR) == 0) {
|
|
/* read */
|
|
__NOP();
|
|
} else {
|
|
/* write */
|
|
__NOP();
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Three dummy reads for clearing interrupt requests */
|
|
dumy_sts = USB20X.NRDYSTS;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Function Name: usbx_function_BEMPInterruptPIPE0
|
|
* Description : Executes BEMP interrupt for pipe0.
|
|
* Arguments : uint16_t status ; BEMPSTS Register Value
|
|
* : uint16_t intenb ; BEMPENB Register Value
|
|
* Return Value : none
|
|
*****************************************************************************/
|
|
extern "C" {
|
|
void usbx_function_BEMPInterruptPIPE0(
|
|
uint16_t status,
|
|
uint16_t intenb,
|
|
USBHAL *object,
|
|
void (USBHAL::*EP0func)(void)
|
|
)
|
|
{
|
|
volatile uint16_t dumy_sts;
|
|
|
|
USB20X.BEMPSTS =
|
|
(uint16_t)~g_usbx_function_bit_set[USB_FUNCTION_PIPE0];
|
|
RZA_IO_RegWrite_16(
|
|
&USB20X.CFIFOSEL, USB_FUNCTION_PIPE0,
|
|
USB_CFIFOSEL_CURPIPE_SHIFT, USB_CFIFOSEL_CURPIPE);
|
|
|
|
/*usbx_function_write_buffer_c(USB_FUNCTION_PIPE0);*/
|
|
(object->*EP0func)();
|
|
|
|
/* Three dummy reads for clearing interrupt requests */
|
|
dumy_sts = USB20X.BEMPSTS;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* Function Name: usbx_function_BEMPInterrupt
|
|
* Description : Executes BEMP interrupt exclude pipe0.
|
|
* Arguments : uint16_t status ; BEMPSTS Register Value
|
|
* : uint16_t intenb ; BEMPENB Register Value
|
|
* Return Value : none
|
|
*****************************************************************************/
|
|
extern "C" {
|
|
void usbx_function_BEMPInterrupt(
|
|
uint16_t status,
|
|
uint16_t intenb,
|
|
USBHAL *object,
|
|
bool (USBHAL::*epCallback[])(void)
|
|
)
|
|
{
|
|
volatile uint16_t dumy_sts;
|
|
|
|
/**************************************************************
|
|
* Function Name: usbx_function_bemp_int
|
|
* Description : Executes BEMP interrupt(USB_FUNCTION_PIPE1-9).
|
|
* Arguments : uint16_t status ; BEMPSTS Register Value
|
|
* : uint16_t intenb ; BEMPENB Register Value
|
|
* Return Value : none
|
|
*************************************************************/
|
|
/* copied from usbx_function_intrn.c */
|
|
uint16_t pid;
|
|
uint16_t pipe;
|
|
uint16_t bitcheck;
|
|
uint16_t inbuf;
|
|
uint16_t ep;
|
|
|
|
bitcheck = (uint16_t)(status & intenb);
|
|
|
|
USB20X.BEMPSTS = (uint16_t)~status;
|
|
|
|
for (pipe = USB_FUNCTION_PIPE1; pipe <= USB_FUNCTION_MAX_PIPE_NO; pipe++) {
|
|
if ((bitcheck&g_usbx_function_bit_set[pipe]) != g_usbx_function_bit_set[pipe]) {
|
|
continue;
|
|
}
|
|
|
|
pid = usbx_function_get_pid(pipe);
|
|
|
|
if ((pid == DEVDRV_USBF_PID_STALL) ||
|
|
(pid == DEVDRV_USBF_PID_STALL2)) {
|
|
g_usbx_function_pipe_status[pipe] = DEVDRV_USBF_PIPE_STALL;
|
|
|
|
} else {
|
|
inbuf = usbx_function_get_inbuf(pipe);
|
|
|
|
if (inbuf == 0) {
|
|
usbx_function_disable_bemp_int(pipe);
|
|
usbx_function_set_pid_nak(pipe);
|
|
g_usbx_function_pipe_status[pipe] = DEVDRV_USBF_PIPE_DONE;
|
|
|
|
switch (g_usbx_function_PipeTbl[pipe] & USB_FUNCTION_FIFO_USE) {
|
|
case USB_FUNCTION_D0FIFO_DMA:
|
|
/*now, DMA is not supported*/
|
|
break;
|
|
|
|
case USB_FUNCTION_D1FIFO_DMA:
|
|
/*now, DMA is not supported*/
|
|
break;
|
|
|
|
default:
|
|
ep = (g_usbx_function_pipecfg[pipe] & USB_PIPECFG_EPNUM) >> USB_PIPECFG_EPNUM_SHIFT;
|
|
ep <<= 1;
|
|
if (RZA_IO_RegRead_16(
|
|
&g_usbx_function_pipecfg[pipe], USB_PIPECFG_DIR_SHIFT, USB_PIPECFG_DIR) == 0) {
|
|
/* read */
|
|
__NOP();
|
|
} else {
|
|
/* write */
|
|
EPx_read_status = DEVDRV_USBF_PIPE_WAIT;
|
|
(object->*(epCallback[ep - 2 + 1])) ();
|
|
EPx_read_status = DEVDRV_USBF_PIPE_DONE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Three dummy reads for clearing interrupt requests */
|
|
dumy_sts = USB20X.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)usbx_function_EpToPipe(endpoint))
|
|
|
|
|
|
/******************************************************************************
|
|
* Function Name: usbx_function_save_request
|
|
* Description : Retains the USB request information in variables.
|
|
* Arguments : none
|
|
* Return Value : none
|
|
*****************************************************************************/
|
|
#define usbx_function_save_request() \
|
|
{ \
|
|
uint16_t *bufO = &setup_buffer[0]; \
|
|
\
|
|
USB20X.INTSTS0 = (uint16_t)~USB_FUNCTION_BITVALID; \
|
|
/*data[0] <= bmRequest, data[1] <= bmRequestType */ \
|
|
*bufO++ = USB20X.USBREQ; \
|
|
/*data[2] data[3] <= wValue*/ \
|
|
*bufO++ = USB20X.USBVAL; \
|
|
/*data[4] data[5] <= wIndex*/ \
|
|
*bufO++ = USB20X.USBINDX; \
|
|
/*data[6] data[6] <= wIndex*/ \
|
|
*bufO++ = USB20X.USBLENG; \
|
|
}
|
|
|
|
|
|
/*************************************************************************/
|
|
/*************************************************************************/
|
|
/*************************************************************************/
|
|
|
|
/*************************************************************************/
|
|
/* constructor */
|
|
USBHAL::USBHAL(void)
|
|
{
|
|
/* ---- P4_1 : P4_1 (USB0_EN for GR-PEACH) ---- */
|
|
//usbx_en = new DigitalOut(P4_1, 1);
|
|
|
|
/* some constants */
|
|
int_id = USBIX_IRQn;
|
|
int_level = ( 2 << 3 );
|
|
clock_mode = USBFCLOCK_X1_48MHZ;
|
|
#if (USB_FUNCTION_HISPEED == 0)
|
|
mode = USB_FUNCTION_FULL_SPEED;
|
|
#else
|
|
mode = USB_FUNCTION_HIGH_SPEED;
|
|
#endif
|
|
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 */
|
|
usbx_function_clear_pipe_tbl();
|
|
|
|
/******************************************************************************
|
|
* Function Name: usbx_api_function_init
|
|
* Description : Initializes the USB module in the USB function mode.
|
|
*****************************************************************************/
|
|
/* The clock of USB0 modules is permitted */
|
|
#if (USB_FUNCTION_CH == 0)
|
|
CPG.STBCR7 &= ~(CPG_STBCR7_MSTP71);
|
|
#else
|
|
CPG.STBCR7 &= ~(CPG_STBCR7_MSTP71 | CPG_STBCR7_MSTP70);
|
|
#endif
|
|
volatile uint8_t dummy8;
|
|
dummy8 = CPG.STBCR7;
|
|
|
|
{
|
|
/******************************************************************************
|
|
* Function Name: usbx_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_usbx_function_d0fifo_dmaintid();
|
|
if (d0fifo_dmaintid != 0xFFFF) {
|
|
InterruptHandlerRegister(d0fifo_dmaintid, usbx_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_usbx_function_d1fifo_dmaintid();
|
|
if (d1fifo_dmaintid != 0xFFFF) {
|
|
InterruptHandlerRegister(d1fifo_dmaintid, usbx_function_dma_interrupt_d1fifo);
|
|
GIC_SetPriority(d1fifo_dmaintid, int_level);
|
|
GIC_EnableIRQ(d1fifo_dmaintid);
|
|
}
|
|
#endif
|
|
/*****************************************************************************/
|
|
}
|
|
|
|
/* reset USB module with setting tranciever and HSE=1 */
|
|
usbx_function_reset_module(clock_mode);
|
|
|
|
/* clear variables */
|
|
usbx_function_init_status();
|
|
|
|
/* select USB Function and Interrupt Enable */
|
|
/* Detect USB Device to attach or detach */
|
|
usbx_function_InitModule(mode);
|
|
|
|
{
|
|
uint16_t buf;
|
|
buf = USB20X.INTENB0;
|
|
buf |= USB_INTENB0_SOFE;
|
|
USB20X.INTENB0 = buf;
|
|
}
|
|
}
|
|
|
|
/*************************************************************************/
|
|
USBHAL::~USBHAL(void)
|
|
{
|
|
/* Disables interrupt for usb */
|
|
GIC_DisableIRQ( int_id );
|
|
/* Unregisters interrupt function and priority */
|
|
InterruptHandlerRegister( int_id, (uint32_t)NULL );
|
|
|
|
//usbx_en = NULL;
|
|
instance = NULL;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
void USBHAL::connect(void)
|
|
{
|
|
/* Activates USB0_EN */
|
|
//(*usbx_en) = 0;
|
|
}
|
|
|
|
|
|
/*************************************************************************/
|
|
void USBHAL::disconnect(void)
|
|
{
|
|
/* Deactivates USB0_EN */
|
|
//(*usbx_en) = 1;
|
|
}
|
|
|
|
|
|
/*************************************************************************/
|
|
void USBHAL::configureDevice(void)
|
|
{
|
|
/*The pipes set up in USBHAL::realiseEndpoint*/
|
|
/*usbx_function_clear_alt();*/ /* Alternate setting clear */
|
|
/*usbx_function_set_pid_buf(USB_FUNCTION_PIPE0);*/
|
|
}
|
|
|
|
|
|
/*************************************************************************/
|
|
void USBHAL::unconfigureDevice(void)
|
|
{
|
|
/* The Interface would be managed by USBDevice */
|
|
/*usbx_function_clear_alt();*/ /* Alternate setting clear */
|
|
/*usbx_function_set_pid_buf(USB_FUNCTION_PIPE0);*/
|
|
}
|
|
|
|
|
|
/*************************************************************************/
|
|
void USBHAL::setAddress(uint8_t address)
|
|
{
|
|
if (address <= 127) {
|
|
usbx_function_set_pid_buf(USB_FUNCTION_PIPE0); /* OK */
|
|
} else {
|
|
usbx_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_usbx_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 = USB20X.BRDYENB;
|
|
buf &= (uint16_t)~g_usbx_function_bit_set[pipe];
|
|
USB20X.BRDYENB = buf;
|
|
buf = USB20X.NRDYENB;
|
|
buf &= (uint16_t)~g_usbx_function_bit_set[pipe];
|
|
USB20X.NRDYENB = buf;
|
|
buf = USB20X.BEMPENB;
|
|
buf &= (uint16_t)~g_usbx_function_bit_set[pipe];
|
|
USB20X.BEMPENB = buf;
|
|
|
|
usbx_function_set_pid_nak(pipe);
|
|
|
|
/* CurrentPIPE Clear */
|
|
if (RZA_IO_RegRead_16(&USB20X.CFIFOSEL, USB_CFIFOSEL_CURPIPE_SHIFT, USB_CFIFOSEL_CURPIPE) == pipe) {
|
|
RZA_IO_RegWrite_16(&USB20X.CFIFOSEL, 0, USB_CFIFOSEL_CURPIPE_SHIFT, USB_CFIFOSEL_CURPIPE);
|
|
}
|
|
|
|
if (RZA_IO_RegRead_16(&USB20X.D0FIFOSEL, USB_DnFIFOSEL_CURPIPE_SHIFT, USB_DnFIFOSEL_CURPIPE) == pipe) {
|
|
RZA_IO_RegWrite_16(&USB20X.D0FIFOSEL, 0, USB_DnFIFOSEL_CURPIPE_SHIFT, USB_DnFIFOSEL_CURPIPE);
|
|
}
|
|
|
|
if (RZA_IO_RegRead_16(&USB20X.D1FIFOSEL, USB_DnFIFOSEL_CURPIPE_SHIFT, USB_DnFIFOSEL_CURPIPE) == pipe) {
|
|
RZA_IO_RegWrite_16(&USB20X.D1FIFOSEL, 0, USB_DnFIFOSEL_CURPIPE_SHIFT, USB_DnFIFOSEL_CURPIPE);
|
|
}
|
|
|
|
/* PIPE Configuration */
|
|
USB20X.PIPESEL = pipe;
|
|
USB20X.PIPECFG = cfg->pipecfg;
|
|
USB20X.PIPEBUF = cfg->pipebuf;
|
|
USB20X.PIPEMAXP = cfg->pipemaxp;
|
|
USB20X.PIPEPERI = cfg->pipeperi;
|
|
|
|
g_usbx_function_pipecfg[pipe] = cfg->pipecfg;
|
|
g_usbx_function_pipebuf[pipe] = cfg->pipebuf;
|
|
g_usbx_function_pipemaxp[pipe] = cfg->pipemaxp;
|
|
g_usbx_function_pipeperi[pipe] = cfg->pipeperi;
|
|
|
|
/* Buffer Clear */
|
|
usbx_function_set_sqclr(pipe);
|
|
usbx_function_aclrm(pipe);
|
|
|
|
/* init Global */
|
|
g_usbx_function_pipe_status[pipe] = DEVDRV_USBF_PIPE_IDLE;
|
|
g_usbx_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;
|
|
usbx_api_function_CtrlWriteStart(size, buffer);
|
|
}
|
|
|
|
|
|
/*************************************************************************/
|
|
uint32_t USBHAL::EP0getReadResult(uint8_t *buffer)
|
|
{
|
|
memcpy(buffer, (uint8_t*)(&setup_buffer[4]), g_usbx_function_PipeDataSize[USB_FUNCTION_PIPE0]);
|
|
|
|
return g_usbx_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 = usbx_api_function_CtrlReadStart(size, buffer);
|
|
} else {
|
|
/* waits the last transmission */
|
|
/*other blocks*/
|
|
g_usbx_function_data_count[ USB_FUNCTION_PIPE0 ] = size;
|
|
g_usbx_function_data_pointer [ USB_FUNCTION_PIPE0 ] = buffer;
|
|
EP0_read_status = usbx_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 = usbx_api_function_check_pipe_status(pipe, &pipe_size);
|
|
|
|
switch (pipe_status) {
|
|
case DEVDRV_USBF_PIPE_IDLE:
|
|
case DEVDRV_USBF_PIPE_WAIT:
|
|
usbx_api_function_set_pid_nak(pipe);
|
|
usbx_api_function_clear_pipe_status(pipe);
|
|
|
|
usbx_api_function_start_receive_transfer(pipe, max_size, recv_buffer);
|
|
break;
|
|
|
|
default:
|
|
status = EP_PENDING;
|
|
break;
|
|
}
|
|
|
|
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 = usbx_api_function_check_pipe_status(pipe, bytes_read);
|
|
switch (pipe_status) {
|
|
case DEVDRV_USBF_PIPE_IDLE:
|
|
return EP_COMPLETED;
|
|
|
|
case DEVDRV_USBF_PIPE_DONE:
|
|
return EP_COMPLETED;
|
|
|
|
case DEVDRV_USBF_PIPE_WAIT:
|
|
break;
|
|
|
|
default:
|
|
return status;
|
|
}
|
|
|
|
/* sets the output buffer and size */
|
|
g_usbx_function_data_pointer[pipe] = buffer;
|
|
|
|
/* receives data from pipe */
|
|
err = usbx_function_read_buffer(pipe);
|
|
recv_error = err;
|
|
switch (err) {
|
|
case USB_FUNCTION_READEND:
|
|
case USB_FUNCTION_READSHRT:
|
|
case USB_FUNCTION_READOVER:
|
|
*bytes_read = g_usbx_function_PipeDataSize[pipe];
|
|
break;
|
|
|
|
case USB_FUNCTION_READING:
|
|
case DEVDRV_USBF_FIFOERROR:
|
|
break;
|
|
}
|
|
|
|
pipe_status = usbx_api_function_check_pipe_status(pipe, bytes_read);
|
|
switch (pipe_status) {
|
|
case DEVDRV_USBF_PIPE_DONE:
|
|
status = EP_COMPLETED;
|
|
break;
|
|
|
|
case DEVDRV_USBF_PIPE_IDLE:
|
|
case DEVDRV_USBF_PIPE_NORES:
|
|
case DEVDRV_USBF_PIPE_STALL:
|
|
case DEVDRV_USBF_FIFOERROR:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
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 = usbx_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 = usbx_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 = usbx_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 = usbx_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:
|
|
usbx_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);
|
|
|
|
usbx_function_clear_pid_stall(pipe);
|
|
}
|
|
|
|
|
|
/*************************************************************************/
|
|
void USBHAL::unstallEndpoint(uint8_t endpoint)
|
|
{
|
|
uint32_t pipe = EP2PIPE(endpoint);
|
|
|
|
usbx_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 = USB20X.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 = USB20X.BRDYSTS;
|
|
int_sts2 = USB20X.NRDYSTS;
|
|
int_sts3 = USB20X.BEMPSTS;
|
|
int_enb0 = USB20X.INTENB0;
|
|
int_enb2 = USB20X.BRDYENB;
|
|
int_enb3 = USB20X.NRDYENB;
|
|
int_enb4 = USB20X.BEMPENB;
|
|
|
|
if ((int_sts0 & USB_FUNCTION_BITRESM) &&
|
|
(int_enb0 & USB_FUNCTION_BITRSME)) {
|
|
USB20X.INTSTS0 = (uint16_t)~USB_FUNCTION_BITRESM;
|
|
RZA_IO_RegWrite_16(&USB20X.INTENB0, 0, USB_INTENB0_RSME_SHIFT, USB_INTENB0_RSME);
|
|
/*usbx_function_USB_FUNCTION_Resume();*/
|
|
suspendStateChanged(1);
|
|
} else if (
|
|
(int_sts0 & USB_FUNCTION_BITVBINT) &&
|
|
(int_enb0 & USB_FUNCTION_BITVBSE)) {
|
|
USB20X.INTSTS0 = (uint16_t)~USB_FUNCTION_BITVBINT;
|
|
|
|
if (usbx_function_CheckVBUStaus() == DEVDRV_USBF_ON) {
|
|
usbx_function_USB_FUNCTION_Attach();
|
|
} else {
|
|
usbx_function_USB_FUNCTION_Detach();
|
|
}
|
|
} else if (
|
|
(int_sts0 & USB_FUNCTION_BITSOFR) &&
|
|
(int_enb0 & USB_FUNCTION_BITSOFE)) {
|
|
USB20X.INTSTS0 = (uint16_t)~USB_FUNCTION_BITSOFR;
|
|
SOF((USB20X.FRMNUM & USB_FRMNUM_FRNM) >> USB_FRMNUM_FRNM_SHIFT);
|
|
} else if (
|
|
(int_sts0 & USB_FUNCTION_BITDVST) &&
|
|
(int_enb0 & USB_FUNCTION_BITDVSE)) {
|
|
USB20X.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: usbx_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
|
|
*****************************************************************************/
|
|
usbx_function_init_status(); /* memory clear */
|
|
|
|
#if 0
|
|
/* You would program those steps in USBCallback_busReset
|
|
* if the system need the comment out steps.
|
|
*/
|
|
|
|
if (usbx_function_is_hispeed() == USB_FUNCTION_HIGH_SPEED) {
|
|
/* Device Descriptor reset */
|
|
usbx_function_ResetDescriptor(USB_FUNCTION_HIGH_SPEED);
|
|
} else {
|
|
/* Device Descriptor reset */
|
|
usbx_function_ResetDescriptor(USB_FUNCTION_FULL_SPEED);
|
|
}
|
|
#endif
|
|
/* Default Control PIPE reset */
|
|
/*****************************************************************************
|
|
* Function Name: usbx_function_ResetDCP
|
|
* Description : Initializes the default control pipe(DCP).
|
|
* Outline : Reset default control pipe
|
|
* Arguments : none
|
|
* Return Value : none
|
|
*****************************************************************************/
|
|
USB20X.DCPCFG = 0;
|
|
USB20X.DCPMAXP = 64; /*TODO: This value is copied from sample*/
|
|
|
|
USB20X.CFIFOSEL = (uint16_t)(USB_FUNCTION_BITMBW_8 | USB_FUNCTION_BITBYTE_LITTLE);
|
|
USB20X.D0FIFOSEL = (uint16_t)(USB_FUNCTION_BITMBW_8 | USB_FUNCTION_BITBYTE_LITTLE);
|
|
USB20X.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);
|
|
/*usbx_function_USB_FUNCTION_Suspend();*/
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
} else if (
|
|
(int_sts0 & USB_FUNCTION_BITBEMP) &&
|
|
(int_enb0 & USB_FUNCTION_BITBEMP) &&
|
|
((int_sts3 & int_enb4) & g_usbx_function_bit_set[USB_FUNCTION_PIPE0])) {
|
|
/* ==== BEMP PIPE0 ==== */
|
|
usbx_function_BEMPInterruptPIPE0(int_sts3, int_enb4, this, &USBHAL::EP0in);
|
|
} else if (
|
|
(int_sts0 & USB_FUNCTION_BITBRDY) &&
|
|
(int_enb0 & USB_FUNCTION_BITBRDY) &&
|
|
((int_sts1 & int_enb2) & g_usbx_function_bit_set[USB_FUNCTION_PIPE0])) {
|
|
/* ==== BRDY PIPE0 ==== */
|
|
usbx_function_BRDYInterruptPIPE0(int_sts1, int_enb2, this, &USBHAL::EP0out);
|
|
} else if (
|
|
(int_sts0 & USB_FUNCTION_BITNRDY) &&
|
|
(int_enb0 & USB_FUNCTION_BITNRDY) &&
|
|
((int_sts2 & int_enb3) & g_usbx_function_bit_set[USB_FUNCTION_PIPE0])) {
|
|
/* ==== NRDY PIPE0 ==== */
|
|
usbx_function_NRDYInterruptPIPE0(int_sts2, int_enb3, this, NULL);
|
|
} else if (
|
|
(int_sts0 & USB_FUNCTION_BITCTRT) && (int_enb0 & USB_FUNCTION_BITCTRE)) {
|
|
int_sts0 = USB20X.INTSTS0;
|
|
USB20X.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 */
|
|
usbx_function_save_request();
|
|
if ((USB20X.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 = USB20X.INTSTS0;
|
|
dumy_sts = USB20X.INTSTS0;
|
|
dumy_sts = USB20X.INTSTS0;
|
|
return;
|
|
}
|
|
}
|
|
|
|
switch (int_sts0 & USB_FUNCTION_BITCTSQ) {
|
|
case USB_FUNCTION_CS_IDST:
|
|
if (g_usbx_function_TestModeFlag == DEVDRV_USBF_YES) {
|
|
/* ==== Test Mode ==== */
|
|
usbx_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 */
|
|
usbx_function_set_pid_buf(USB_FUNCTION_PIPE0);
|
|
|
|
RZA_IO_RegWrite_16(&USB20X.DCPCTR, 1, USB_DCPCTR_CCPL_SHIFT, USB_DCPCTR_CCPL);
|
|
break;
|
|
|
|
case USB_FUNCTION_CS_RDSS:
|
|
RZA_IO_RegWrite_16(&USB20X.DCPCTR, 1, USB_DCPCTR_CCPL_SHIFT, USB_DCPCTR_CCPL);
|
|
break;
|
|
|
|
case USB_FUNCTION_CS_WRSS:
|
|
RZA_IO_RegWrite_16(&USB20X.DCPCTR, 1, USB_DCPCTR_CCPL_SHIFT, USB_DCPCTR_CCPL);
|
|
break;
|
|
|
|
case USB_FUNCTION_CS_SQER:
|
|
usbx_function_set_pid_stall(USB_FUNCTION_PIPE0);
|
|
break;
|
|
|
|
default:
|
|
usbx_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 ==== */
|
|
usbx_function_BEMPInterrupt(int_sts3, int_enb4, this, epCallback);
|
|
} else if (
|
|
(int_sts0 & USB_FUNCTION_BITBRDY) &&
|
|
(int_enb0 & USB_FUNCTION_BITBRDY) &&
|
|
(int_sts1 & int_enb2) ) {
|
|
/* ==== BRDY PIPEx ==== */
|
|
usbx_function_BRDYInterrupt(int_sts1, int_enb2, this, epCallback);
|
|
} else if (
|
|
(int_sts0 & USB_FUNCTION_BITNRDY) &&
|
|
(int_enb0 & USB_FUNCTION_BITNRDY) &&
|
|
(int_sts2 & int_enb3)) {
|
|
/* ==== NRDY PIPEx ==== */
|
|
usbx_function_NRDYInterrupt(int_sts2, int_enb3, this, epCallback);
|
|
} else {
|
|
/* Do Nothing */
|
|
}
|
|
|
|
/* Three dummy reads for cleearing interrupt requests */
|
|
dumy_sts = USB20X.INTSTS0;
|
|
dumy_sts = USB20X.INTSTS1;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
#endif
|
|
/*************************************************************************/
|
|
/*EOF*/
|