RISC-V/V203/usb/cdc/ch32v203/cdc_class.cpp
2024-10-12 14:02:13 +02:00

678 lines
26 KiB
C++

#include "cdc_class.h"
#include "system.h"
static cdc_class * pInstance = nullptr;
/* Interrupt Service Routine Declaration*/
extern "C" void USBFS_IRQHandler(void) __attribute__((interrupt));
void USBFS_IRQHandler () {
if (pInstance) pInstance->cdc_irq();
}
/* USB_Device_clock_source */
#define RCC_USBCLKSource_PLLCLK_Div1 ((uint8_t)0x00)
#define RCC_USBCLKSource_PLLCLK_Div2 ((uint8_t)0x01)
#define RCC_USBCLKSource_PLLCLK_Div3 ((uint8_t)0x02)
#define RCC_AHBPeriph_USBFS ((uint32_t)0x00001000)
#define RCC_AHBPeriph_OTG_FS RCC_AHBPeriph_USBFS
enum FunctionalState {DISABLE = 0, ENABLE};
static void RCC_USBCLKConfig(uint32_t RCC_USBCLKSource) {
RCC.CFGR0.B.USBPRE = RCC_USBCLKSource;
}
static void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState) {
if (NewState != DISABLE) {
RCC.AHBPCENR.R |= RCC_AHBPeriph;
} else {
RCC.AHBPCENR.R &= ~RCC_AHBPeriph;
}
}
/*********************************************************************
* @fn USBFS_RCC_Init
*
* @brief Initializes the usbfs clock configuration.
*
* @return none
*/
static void USBFS_RCC_Init( void ) {
if( SystemCoreClock == 144000000 ) {
RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div3 );
} else if( SystemCoreClock == 96000000 ) {
RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div2 );
} else if( SystemCoreClock == 48000000 ) {
RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div1 );
}
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_USBFS, ENABLE );
}
/*********************************************************************
* @fn USBFS_Device_Endp_Init
*
* @brief Initializes USB device endpoints.
*
* @return none
*/
void cdc_class::USBFS_Device_Endp_Init( void ) {
USBFSD->UEP4_1_MOD = USBFS_UEP1_TX_EN;
USBFSD->UEP2_3_MOD = USBFS_UEP2_RX_EN|USBFS_UEP3_TX_EN;
USBFSD->UEP0_DMA = (size_t)USBFS_EP0_Buf;
USBFSD->UEP1_DMA = (size_t)USBFS_EP1_Buf;
USBFSD->UEP2_DMA = (size_t)USBFS_EP2_Buf;
USBFSD->UEP3_DMA = (size_t)USBFS_EP3_Buf;
USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_RES_ACK;
USBFSD->UEP2_RX_CTRL = USBFS_UEP_R_RES_ACK;
USBFSD->UEP1_TX_LEN = 0;
USBFSD->UEP3_TX_LEN = 0;
USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK;
USBFSD->UEP1_TX_CTRL = USBFS_UEP_T_RES_NAK;
USBFSD->UEP3_TX_CTRL = USBFS_UEP_T_RES_NAK;
/* Clear End-points Busy Status */
for(uint8_t i=0; i<DEF_UEP_NUM; i++ ) {
USBFS_Endp_Busy[ i ] = 0;
}
}
/*********************************************************************
* @fn USBFS_Device_Init
*
* @brief Initializes USB device.
*
* @return none
*/
void cdc_class::USBFS_Device_Init( bool sta ) {
if( sta ) {
USBFSH->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL;
delay_us( 10 );
USBFSH->BASE_CTRL = 0x00;
USBFSD->INT_EN = USBFS_UIE_SUSPEND | USBFS_UIE_BUS_RST | USBFS_UIE_TRANSFER;
USBFSD->BASE_CTRL = USBFS_UC_DEV_PU_EN | USBFS_UC_INT_BUSY | USBFS_UC_DMA_EN;
USBFS_Device_Endp_Init( );
USBFSD->UDEV_CTRL = USBFS_UD_PD_DIS | USBFS_UD_PORT_EN;
NVIC.EnableIRQ( USBFS_IRQn );
} else {
USBFSH->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL;
delay_us( 10 );
USBFSD->BASE_CTRL = 0x00;
NVIC.DisableIRQ( USBFS_IRQn );
}
dtr << true;
}
/*********************************************************************
* @fn USBFS_Endp_DataUp
*
* @brief USBFS device data upload
*
* @return none
*/
uint8_t cdc_class::USBFS_Endp_DataUp(uint8_t endp, const uint8_t * pbuf, uint16_t len, uint8_t mod) {
uint8_t endp_mode;
uint8_t buf_load_offset;
/* DMA config, endp_ctrl config, endp_len config */
if( (endp>=DEF_UEP1) && (endp<=DEF_UEP7) ) {
if( USBFS_Endp_Busy[ endp ] == 0 ) {
if( (endp == DEF_UEP1) || (endp == DEF_UEP4) ) {
/* endp1/endp4 */
endp_mode = USBFSD_UEP_MOD(0);
if( endp == DEF_UEP1 ) {
endp_mode = (uint8_t)(endp_mode>>4);
}
} else if( (endp == DEF_UEP2) || (endp == DEF_UEP3) ) {
/* endp2/endp3 */
endp_mode = USBFSD_UEP_MOD(1);
if( endp == DEF_UEP3 ) {
endp_mode = (uint8_t)(endp_mode>>4);
}
} else if( (endp == DEF_UEP5) || (endp == DEF_UEP6) ) {
/* endp5/endp6 */
endp_mode = USBFSD_UEP_MOD(2);
if( endp == DEF_UEP6 ) {
endp_mode = (uint8_t)(endp_mode>>4);
}
} else {
/* endp7 */
endp_mode = USBFSD_UEP_MOD(3);
}
if( endp_mode & USBFSD_UEP_TX_EN ) {
if( endp_mode & USBFSD_UEP_RX_EN ) {
buf_load_offset = 64;
} else {
buf_load_offset = 0;
}
if( buf_load_offset == 0 ) {
if( mod == DEF_UEP_DMA_LOAD ) {
/* DMA mode */
USBFSD_UEP_DMA(endp) = (uint16_t)(size_t)pbuf;
} else {
/* copy mode */
memcpy( USBFSD_UEP_BUF(endp), pbuf, len );
}
} else {
memcpy( USBFSD_UEP_BUF(endp)+buf_load_offset, pbuf, len );
}
/* Set end-point busy */
USBFS_Endp_Busy[ endp ] = 0x01;
/* tx length */
USBFSD_UEP_TLEN(endp) = len;
/* response ack */
USBFSD_UEP_CTRL(endp) = (USBFSD_UEP_CTRL(endp) & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK;
}
} else {
return 1;
}
} else {
return 1;
}
return 0;
}
cdc_class::cdc_class() noexcept : BaseLayer(), dtr (GPIOA, 0), Ready(false) {
pInstance = this;
USBFS_DevConfig = 0;
USBFS_DevAddr = 0;
USBFS_DevSleepStatus = 0;
USBFS_DevEnumStatus = 0;
}
void cdc_class::init() {
delay_init();
USBFS_RCC_Init( );
USBFS_Device_Init( true );
while (!USBFS_DevEnumStatus);
}
__always_inline void cdc_class::InTokenHandler(const uint8_t intst) {
switch ( intst & ( USBFS_UIS_TOKEN_MASK | USBFS_UIS_ENDP_MASK ) ) {
/* end-point 0 data in interrupt */
case USBFS_UIS_TOKEN_IN | DEF_UEP0:
if( USBFS_SetupReqLen == 0 ) {
USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_TOG | USBFS_UEP_R_RES_ACK;
}
if ( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) {
/* Non-standard request endpoint 0 Data upload */
} else {
/* Standard request endpoint 0 Data upload */
switch( USBFS_SetupReqCode ) {
case USB_GET_DESCRIPTOR: {
const uint16_t len = USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen;
memcpy( USBFS_EP0_Buf, pUSBFS_Descr, len );
USBFS_SetupReqLen -= len;
pUSBFS_Descr += len;
USBFSD->UEP0_TX_LEN = len;
USBFSD->UEP0_TX_CTRL ^= USBFS_UEP_T_TOG;
} break;
case USB_SET_ADDRESS:
USBFSD->DEV_ADDR = (USBFSD->DEV_ADDR & USBFS_UDA_GP_BIT) | USBFS_DevAddr;
break;
default:
break;
}
}
break;
/* end-point 1 data in interrupt */
case ( USBFS_UIS_TOKEN_IN | DEF_UEP1 ):
USBFSD->UEP1_TX_CTRL ^= USBFS_UEP_T_TOG;
USBFSD->UEP1_TX_CTRL = (USBFSD->UEP1_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK;
USBFS_Endp_Busy[ DEF_UEP1 ] = 0;
break;
/* end-point 3 data in interrupt */
case ( USBFS_UIS_TOKEN_IN | DEF_UEP3 ):
USBFSD->UEP3_TX_CTRL ^= USBFS_UEP_T_TOG;
USBFSD->UEP3_TX_CTRL = (USBFSD->UEP3_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK;
USBFS_Endp_Busy[ DEF_UEP3 ] = 0;
TxDataDeal ();
break;
default :
break;
}
}
__always_inline void cdc_class::OutTokenHandler(const uint8_t intst) {
uint16_t len;
switch ( intst & ( USBFS_UIS_TOKEN_MASK | USBFS_UIS_ENDP_MASK ) ) {
/* end-point 0 data out interrupt */
case USBFS_UIS_TOKEN_OUT | DEF_UEP0:
len = USBFSD->RX_LEN;
(void) len;
if ( intst & USBFS_UIS_TOG_OK ) {
if ( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) {
/* Non-standard request end-point 0 Data download */
USBFS_SetupReqLen = 0;
/* Non-standard request end-point 0 Data download */
if( USBFS_SetupReqCode == CDC_SET_LINE_CODING ) {
/* Save relevant parameters such as serial port baud rate */
/* The downlinked data is processed in the endpoint 0 OUT packet, the 7 bytes of the downlink are, in order
4 bytes: baud rate value: lowest baud rate byte, next lowest baud rate byte, next highest baud rate byte, highest baud rate byte.
1 byte: number of stop bits (0: 1 stop bit; 1: 1.5 stop bit; 2: 2 stop bits).
1 byte: number of parity bits (0: None; 1: Odd; 2: Even; 3: Mark; 4: Space).
1 byte: number of data bits (5,6,7,8,16); */
/*
Uart.Com_Cfg[ 0 ] = USBFS_EP0_Buf[ 0 ];
Uart.Com_Cfg[ 1 ] = USBFS_EP0_Buf[ 1 ];
Uart.Com_Cfg[ 2 ] = USBFS_EP0_Buf[ 2 ];
Uart.Com_Cfg[ 3 ] = USBFS_EP0_Buf[ 3 ];
Uart.Com_Cfg[ 4 ] = USBFS_EP0_Buf[ 4 ];
Uart.Com_Cfg[ 5 ] = USBFS_EP0_Buf[ 5 ];
Uart.Com_Cfg[ 6 ] = USBFS_EP0_Buf[ 6 ];
Uart.Com_Cfg[ 7 ] = DEF_UARTx_RX_TIMEOUT;
baudrate = USBFS_EP0_Buf[ 0 ];
baudrate += ((uint32_t)USBFS_EP0_Buf[ 1 ] << 8 );
baudrate += ((uint32_t)USBFS_EP0_Buf[ 2 ] << 16 );
baudrate += ((uint32_t)USBFS_EP0_Buf[ 3 ] << 24 );
Uart.Com_Cfg[ 7 ] = Uart.Rx_TimeOutMax;
UART2_USB_Init( );
*/
}
} else {
/* Standard request end-point 0 Data download */
/* Add your code here */
}
if( USBFS_SetupReqLen == 0 ) {
USBFSD->UEP0_TX_LEN = 0;
USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK;
}
}
break;
/* end-point 1 data out interrupt */
case USBFS_UIS_TOKEN_OUT | DEF_UEP2: {
USBFSD->UEP2_RX_CTRL ^= USBFS_UEP_R_TOG;
const uint32_t rlen = USBFSD->RX_LEN;
const char *ptr = reinterpret_cast<const char*> (USBFS_EP2_Buf);
USBFSD->UEP2_RX_CTRL = (USBFSD->UEP2_RX_CTRL & ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_NAK;
Up (ptr, rlen);
USBFSD->UEP2_RX_CTRL = (USBFSD->UEP2_RX_CTRL & ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_ACK;
} break;
default:
break;
}
}
void cdc_class::SetupTokenHandler() {
uint8_t errflag;
uint16_t len;
USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_TOG|USBFS_UEP_T_RES_NAK;
USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_TOG|USBFS_UEP_R_RES_NAK;
/* Store All Setup Values */
USBFS_SetupReqType = pUSBFS_SetupReqPak->bRequestType;
USBFS_SetupReqCode = pUSBFS_SetupReqPak->bRequest;
USBFS_SetupReqLen = pUSBFS_SetupReqPak->wLength;
USBFS_SetupReqValue = pUSBFS_SetupReqPak->wValue;
USBFS_SetupReqIndex = pUSBFS_SetupReqPak->wIndex;
len = 0;
errflag = 0;
if ( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) {
/* usb non-standard request processing */
if( USBFS_SetupReqType & USB_REQ_TYP_CLASS ) {
/* Class requests */
switch( USBFS_SetupReqCode ) {
case CDC_GET_LINE_CODING:
// pUSBFS_Descr = (uint8_t *)&Uart.Com_Cfg[ 0 ];
len = 7;
break;
case CDC_SET_LINE_CODING:
break;
/* TODO: DTR - wValue & 1 */
case CDC_SET_LINE_CTLSTE: {
const bool b = USBFS_SetupReqValue & 1;
Ready = b;
dtr << !b;
} break;
case CDC_SEND_BREAK:
break;
default:
errflag = 0xff;
break;
}
} else if ( USBFS_SetupReqType & USB_REQ_TYP_VENDOR ) {
/* Manufacturer request */
} else {
errflag = 0xFF;
}
/* Copy Descriptors to Endp0 DMA buffer */
len = (USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE) ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen;
memcpy( USBFS_EP0_Buf, pUSBFS_Descr, len );
pUSBFS_Descr += len;
} else {
/* usb standard request processing */
switch( USBFS_SetupReqCode ) {
/* get device/configuration/string/report/... descriptors */
case USB_GET_DESCRIPTOR:
switch( (uint8_t)( USBFS_SetupReqValue >> 8 ) ) {
/* get usb device descriptor */
case USB_DESCR_TYP_DEVICE:
pUSBFS_Descr = MyDevDescr;
len = DEF_USBD_DEVICE_DESC_LEN;
break;
/* get usb configuration descriptor */
case USB_DESCR_TYP_CONFIG:
pUSBFS_Descr = MyCfgDescr;
len = DEF_USBD_CONFIG_DESC_LEN;
break;
/* get usb string descriptor */
case USB_DESCR_TYP_STRING:
switch( (uint8_t)( USBFS_SetupReqValue & 0xFF ) ) {
/* Descriptor 0, Language descriptor */
case DEF_STRING_DESC_LANG:
pUSBFS_Descr = MyLangDescr;
len = DEF_USBD_LANG_DESC_LEN;
break;
/* Descriptor 1, Manufacturers String descriptor */
case DEF_STRING_DESC_MANU:
pUSBFS_Descr = MyManuInfo;
len = DEF_USBD_MANU_DESC_LEN;
break;
/* Descriptor 2, Product String descriptor */
case DEF_STRING_DESC_PROD:
pUSBFS_Descr = MyProdInfo;
len = DEF_USBD_PROD_DESC_LEN;
break;
/* Descriptor 3, Serial-number String descriptor */
case DEF_STRING_DESC_SERN:
pUSBFS_Descr = MySerNumInfo;
len = DEF_USBD_SN_DESC_LEN;
break;
default:
errflag = 0xFF;
break;
}
break;
default :
errflag = 0xFF;
break;
}
/* Copy Descriptors to Endp0 DMA buffer */
if( USBFS_SetupReqLen>len ) {
USBFS_SetupReqLen = len;
}
len = (USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE) ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen;
memcpy( USBFS_EP0_Buf, pUSBFS_Descr, len );
pUSBFS_Descr += len;
break;
/* Set usb address */
case USB_SET_ADDRESS:
USBFS_DevAddr = (uint8_t)( USBFS_SetupReqValue & 0xFF );
break;
/* Get usb configuration now set */
case USB_GET_CONFIGURATION:
USBFS_EP0_Buf[0] = USBFS_DevConfig;
if ( USBFS_SetupReqLen > 1 ) {
USBFS_SetupReqLen = 1;
}
break;
/* Set usb configuration to use */
case USB_SET_CONFIGURATION:
USBFS_DevConfig = (uint8_t)( USBFS_SetupReqValue & 0xFF );
USBFS_DevEnumStatus = 0x01;
break;
/* Clear or disable one usb feature */
case USB_CLEAR_FEATURE:
if ( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE ) {
/* clear one device feature */
if( (uint8_t)( USBFS_SetupReqValue & 0xFF ) == USB_REQ_FEAT_REMOTE_WAKEUP ) {
/* clear usb sleep status, device not prepare to sleep */
USBFS_DevSleepStatus &= ~0x01;
}
} else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) {
/* Clear End-point Feature */
if( (uint8_t)( USBFS_SetupReqValue & 0xFF ) == USB_REQ_FEAT_ENDP_HALT ) {
switch( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) ) {
case ( DEF_UEP_IN | DEF_UEP1 ):
/* Set End-point 1 IN NAK */
USBFSD->UEP1_TX_CTRL = USBFS_UEP_T_RES_NAK;
break;
case ( DEF_UEP_OUT | DEF_UEP2 ):
/* Set End-point 2 OUT ACK */
USBFSD->UEP2_RX_CTRL = USBFS_UEP_R_RES_ACK;
break;
case ( DEF_UEP_IN | DEF_UEP3 ):
/* Set End-point 3 IN NAK */
USBFSD->UEP3_TX_CTRL = USBFS_UEP_T_RES_NAK;
break;
default:
errflag = 0xFF;
break;
}
} else {
errflag = 0xFF;
}
} else {
errflag = 0xFF;
}
break;
/* set or enable one usb feature */
case USB_SET_FEATURE:
if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE ) {
/* Set Device Feature */
if( (uint8_t)( USBFS_SetupReqValue & 0xFF ) == USB_REQ_FEAT_REMOTE_WAKEUP ) {
if( MyCfgDescr[ 7 ] & 0x20 ) {
/* Set Wake-up flag, device prepare to sleep */
USBFS_DevSleepStatus |= 0x01;
} else {
errflag = 0xFF;
}
} else {
errflag = 0xFF;
}
}
else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) {
/* Set End-point Feature */
if( (uint8_t)( USBFS_SetupReqValue & 0xFF ) == USB_REQ_FEAT_ENDP_HALT ) {
/* Set end-points status stall */
switch( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) ) {
case ( DEF_UEP_IN | DEF_UEP1 ):
/* Set End-point 1 IN STALL */
USBFSD->UEP1_TX_CTRL = ( USBFSD->UEP1_TX_CTRL & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_STALL;
break;
case ( DEF_UEP_OUT | DEF_UEP2 ):
/* Set End-point 2 OUT STALL */
USBFSD->UEP2_RX_CTRL = ( USBFSD->UEP2_RX_CTRL & ~USBFS_UEP_R_RES_MASK ) | USBFS_UEP_R_RES_STALL;
break;
case ( DEF_UEP_IN | DEF_UEP3 ):
/* Set End-point 3 IN STALL */
USBFSD->UEP3_TX_CTRL = ( USBFSD->UEP3_TX_CTRL & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_STALL;
break;
default:
errflag = 0xFF;
break;
}
} else {
errflag = 0xFF;
}
} else {
errflag = 0xFF;
}
break;
/* This request allows the host to select another setting for the specified interface */
case USB_GET_INTERFACE:
USBFS_EP0_Buf[0] = 0x00;
if ( USBFS_SetupReqLen > 1 ) {
USBFS_SetupReqLen = 1;
}
break;
case USB_SET_INTERFACE:
break;
/* host get status of specified device/interface/end-points */
case USB_GET_STATUS:
USBFS_EP0_Buf[ 0 ] = 0x00;
USBFS_EP0_Buf[ 1 ] = 0x00;
if ( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE ) {
if( USBFS_DevSleepStatus & 0x01 ) {
USBFS_EP0_Buf[ 0 ] = 0x02;
}
} else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) {
switch( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) ) {
case ( DEF_UEP_IN | DEF_UEP1 ):
if( ( (USBFSD->UEP1_TX_CTRL) & USBFS_UEP_T_RES_MASK ) == USBFS_UEP_T_RES_STALL ) {
USBFS_EP0_Buf[ 0 ] = 0x01;
}
break;
case ( DEF_UEP_OUT | DEF_UEP2 ):
if( ( (USBFSD->UEP2_RX_CTRL) & USBFS_UEP_R_RES_MASK ) == USBFS_UEP_R_RES_STALL ) {
USBFS_EP0_Buf[ 0 ] = 0x01;
}
break;
case ( DEF_UEP_IN | DEF_UEP3 ):
if( ( (USBFSD->UEP3_TX_CTRL) & USBFS_UEP_T_RES_MASK ) == USBFS_UEP_T_RES_STALL ) {
USBFS_EP0_Buf[ 0 ] = 0x01;
}
break;
default:
errflag = 0xFF;
break;
}
} else {
errflag = 0xFF;
}
if( USBFS_SetupReqLen > 2 ) {
USBFS_SetupReqLen = 2;
}
break;
default:
errflag = 0xFF;
break;
}
}
/* errflag = 0xFF means a request not support or some errors occurred, else correct */
if( errflag == 0xff) {
/* if one request not support, return stall */
USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_TOG|USBFS_UEP_T_RES_STALL;
USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_TOG|USBFS_UEP_R_RES_STALL;
} else {
/* end-point 0 data Tx/Rx */
if( USBFS_SetupReqType & DEF_UEP_IN ) {
/* tx */
len = (USBFS_SetupReqLen>DEF_USBD_UEP0_SIZE) ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen;
USBFS_SetupReqLen -= len;
USBFSD->UEP0_TX_LEN = len;
USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_TOG|USBFS_UEP_T_RES_ACK;
} else {
/* rx */
if( USBFS_SetupReqLen == 0 ) {
USBFSD->UEP0_TX_LEN = 0;
USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_TOG|USBFS_UEP_T_RES_ACK;
} else {
USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_TOG|USBFS_UEP_R_RES_ACK;
}
}
}
}
__always_inline void cdc_class::TransferHandler() {
const uint8_t intst = USBFSD->INT_ST;
switch (intst & USBFS_UIS_TOKEN_MASK) {
/* data-in stage processing */
case USBFS_UIS_TOKEN_IN:
InTokenHandler(intst);
break;
/* data-out stage processing */
case USBFS_UIS_TOKEN_OUT:
OutTokenHandler(intst);
break;
/* Setup stage processing */
case USBFS_UIS_TOKEN_SETUP:
SetupTokenHandler();
break;
default :
break;
}
USBFSD->INT_FG = USBFS_UIF_TRANSFER;
}
void cdc_class::cdc_irq() {
const uint8_t intflag = USBFSD->INT_FG;
if( intflag & USBFS_UIF_TRANSFER ) {
TransferHandler ();
} else if( intflag & USBFS_UIF_BUS_RST ) {
/* usb reset interrupt processing */
USBFS_DevConfig = 0;
USBFS_DevAddr = 0;
USBFS_DevSleepStatus = 0;
USBFS_DevEnumStatus = 0;
USBFSD->DEV_ADDR = 0;
USBFS_Device_Endp_Init( );
//UART2_ParaInit( 1 );
USBFSD->INT_FG = USBFS_UIF_BUS_RST;
} else if( intflag & USBFS_UIF_SUSPEND ) {
USBFSD->INT_FG = USBFS_UIF_SUSPEND;
delay_us(10);
/* usb suspend interrupt processing */
if ( USBFSD->MIS_ST & USBFS_UMS_SUSPEND ) {
USBFS_DevSleepStatus |= 0x02;
if( USBFS_DevSleepStatus == 0x03 ) {
/* Handling usb sleep here */
}
} else {
USBFS_DevSleepStatus &= ~0x02;
}
} else {
/* other interrupts */
USBFSD->INT_FG = intflag;
}
}
void cdc_class::TxDataDeal() {
/* Asi by to mělo fungovat nějak přes frontu, ale zatím nevím jak to nastartovat, nepoužito */
}
/* Pozor - funkce je blokující, lze použít jen v hlavní smyčce programu, ne v přerušení */
uint32_t cdc_class::Down (const char * data, const uint32_t len) {
if ((!Ready) or (!USBFS_DevEnumStatus)) return 0;
uint32_t rem = len;
const uint32_t max = DEF_USBD_ENDP3_SIZE;
const uint8_t * ptr = reinterpret_cast<const uint8_t*> (data);
while (rem) {
const uint32_t chunk = rem > max ? max : rem;
if (USBFS_Endp_DataUp (DEF_UEP3, ptr, chunk, DEF_UEP_CPY_LOAD)) {
delay_us(10); // čekej dokud je USBFS_Endp_Busy
} else {
ptr += chunk;
rem -= chunk;
}
}
return len;
}