diff --git a/V203/usb/cdc/ch32v203/baselayer.h b/V203/usb/cdc/ch32v203/baselayer.h index 9a90cc6..9047b49 100644 --- a/V203/usb/cdc/ch32v203/baselayer.h +++ b/V203/usb/cdc/ch32v203/baselayer.h @@ -2,15 +2,6 @@ #define BASELAYER_H #include -#ifdef __arm__ -#define debug(...) -#else // ARCH_CM0 -#ifdef DEBUG -#define debug printf -#else // DEBUG -#define debug(...) -#endif // DEBUG -#endif // ARCH_CM0 /** @brief Bázová třída pro stack trochu obecnějšího komunikačního protokolu. * * @class BaseLayer diff --git a/V203/usb/cdc/ch32v203/cdc_class.cpp b/V203/usb/cdc/ch32v203/cdc_class.cpp index f92f73b..ce062f6 100644 --- a/V203/usb/cdc/ch32v203/cdc_class.cpp +++ b/V203/usb/cdc/ch32v203/cdc_class.cpp @@ -1,31 +1,28 @@ #include "cdc_class.h" #include "system.h" - +typedef __SIZE_TYPE__ size_t; +/* Only one instance of this class ! */ static cdc_class * pInstance = nullptr; -/* Interrupt Service Routine Declaration*/ -extern "C" void USBFS_IRQHandler(void) __attribute__((interrupt)); +extern "C" { + /* Interrupt Service Routine Declaration*/ + [[gnu::interrupt]] void USBFS_IRQHandler(); + /* prototype from libc, (hack.c), clang needed */ + void * memcpy (void * dest, const void * src, size_t n); +}; +/* Interrupt Service Routine Definition */ 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}; +enum RCC_USB_CLK_SRC : uint32_t { + RCC_USBCLKSource_PLLCLK_Div1 = 0u, + RCC_USBCLKSource_PLLCLK_Div2, + RCC_USBCLKSource_PLLCLK_Div3, +}; -static void RCC_USBCLKConfig(uint32_t RCC_USBCLKSource) { +static void RCC_USBCLKConfig(const RCC_USB_CLK_SRC 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 * @@ -34,14 +31,14 @@ static void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewSta * @return none */ static void USBFS_RCC_Init( void ) { - if( SystemCoreClock == 144000000 ) { + if( SystemCoreClock == 144'000'000 ) { RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div3 ); - } else if( SystemCoreClock == 96000000 ) { + } else if( SystemCoreClock == 96'000'000 ) { RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div2 ); - } else if( SystemCoreClock == 48000000 ) { + } else if( SystemCoreClock == 48'000'000 ) { RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div1 ); } - RCC_AHBPeriphClockCmd( RCC_AHBPeriph_USBFS, ENABLE ); + RCC.AHBPCENR.B.OTG_EN = SET; } /********************************************************************* * @fn USBFS_Device_Endp_Init @@ -89,10 +86,10 @@ void cdc_class::USBFS_Device_Init( bool 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->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; + 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; @@ -103,7 +100,8 @@ void cdc_class::USBFS_Device_Init( bool sta ) { dtr << true; } -cdc_class::cdc_class() noexcept : BaseLayer(), dtr (GPIOA, 0), TxRing(), Ready(false) { +cdc_class::cdc_class() noexcept : BaseLayer(), + CtrlIface(nullptr), dtr (GPIOA, 0), TxRing(), Ready(false), LineCoding() { pInstance = this; USBFS_DevConfig = 0; USBFS_DevAddr = 0; @@ -116,7 +114,7 @@ void cdc_class::init() { USBFS_Device_Init( true ); while (!USBFS_DevEnumStatus) delay_us(10'000); } -__always_inline void cdc_class::InTokenHandler(const uint8_t intst) { +[[gnu::__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: @@ -164,7 +162,7 @@ __always_inline void cdc_class::InTokenHandler(const uint8_t intst) { break; } } -__always_inline void cdc_class::OutTokenHandler(const uint8_t intst) { +[[gnu::__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 */ @@ -183,24 +181,8 @@ __always_inline void cdc_class::OutTokenHandler(const uint8_t intst) { 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( ); - */ + memcpy(& LineCoding, USBFS_EP0_Buf, sizeof (LineCoding)); + if (CtrlIface) CtrlIface->IOCtrl(USB_USART_SET_PARAM, & LineCoding, sizeof (LineCoding)); } } else { /* Standard request end-point 0 Data download */ @@ -227,7 +209,12 @@ __always_inline void cdc_class::OutTokenHandler(const uint8_t intst) { break; } } -void cdc_class::SetupTokenHandler() { +union DtrRts { + uint16_t data; + uint8_t bytes [2]; + explicit DtrRts (const uint16_t n) noexcept { data = n; } +}; +[[gnu::__always_inline__]] void cdc_class::SetupTokenHandler() { uint8_t errflag; uint16_t len; USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_TOG|USBFS_UEP_T_RES_NAK; @@ -247,13 +234,16 @@ void cdc_class::SetupTokenHandler() { switch( USBFS_SetupReqCode ) { case CDC_GET_LINE_CODING: // pUSBFS_Descr = (uint8_t *)&Uart.Com_Cfg[ 0 ]; - len = 7; + pUSBFS_Descr = reinterpret_cast(& LineCoding); + len = sizeof (LineCoding); break; case CDC_SET_LINE_CODING: break; - /* TODO: DTR - wValue & 1 */ + /* DTR - wValue & 1, RTS - wValue & 2 */ case CDC_SET_LINE_CTLSTE: { + DtrRts tmp (USBFS_SetupReqValue); + if (CtrlIface) CtrlIface->IOCtrl(USB_USART_SET_DTR_RTS, tmp.bytes, 2); const bool b = USBFS_SetupReqValue & 1; Ready = b; dtr << !b; @@ -507,7 +497,7 @@ void cdc_class::SetupTokenHandler() { } } -__always_inline void cdc_class::TransferHandler() { +[[gnu::__always_inline__]] void cdc_class::TransferHandler() { const uint8_t intst = USBFSD->INT_ST; switch (intst & USBFS_UIS_TOKEN_MASK) { @@ -533,7 +523,7 @@ void cdc_class::cdc_irq() { const uint8_t intflag = USBFSD->INT_FG; if( intflag & USBFS_UIF_TRANSFER ) { - TransferHandler (); + TransferHandler (); } else if( intflag & USBFS_UIF_BUS_RST ) { /* usb reset interrupt processing */ USBFS_DevConfig = 0; @@ -544,6 +534,7 @@ void cdc_class::cdc_irq() { USBFSD->DEV_ADDR = 0; USBFS_Device_Endp_Init( ); //UART2_ParaInit( 1 ); + if (CtrlIface) CtrlIface->IOCtrl(USB_USART_INIT, nullptr, 0); USBFSD->INT_FG = USBFS_UIF_BUS_RST; } else if( intflag & USBFS_UIF_SUSPEND ) { USBFSD->INT_FG = USBFS_UIF_SUSPEND; diff --git a/V203/usb/cdc/ch32v203/cdc_class.h b/V203/usb/cdc/ch32v203/cdc_class.h index 821e6e4..7dae761 100644 --- a/V203/usb/cdc/ch32v203/cdc_class.h +++ b/V203/usb/cdc/ch32v203/cdc_class.h @@ -1,48 +1,31 @@ #ifndef CDC_CLASS_H #define CDC_CLASS_H #include "baselayer.h" +#include "ctrlinterface.h" #include "gpio.h" #include "fifo.h" #include "system.h" #ifdef __cplusplus extern "C" { #endif -#include #include "usb_desc.h" #include "ch32v20x_usb.h" - /******************************************************************************/ /* Global Define */ /* end-point number */ +enum EDEF_UEPS { + DEF_UEP0 = 0, DEF_UEP1, DEF_UEP2, DEF_UEP3, DEF_UEP4, DEF_UEP5, DEF_UEP6, DEF_UEP7, MAX_UEPS +}; +static constexpr uint32_t DEF_UEP_NUM = MAX_UEPS; +static_assert (DEF_UEP_NUM == 8, "Number endpoints fail"); +// Tohle nechám být, je to celkem jedno #define DEF_UEP_IN 0x80 #define DEF_UEP_OUT 0x00 -#define DEF_UEP0 0x00 -#define DEF_UEP1 0x01 -#define DEF_UEP2 0x02 -#define DEF_UEP3 0x03 -#define DEF_UEP4 0x04 -#define DEF_UEP5 0x05 -#define DEF_UEP6 0x06 -#define DEF_UEP7 0x07 -#define DEF_UEP_NUM 8 - -#define USBFSD_UEP_MOD_BASE 0x5000000C -#define USBFSD_UEP_DMA_BASE 0x50000010 -#define USBFSD_UEP_LEN_BASE 0x50000030 -#define USBFSD_UEP_CTL_BASE 0x50000032 #define USBFSD_UEP_RX_EN 0x08 #define USBFSD_UEP_TX_EN 0x04 #define USBFSD_UEP_BUF_MOD 0x01 -#define DEF_UEP_DMA_LOAD 0 /* Direct the DMA address to the data to be processed */ -#define DEF_UEP_CPY_LOAD 1 /* Use memcpy to move data to a buffer */ -#define USBFSD_UEP_MOD(n) (*((volatile uint8_t *)(USBFSD_UEP_MOD_BASE+n))) -#define USBFSD_UEP_CTRL(n) (*((volatile uint8_t *)(USBFSD_UEP_CTL_BASE+n*0x04))) -#define USBFSD_UEP_DMA(n) (*((volatile uint32_t *)(USBFSD_UEP_DMA_BASE+n*0x04))) -#define USBFSD_UEP_BUF(n) ((uint8_t *)(*((volatile uint32_t *)(USBFSD_UEP_DMA_BASE+n*0x04)))+0x20000000) -#define USBFSD_UEP_TLEN(n) (*((volatile uint16_t *)(USBFSD_UEP_LEN_BASE+n*0x04))) - /* Setup Request Packets */ -#define pUSBFS_SetupReqPak ((PUSB_SETUP_REQ)USBFS_EP0_Buf) +#define pUSBFS_SetupReqPak ((PUSB_SETUP_REQ)USBFS_EP0_Buf) #ifdef __cplusplus }; #endif @@ -53,10 +36,12 @@ extern "C" { * přidáno odhadem. */ class cdc_class : public BaseLayer { - GpioClass dtr; - FIFO TxRing; - bool Ready; - const uint8_t * pUSBFS_Descr; + CDC_CtrlInterface * CtrlIface; + GpioClass dtr; + FIFO TxRing; + volatile bool Ready; + USB_CDC_LineCoding LineCoding; + const uint8_t * pUSBFS_Descr; /* Setup Request */ volatile uint8_t USBFS_SetupReqCode; volatile uint8_t USBFS_SetupReqType; @@ -69,14 +54,15 @@ class cdc_class : public BaseLayer { volatile uint8_t USBFS_DevSleepStatus; volatile uint8_t USBFS_DevEnumStatus; /* Endpoint Buffer */ - __attribute__ ((aligned(4))) uint8_t USBFS_EP0_Buf[ DEF_USBD_UEP0_SIZE ]; - __attribute__ ((aligned(4))) uint8_t USBFS_EP1_Buf[ DEF_USBD_ENDP1_SIZE ]; - __attribute__ ((aligned(4))) uint8_t USBFS_EP2_Buf[ DEF_USBD_ENDP2_SIZE ]; - __attribute__ ((aligned(4))) uint8_t USBFS_EP3_Buf[ DEF_USBD_ENDP3_SIZE ]; + [[gnu::aligned(4)]] uint8_t USBFS_EP0_Buf[ DEF_USBD_UEP0_SIZE ]; + [[gnu::aligned(4)]] uint8_t USBFS_EP1_Buf[ DEF_USBD_ENDP1_SIZE ]; + [[gnu::aligned(4)]] uint8_t USBFS_EP2_Buf[ DEF_USBD_ENDP2_SIZE ]; + [[gnu::aligned(4)]] uint8_t USBFS_EP3_Buf[ DEF_USBD_ENDP3_SIZE ]; /* USB IN Endpoint Busy Flag */ volatile uint8_t USBFS_Endp_Busy[ DEF_UEP_NUM ]; public: explicit cdc_class () noexcept; + void attach (CDC_CtrlInterface & ctrl) { CtrlIface = & ctrl; } void init (); void cdc_irq (); /// Předěláno na neblokující, data se vyměňují přes FIFO, rychlejší @@ -85,10 +71,10 @@ class cdc_class : public BaseLayer { void USBFS_Device_Init( bool sta ); void USBFS_Device_Endp_Init (); void TxDataDeal (); - void TransferHandler (); - void InTokenHandler (const uint8_t intst); - void OutTokenHandler (const uint8_t intst); - void SetupTokenHandler (); + inline void TransferHandler (); + inline void InTokenHandler (const uint8_t intst); + inline void OutTokenHandler (const uint8_t intst); + inline void SetupTokenHandler (); }; #endif // CDC_CLASS_H diff --git a/V203/usb/cdc/ch32v203/ctrlinterface.h b/V203/usb/cdc/ch32v203/ctrlinterface.h new file mode 100644 index 0000000..291407a --- /dev/null +++ b/V203/usb/cdc/ch32v203/ctrlinterface.h @@ -0,0 +1,29 @@ +#ifndef CTRLINTERFACE_DEF_H +#define CTRLINTERFACE_DEF_H +#include +enum CTRL_TYPES_DEF { + UNKNOWN_TYPE = 0, + USB_USART_SET_PARAM, + USB_USART_SET_DTR_RTS, + USB_USART_INIT, +}; +struct USB_CDC_LineCoding { + uint32_t baud; + uint8_t stop, parity, data; + explicit USB_CDC_LineCoding () noexcept : baud (57600u), stop (0u), parity (0u), data (8u) {} +}__attribute__((packed)); +static_assert (sizeof(USB_CDC_LineCoding) == 7, "USB_CDC_LineCoding size error"); +/** @class CtrlInterface + * Abstraktní interface, které je možné podědit třeba ve třídě USART a pomocí + * jediné virtuální metody zadefinovat chování při událostech měnících parametry + * přenosu, přicházejících po USB. Fakticky místo callback funkce, nutí to + * IOCtrl() opravdu přetížit. + * Je to mimo třídu BaseLayer, protože Up třída nemusí být totožná s kontrolní. + * V cdc_class se proto musí nastavit na toto ukazatel pomocí metody attach(). + * */ +class CDC_CtrlInterface { + public: + virtual bool IOCtrl (const CTRL_TYPES_DEF type, const void * data, const uint32_t len) = 0; +}; + +#endif // CTRLINTERFACE_DEF_H