add ctrl interface

This commit is contained in:
Kizarm 2024-10-14 16:50:40 +02:00
parent c1cf18d047
commit 34e58e1b2b
4 changed files with 93 additions and 96 deletions

View file

@ -2,15 +2,6 @@
#define BASELAYER_H #define BASELAYER_H
#include <stdint.h> #include <stdint.h>
#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. /** @brief Bázová třída pro stack trochu obecnějšího komunikačního protokolu.
* *
* @class BaseLayer * @class BaseLayer

View file

@ -1,31 +1,28 @@
#include "cdc_class.h" #include "cdc_class.h"
#include "system.h" #include "system.h"
typedef __SIZE_TYPE__ size_t;
/* Only one instance of this class ! */
static cdc_class * pInstance = nullptr; static cdc_class * pInstance = nullptr;
/* Interrupt Service Routine Declaration*/ extern "C" {
extern "C" void USBFS_IRQHandler(void) __attribute__((interrupt)); /* 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 () { void USBFS_IRQHandler () {
if (pInstance) pInstance->cdc_irq(); if (pInstance) pInstance->cdc_irq();
} }
/* USB_Device_clock_source */ /* USB_Device_clock_source */
#define RCC_USBCLKSource_PLLCLK_Div1 ((uint8_t)0x00) enum RCC_USB_CLK_SRC : uint32_t {
#define RCC_USBCLKSource_PLLCLK_Div2 ((uint8_t)0x01) RCC_USBCLKSource_PLLCLK_Div1 = 0u,
#define RCC_USBCLKSource_PLLCLK_Div3 ((uint8_t)0x02) RCC_USBCLKSource_PLLCLK_Div2,
#define RCC_AHBPeriph_USBFS ((uint32_t)0x00001000) RCC_USBCLKSource_PLLCLK_Div3,
#define RCC_AHBPeriph_OTG_FS RCC_AHBPeriph_USBFS };
enum FunctionalState {DISABLE = 0, ENABLE};
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; 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 * @fn USBFS_RCC_Init
* *
@ -34,14 +31,14 @@ static void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewSta
* @return none * @return none
*/ */
static void USBFS_RCC_Init( void ) { static void USBFS_RCC_Init( void ) {
if( SystemCoreClock == 144000000 ) { if( SystemCoreClock == 144'000'000 ) {
RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div3 ); RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div3 );
} else if( SystemCoreClock == 96000000 ) { } else if( SystemCoreClock == 96'000'000 ) {
RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div2 ); RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div2 );
} else if( SystemCoreClock == 48000000 ) { } else if( SystemCoreClock == 48'000'000 ) {
RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div1 ); RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div1 );
} }
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_USBFS, ENABLE ); RCC.AHBPCENR.B.OTG_EN = SET;
} }
/********************************************************************* /*********************************************************************
* @fn USBFS_Device_Endp_Init * @fn USBFS_Device_Endp_Init
@ -103,7 +100,8 @@ void cdc_class::USBFS_Device_Init( bool sta ) {
dtr << true; 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; pInstance = this;
USBFS_DevConfig = 0; USBFS_DevConfig = 0;
USBFS_DevAddr = 0; USBFS_DevAddr = 0;
@ -116,7 +114,7 @@ void cdc_class::init() {
USBFS_Device_Init( true ); USBFS_Device_Init( true );
while (!USBFS_DevEnumStatus) delay_us(10'000); 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 ) ) { switch ( intst & ( USBFS_UIS_TOKEN_MASK | USBFS_UIS_ENDP_MASK ) ) {
/* end-point 0 data in interrupt */ /* end-point 0 data in interrupt */
case USBFS_UIS_TOKEN_IN | DEF_UEP0: case USBFS_UIS_TOKEN_IN | DEF_UEP0:
@ -164,7 +162,7 @@ __always_inline void cdc_class::InTokenHandler(const uint8_t intst) {
break; 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; uint16_t len;
switch ( intst & ( USBFS_UIS_TOKEN_MASK | USBFS_UIS_ENDP_MASK ) ) { switch ( intst & ( USBFS_UIS_TOKEN_MASK | USBFS_UIS_ENDP_MASK ) ) {
/* end-point 0 data out interrupt */ /* 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 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 parity bits (0: None; 1: Odd; 2: Even; 3: Mark; 4: Space).
1 byte: number of data bits (5,6,7,8,16); */ 1 byte: number of data bits (5,6,7,8,16); */
/* memcpy(& LineCoding, USBFS_EP0_Buf, sizeof (LineCoding));
Uart.Com_Cfg[ 0 ] = USBFS_EP0_Buf[ 0 ]; if (CtrlIface) CtrlIface->IOCtrl(USB_USART_SET_PARAM, & LineCoding, sizeof (LineCoding));
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 { } else {
/* Standard request end-point 0 Data download */ /* Standard request end-point 0 Data download */
@ -227,7 +209,12 @@ __always_inline void cdc_class::OutTokenHandler(const uint8_t intst) {
break; 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; uint8_t errflag;
uint16_t len; uint16_t len;
USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_TOG|USBFS_UEP_T_RES_NAK; USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_TOG|USBFS_UEP_T_RES_NAK;
@ -247,13 +234,16 @@ void cdc_class::SetupTokenHandler() {
switch( USBFS_SetupReqCode ) { switch( USBFS_SetupReqCode ) {
case CDC_GET_LINE_CODING: case CDC_GET_LINE_CODING:
// pUSBFS_Descr = (uint8_t *)&Uart.Com_Cfg[ 0 ]; // pUSBFS_Descr = (uint8_t *)&Uart.Com_Cfg[ 0 ];
len = 7; pUSBFS_Descr = reinterpret_cast<uint8_t*>(& LineCoding);
len = sizeof (LineCoding);
break; break;
case CDC_SET_LINE_CODING: case CDC_SET_LINE_CODING:
break; break;
/* TODO: DTR - wValue & 1 */ /* DTR - wValue & 1, RTS - wValue & 2 */
case CDC_SET_LINE_CTLSTE: { 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; const bool b = USBFS_SetupReqValue & 1;
Ready = b; Ready = b;
dtr << !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; const uint8_t intst = USBFSD->INT_ST;
switch (intst & USBFS_UIS_TOKEN_MASK) { switch (intst & USBFS_UIS_TOKEN_MASK) {
@ -544,6 +534,7 @@ void cdc_class::cdc_irq() {
USBFSD->DEV_ADDR = 0; USBFSD->DEV_ADDR = 0;
USBFS_Device_Endp_Init( ); USBFS_Device_Endp_Init( );
//UART2_ParaInit( 1 ); //UART2_ParaInit( 1 );
if (CtrlIface) CtrlIface->IOCtrl(USB_USART_INIT, nullptr, 0);
USBFSD->INT_FG = USBFS_UIF_BUS_RST; USBFSD->INT_FG = USBFS_UIF_BUS_RST;
} else if( intflag & USBFS_UIF_SUSPEND ) { } else if( intflag & USBFS_UIF_SUSPEND ) {
USBFSD->INT_FG = USBFS_UIF_SUSPEND; USBFSD->INT_FG = USBFS_UIF_SUSPEND;

View file

@ -1,46 +1,29 @@
#ifndef CDC_CLASS_H #ifndef CDC_CLASS_H
#define CDC_CLASS_H #define CDC_CLASS_H
#include "baselayer.h" #include "baselayer.h"
#include "ctrlinterface.h"
#include "gpio.h" #include "gpio.h"
#include "fifo.h" #include "fifo.h"
#include "system.h" #include "system.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include <string.h>
#include "usb_desc.h" #include "usb_desc.h"
#include "ch32v20x_usb.h" #include "ch32v20x_usb.h"
/******************************************************************************/ /******************************************************************************/
/* Global Define */ /* Global Define */
/* end-point number */ /* 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_IN 0x80
#define DEF_UEP_OUT 0x00 #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_RX_EN 0x08
#define USBFSD_UEP_TX_EN 0x04 #define USBFSD_UEP_TX_EN 0x04
#define USBFSD_UEP_BUF_MOD 0x01 #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 */ /* Setup Request Packets */
#define pUSBFS_SetupReqPak ((PUSB_SETUP_REQ)USBFS_EP0_Buf) #define pUSBFS_SetupReqPak ((PUSB_SETUP_REQ)USBFS_EP0_Buf)
#ifdef __cplusplus #ifdef __cplusplus
@ -53,9 +36,11 @@ extern "C" {
* přidáno odhadem. * přidáno odhadem.
*/ */
class cdc_class : public BaseLayer { class cdc_class : public BaseLayer {
CDC_CtrlInterface * CtrlIface;
GpioClass dtr; GpioClass dtr;
FIFO<char, 128> TxRing; FIFO<char, 128> TxRing;
bool Ready; volatile bool Ready;
USB_CDC_LineCoding LineCoding;
const uint8_t * pUSBFS_Descr; const uint8_t * pUSBFS_Descr;
/* Setup Request */ /* Setup Request */
volatile uint8_t USBFS_SetupReqCode; volatile uint8_t USBFS_SetupReqCode;
@ -69,14 +54,15 @@ class cdc_class : public BaseLayer {
volatile uint8_t USBFS_DevSleepStatus; volatile uint8_t USBFS_DevSleepStatus;
volatile uint8_t USBFS_DevEnumStatus; volatile uint8_t USBFS_DevEnumStatus;
/* Endpoint Buffer */ /* Endpoint Buffer */
__attribute__ ((aligned(4))) uint8_t USBFS_EP0_Buf[ DEF_USBD_UEP0_SIZE ]; [[gnu::aligned(4)]] uint8_t USBFS_EP0_Buf[ DEF_USBD_UEP0_SIZE ];
__attribute__ ((aligned(4))) uint8_t USBFS_EP1_Buf[ DEF_USBD_ENDP1_SIZE ]; [[gnu::aligned(4)]] uint8_t USBFS_EP1_Buf[ DEF_USBD_ENDP1_SIZE ];
__attribute__ ((aligned(4))) uint8_t USBFS_EP2_Buf[ DEF_USBD_ENDP2_SIZE ]; [[gnu::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_EP3_Buf[ DEF_USBD_ENDP3_SIZE ];
/* USB IN Endpoint Busy Flag */ /* USB IN Endpoint Busy Flag */
volatile uint8_t USBFS_Endp_Busy[ DEF_UEP_NUM ]; volatile uint8_t USBFS_Endp_Busy[ DEF_UEP_NUM ];
public: public:
explicit cdc_class () noexcept; explicit cdc_class () noexcept;
void attach (CDC_CtrlInterface & ctrl) { CtrlIface = & ctrl; }
void init (); void init ();
void cdc_irq (); void cdc_irq ();
/// Předěláno na neblokující, data se vyměňují přes FIFO, rychlejší /// 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_Init( bool sta );
void USBFS_Device_Endp_Init (); void USBFS_Device_Endp_Init ();
void TxDataDeal (); void TxDataDeal ();
void TransferHandler (); inline void TransferHandler ();
void InTokenHandler (const uint8_t intst); inline void InTokenHandler (const uint8_t intst);
void OutTokenHandler (const uint8_t intst); inline void OutTokenHandler (const uint8_t intst);
void SetupTokenHandler (); inline void SetupTokenHandler ();
}; };
#endif // CDC_CLASS_H #endif // CDC_CLASS_H

View file

@ -0,0 +1,29 @@
#ifndef CTRLINTERFACE_DEF_H
#define CTRLINTERFACE_DEF_H
#include <stdint.h>
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