Compare commits
No commits in common. "30e55b8e728fa68ef45c13776ef35b51eb99581b" and "f653fe0914d712be03adc7f1c938fad7decd3794" have entirely different histories.
30e55b8e72
...
f653fe0914
24 changed files with 5 additions and 15135 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -14,4 +14,4 @@
|
||||||
*/midi/ton/miditones
|
*/midi/ton/miditones
|
||||||
V203/pwm/sin.c
|
V203/pwm/sin.c
|
||||||
V203/gsm/lib/libgsm.a
|
V203/gsm/lib/libgsm.a
|
||||||
V203/usb/cdc/mystrings.inc
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#include "generator.h"
|
#include "generator.h"
|
||||||
#include "pwmclass.h"
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
static constexpr unsigned W_TB = 8u;
|
static constexpr unsigned W_TB = 8u;
|
||||||
static constexpr double AMPL = MAXPWM >> 1;
|
static constexpr double AMPL = 3000.0;
|
||||||
static constexpr int ULEN = 1 << W_TB;
|
static constexpr int ULEN = 1 << W_TB;
|
||||||
|
|
||||||
static constexpr uint16_t u16_sin (const int x) {
|
static constexpr uint16_t u16_sin (const int x) {
|
||||||
|
|
|
@ -22,8 +22,7 @@ static constexpr unsigned slen (const char * const str) {
|
||||||
while (str[n]) n++;
|
while (str[n]) n++;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
static const TABLE<unsigned char, array_size (morse_code)> compressed_table
|
static constexpr unsigned char compress (const unsigned n) {
|
||||||
([](const unsigned n) -> auto {
|
|
||||||
const char * const ptr = morse_code [n];
|
const char * const ptr = morse_code [n];
|
||||||
const unsigned len = slen (ptr);
|
const unsigned len = slen (ptr);
|
||||||
unsigned char mb = 0u;
|
unsigned char mb = 0u;
|
||||||
|
@ -33,7 +32,8 @@ static const TABLE<unsigned char, array_size (morse_code)> compressed_table
|
||||||
if (ptr [n] == '-') mb |= (1u << n);
|
if (ptr [n] == '-') mb |= (1u << n);
|
||||||
}
|
}
|
||||||
return mb;
|
return mb;
|
||||||
});
|
}
|
||||||
|
static const TABLE<unsigned char, array_size (morse_code)> compressed_table (compress);
|
||||||
extern void print_morse_table (const TABLE<unsigned char, array_size(morse_code)> & tab);
|
extern void print_morse_table (const TABLE<unsigned char, array_size(morse_code)> & tab);
|
||||||
|
|
||||||
Morse::Morse(const GpioClass & pin, const unsigned int ms) noexcept : unit (ms), led (pin),
|
Morse::Morse(const GpioClass & pin, const unsigned int ms) noexcept : unit (ms), led (pin),
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
TOOL ?= gcc
|
|
||||||
#TOOL ?= clang
|
|
||||||
TARGET = ch32v203
|
|
||||||
|
|
||||||
PRJ = example
|
|
||||||
VPATH += ./ch32v203
|
|
||||||
BLD = ./build/
|
|
||||||
DFLAGS = -d
|
|
||||||
LFLAGS = -g
|
|
||||||
LDLIBS =
|
|
||||||
BFLAGS = --strip-unneeded
|
|
||||||
|
|
||||||
CFLAGS = -MMD -Wall -Wno-format -Wno-parentheses -ggdb -fno-exceptions -ffunction-sections -fdata-sections
|
|
||||||
CFLAGS+= -I. -I./ch32v203
|
|
||||||
DEL = rm -f
|
|
||||||
|
|
||||||
# zdrojaky
|
|
||||||
OBJS = main.o hack.o print.o
|
|
||||||
OBJS += startup.o system.o usb_desc.o
|
|
||||||
OBJS += cdc_class.o
|
|
||||||
|
|
||||||
include $(TOOL).mk
|
|
||||||
BOBJS = $(addprefix $(BLD),$(OBJS))
|
|
||||||
|
|
||||||
all: $(BLD) $(PRJ).elf
|
|
||||||
# ... atd.
|
|
||||||
-include $(BLD)*.d
|
|
||||||
mystrings.inc: string.py
|
|
||||||
./string.py
|
|
||||||
usb_desc.c: mystrings.inc
|
|
||||||
# linker
|
|
||||||
$(PRJ).elf: $(BOBJS)
|
|
||||||
-@echo [LD $(TOOL),$(TARGET)] $@
|
|
||||||
@$(LD) $(LFLAGS) -o $(PRJ).elf $(BOBJS) $(LDLIBS)
|
|
||||||
-@echo "size:"
|
|
||||||
@$(SIZE) $(PRJ).elf
|
|
||||||
-@echo "listing:"
|
|
||||||
$(DUMP) $(DFLAGS) $(PRJ).elf > $(PRJ).lst
|
|
||||||
-@echo "OK."
|
|
||||||
$(COPY) $(BFLAGS) -O binary $(PRJ).elf $(PRJ).bin
|
|
||||||
# preloz co je potreba
|
|
||||||
$(BLD)%.o: %.S
|
|
||||||
-@echo [AS $(TOOL),$(TARGET)] $@
|
|
||||||
$(AS) -$(CCPU) $< -o $@
|
|
||||||
$(BLD)%.o: %.c
|
|
||||||
-@echo [CC $(TOOL),$(TARGET)] $@
|
|
||||||
@$(CC) -std=gnu99 -c $(CFLAGS) $< -o $@
|
|
||||||
$(BLD)%.o: %.cpp
|
|
||||||
-@echo [CX $(TOOL),$(TARGET)] $@
|
|
||||||
@$(CXX) -std=c++17 -fno-rtti -c $(CFLAGS) $< -o $@
|
|
||||||
$(BLD):
|
|
||||||
mkdir $(BLD)
|
|
||||||
flash: $(PRJ).elf
|
|
||||||
minichlink -w $(PRJ).bin flash -b
|
|
||||||
# vycisti
|
|
||||||
clean:
|
|
||||||
$(DEL) $(BLD)* *.lst *.bin *.elf *.map *~ mystrings.inc
|
|
||||||
.PHONY: all clean flash run
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,74 +0,0 @@
|
||||||
#ifndef BASELAYER_H
|
|
||||||
#define BASELAYER_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.
|
|
||||||
*
|
|
||||||
* @class BaseLayer
|
|
||||||
* @brief Od této třídy budeme dále odvozovat ostatní.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class BaseLayer {
|
|
||||||
public:
|
|
||||||
/** Konstruktor
|
|
||||||
*/
|
|
||||||
explicit constexpr BaseLayer () noexcept : pUp(nullptr), pDown(nullptr) {};
|
|
||||||
/** Virtuální metoda, přesouvající data směrem nahoru, pokud s nimi nechceme dělat něco jiného.
|
|
||||||
@param data ukazatel na pole dat
|
|
||||||
@param len delka dat v bytech
|
|
||||||
@return počet přenesených bytů
|
|
||||||
*/
|
|
||||||
virtual uint32_t Up (const char * data, const uint32_t len) {
|
|
||||||
if (pUp) return pUp->Up (data, len);
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
/** Virtuální metoda, přesouvající data směrem dolů, pokud s nimi nechceme dělat něco jiného.
|
|
||||||
@param data ukazatel na pole dat
|
|
||||||
@param len delka dat v bytech
|
|
||||||
@return počet přenesených bytů
|
|
||||||
*/
|
|
||||||
virtual uint32_t Down (const char * data, const uint32_t len) {
|
|
||||||
if (pDown) return pDown->Down (data, len);
|
|
||||||
return len;
|
|
||||||
};
|
|
||||||
/** @brief Zřetězení stacku.
|
|
||||||
* Tohle je vlastně to nejdůležitější. V čistém C by se musely
|
|
||||||
* nastavovat ukazatele na callback funkce, tady je to čitší - pro uživatele neviditelné,
|
|
||||||
* ale je to to samé.
|
|
||||||
@param bl Třída, ležící pod, spodní
|
|
||||||
@return Odkaz na tuto třídu (aby se to dalo řetězit)
|
|
||||||
*/
|
|
||||||
virtual BaseLayer & operator += (BaseLayer & bl) {
|
|
||||||
bl.setUp (this); // ta spodní bude volat při Up tuto třídu
|
|
||||||
setDown (& bl); // a tato třída bude volat při Down tu spodní
|
|
||||||
return * this;
|
|
||||||
};
|
|
||||||
/** Getter pro pDown
|
|
||||||
@return pDown
|
|
||||||
*/
|
|
||||||
BaseLayer * getDown (void) const { return pDown; };
|
|
||||||
protected:
|
|
||||||
/** Lokální setter pro pUp
|
|
||||||
@param p Co budeme do pUp dávat
|
|
||||||
*/
|
|
||||||
void setUp (BaseLayer * p) { pUp = p; };
|
|
||||||
/** Lokální setter pro pDown
|
|
||||||
@param p Co budeme do pDown dávat
|
|
||||||
*/
|
|
||||||
void setDown (BaseLayer * p) { pDown = p; };
|
|
||||||
private:
|
|
||||||
// Ono to je vlastně oboustranně vázaný spojový seznam.
|
|
||||||
BaseLayer * pUp; //!< Ukazatel na třídu, která bude dále volat Up
|
|
||||||
BaseLayer * pDown; //!< Ukazatel na třídu, která bude dále volat Down
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // BASELAYER_H
|
|
|
@ -1,670 +0,0 @@
|
||||||
#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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cdc_class::cdc_irq() {
|
|
||||||
uint8_t intflag, intst, errflag;
|
|
||||||
uint16_t len;
|
|
||||||
//uint32_t baudrate;
|
|
||||||
|
|
||||||
intflag = USBFSD->INT_FG;
|
|
||||||
intst = USBFSD->INT_ST;
|
|
||||||
|
|
||||||
if( intflag & USBFS_UIF_TRANSFER ) {
|
|
||||||
switch (intst & USBFS_UIS_TOKEN_MASK) {
|
|
||||||
/* data-in stage processing */
|
|
||||||
case USBFS_UIS_TOKEN_IN:
|
|
||||||
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:
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* data-out stage processing */
|
|
||||||
case USBFS_UIS_TOKEN_OUT:
|
|
||||||
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;
|
|
||||||
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_NAK;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Setup stage processing */
|
|
||||||
case USBFS_UIS_TOKEN_SETUP:
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default :
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
USBFSD->INT_FG = USBFS_UIF_TRANSFER;
|
|
||||||
} 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 */
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = 64;
|
|
||||||
const uint8_t * ptr = reinterpret_cast<const uint8_t*> (data);
|
|
||||||
delay_us(5'000); // zde se musí počkat, nevím proč, ale jinak to nechodí
|
|
||||||
while (rem) {
|
|
||||||
const uint32_t chunk = rem > max ? max : rem;
|
|
||||||
if (USBFS_Endp_DataUp (DEF_UEP3, ptr, chunk, DEF_UEP_CPY_LOAD)) {
|
|
||||||
delay_us(1000);
|
|
||||||
} else {
|
|
||||||
ptr += chunk;
|
|
||||||
rem -= chunk;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
#ifndef CDC_CLASS_H
|
|
||||||
#define CDC_CLASS_H
|
|
||||||
#include "baselayer.h"
|
|
||||||
#include "gpio.h"
|
|
||||||
#include "system.h"
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
#include <string.h>
|
|
||||||
#include "usb_desc.h"
|
|
||||||
#include "ch32v20x_usb.h"
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
/* Global Define */
|
|
||||||
#ifndef __PACKED
|
|
||||||
#define __PACKED __attribute__((packed))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* end-point number */
|
|
||||||
#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)
|
|
||||||
#ifdef __cplusplus
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
class cdc_class : public BaseLayer {
|
|
||||||
GpioClass dtr;
|
|
||||||
bool Ready;
|
|
||||||
const uint8_t * pUSBFS_Descr;
|
|
||||||
/* Setup Request */
|
|
||||||
volatile uint8_t USBFS_SetupReqCode;
|
|
||||||
volatile uint8_t USBFS_SetupReqType;
|
|
||||||
volatile uint16_t USBFS_SetupReqValue;
|
|
||||||
volatile uint16_t USBFS_SetupReqIndex;
|
|
||||||
volatile uint16_t USBFS_SetupReqLen;
|
|
||||||
/* USB Device Status */
|
|
||||||
volatile uint8_t USBFS_DevConfig;
|
|
||||||
volatile uint8_t USBFS_DevAddr;
|
|
||||||
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 ];
|
|
||||||
/* USB IN Endpoint Busy Flag */
|
|
||||||
volatile uint8_t USBFS_Endp_Busy[ DEF_UEP_NUM ];
|
|
||||||
public:
|
|
||||||
explicit cdc_class () noexcept;
|
|
||||||
void init ();
|
|
||||||
void cdc_irq ();
|
|
||||||
uint32_t Down(const char * data, const uint32_t len) override;
|
|
||||||
protected:
|
|
||||||
void USBFS_Device_Init( bool sta );
|
|
||||||
void USBFS_Device_Endp_Init ();
|
|
||||||
uint8_t USBFS_Endp_DataUp(uint8_t endp, const uint8_t *pbuf, uint16_t len, uint8_t mod);
|
|
||||||
void TxDataDeal ();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CDC_CLASS_H
|
|
|
@ -1,626 +0,0 @@
|
||||||
/********************************** (C) COPYRIGHT *******************************
|
|
||||||
* File Name : ch32v20x_usb.h
|
|
||||||
* Author : WCH
|
|
||||||
* Version : V1.0.0
|
|
||||||
* Date : 2024/01/30
|
|
||||||
* Description : This file contains all the functions prototypes for the USB
|
|
||||||
* firmware library.
|
|
||||||
*********************************************************************************
|
|
||||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
|
||||||
* Attention: This software (modified or not) and binary are used for
|
|
||||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
|
||||||
*******************************************************************************/
|
|
||||||
#ifndef __CH32V20X_USB_H
|
|
||||||
#define __CH32V20X_USB_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
/*******************************************************************************/
|
|
||||||
/* Header File */
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/*******************************************************************************/
|
|
||||||
/* USB Communication Related Macro Definition */
|
|
||||||
#ifndef DEFAULT_ENDP0_SIZE
|
|
||||||
#define DEFAULT_ENDP0_SIZE 8 // default maximum packet size for endpoint 0
|
|
||||||
#endif
|
|
||||||
#ifndef MAX_PACKET_SIZE
|
|
||||||
#define MAX_PACKET_SIZE 64 // maximum packet size
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* USB PID */
|
|
||||||
#ifndef USB_PID_SETUP
|
|
||||||
#define USB_PID_NULL 0x00
|
|
||||||
#define USB_PID_SOF 0x05
|
|
||||||
#define USB_PID_SETUP 0x0D
|
|
||||||
#define USB_PID_IN 0x09
|
|
||||||
#define USB_PID_OUT 0x01
|
|
||||||
#define USB_PID_NYET 0x06
|
|
||||||
#define USB_PID_ACK 0x02
|
|
||||||
#define USB_PID_NAK 0x0A
|
|
||||||
#define USB_PID_STALL 0x0E
|
|
||||||
#define USB_PID_DATA0 0x03
|
|
||||||
#define USB_PID_DATA1 0x0B
|
|
||||||
#define USB_PID_PRE 0x0C
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* USB standard device request code */
|
|
||||||
#ifndef USB_GET_DESCRIPTOR
|
|
||||||
#define USB_GET_STATUS 0x00
|
|
||||||
#define USB_CLEAR_FEATURE 0x01
|
|
||||||
#define USB_SET_FEATURE 0x03
|
|
||||||
#define USB_SET_ADDRESS 0x05
|
|
||||||
#define USB_GET_DESCRIPTOR 0x06
|
|
||||||
#define USB_SET_DESCRIPTOR 0x07
|
|
||||||
#define USB_GET_CONFIGURATION 0x08
|
|
||||||
#define USB_SET_CONFIGURATION 0x09
|
|
||||||
#define USB_GET_INTERFACE 0x0A
|
|
||||||
#define USB_SET_INTERFACE 0x0B
|
|
||||||
#define USB_SYNCH_FRAME 0x0C
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DEF_STRING_DESC_LANG 0x00
|
|
||||||
#define DEF_STRING_DESC_MANU 0x01
|
|
||||||
#define DEF_STRING_DESC_PROD 0x02
|
|
||||||
#define DEF_STRING_DESC_SERN 0x03
|
|
||||||
|
|
||||||
/* USB hub class request code */
|
|
||||||
#ifndef HUB_GET_DESCRIPTOR
|
|
||||||
#define HUB_GET_STATUS 0x00
|
|
||||||
#define HUB_CLEAR_FEATURE 0x01
|
|
||||||
#define HUB_GET_STATE 0x02
|
|
||||||
#define HUB_SET_FEATURE 0x03
|
|
||||||
#define HUB_GET_DESCRIPTOR 0x06
|
|
||||||
#define HUB_SET_DESCRIPTOR 0x07
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* USB HID class request code */
|
|
||||||
#ifndef HID_GET_REPORT
|
|
||||||
#define HID_GET_REPORT 0x01
|
|
||||||
#define HID_GET_IDLE 0x02
|
|
||||||
#define HID_GET_PROTOCOL 0x03
|
|
||||||
#define HID_SET_REPORT 0x09
|
|
||||||
#define HID_SET_IDLE 0x0A
|
|
||||||
#define HID_SET_PROTOCOL 0x0B
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Bit Define for USB Request Type */
|
|
||||||
#ifndef USB_REQ_TYP_MASK
|
|
||||||
#define USB_REQ_TYP_IN 0x80
|
|
||||||
#define USB_REQ_TYP_OUT 0x00
|
|
||||||
#define USB_REQ_TYP_READ 0x80
|
|
||||||
#define USB_REQ_TYP_WRITE 0x00
|
|
||||||
#define USB_REQ_TYP_MASK 0x60
|
|
||||||
#define USB_REQ_TYP_STANDARD 0x00
|
|
||||||
#define USB_REQ_TYP_CLASS 0x20
|
|
||||||
#define USB_REQ_TYP_VENDOR 0x40
|
|
||||||
#define USB_REQ_TYP_RESERVED 0x60
|
|
||||||
#define USB_REQ_RECIP_MASK 0x1F
|
|
||||||
#define USB_REQ_RECIP_DEVICE 0x00
|
|
||||||
#define USB_REQ_RECIP_INTERF 0x01
|
|
||||||
#define USB_REQ_RECIP_ENDP 0x02
|
|
||||||
#define USB_REQ_RECIP_OTHER 0x03
|
|
||||||
#define USB_REQ_FEAT_REMOTE_WAKEUP 0x01
|
|
||||||
#define USB_REQ_FEAT_ENDP_HALT 0x00
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* USB Descriptor Type */
|
|
||||||
#ifndef USB_DESCR_TYP_DEVICE
|
|
||||||
#define USB_DESCR_TYP_DEVICE 0x01
|
|
||||||
#define USB_DESCR_TYP_CONFIG 0x02
|
|
||||||
#define USB_DESCR_TYP_STRING 0x03
|
|
||||||
#define USB_DESCR_TYP_INTERF 0x04
|
|
||||||
#define USB_DESCR_TYP_ENDP 0x05
|
|
||||||
#define USB_DESCR_TYP_QUALIF 0x06
|
|
||||||
#define USB_DESCR_TYP_SPEED 0x07
|
|
||||||
#define USB_DESCR_TYP_OTG 0x09
|
|
||||||
#define USB_DESCR_TYP_BOS 0X0F
|
|
||||||
#define USB_DESCR_TYP_HID 0x21
|
|
||||||
#define USB_DESCR_TYP_REPORT 0x22
|
|
||||||
#define USB_DESCR_TYP_PHYSIC 0x23
|
|
||||||
#define USB_DESCR_TYP_CS_INTF 0x24
|
|
||||||
#define USB_DESCR_TYP_CS_ENDP 0x25
|
|
||||||
#define USB_DESCR_TYP_HUB 0x29
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* USB Device Class */
|
|
||||||
#ifndef USB_DEV_CLASS_HUB
|
|
||||||
#define USB_DEV_CLASS_RESERVED 0x00
|
|
||||||
#define USB_DEV_CLASS_AUDIO 0x01
|
|
||||||
#define USB_DEV_CLASS_COMMUNIC 0x02
|
|
||||||
#define USB_DEV_CLASS_HID 0x03
|
|
||||||
#define USB_DEV_CLASS_MONITOR 0x04
|
|
||||||
#define USB_DEV_CLASS_PHYSIC_IF 0x05
|
|
||||||
#define USB_DEV_CLASS_POWER 0x06
|
|
||||||
#define USB_DEV_CLASS_IMAGE 0x06
|
|
||||||
#define USB_DEV_CLASS_PRINTER 0x07
|
|
||||||
#define USB_DEV_CLASS_STORAGE 0x08
|
|
||||||
#define USB_DEV_CLASS_HUB 0x09
|
|
||||||
#define USB_DEV_CLASS_VEN_SPEC 0xFF
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* USB Hub Class Request */
|
|
||||||
#ifndef HUB_GET_HUB_DESCRIPTOR
|
|
||||||
#define HUB_CLEAR_HUB_FEATURE 0x20
|
|
||||||
#define HUB_CLEAR_PORT_FEATURE 0x23
|
|
||||||
#define HUB_GET_BUS_STATE 0xA3
|
|
||||||
#define HUB_GET_HUB_DESCRIPTOR 0xA0
|
|
||||||
#define HUB_GET_HUB_STATUS 0xA0
|
|
||||||
#define HUB_GET_PORT_STATUS 0xA3
|
|
||||||
#define HUB_SET_HUB_DESCRIPTOR 0x20
|
|
||||||
#define HUB_SET_HUB_FEATURE 0x20
|
|
||||||
#define HUB_SET_PORT_FEATURE 0x23
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Hub Class Feature Selectors */
|
|
||||||
#ifndef HUB_PORT_RESET
|
|
||||||
#define HUB_C_HUB_LOCAL_POWER 0
|
|
||||||
#define HUB_C_HUB_OVER_CURRENT 1
|
|
||||||
#define HUB_PORT_CONNECTION 0
|
|
||||||
#define HUB_PORT_ENABLE 1
|
|
||||||
#define HUB_PORT_SUSPEND 2
|
|
||||||
#define HUB_PORT_OVER_CURRENT 3
|
|
||||||
#define HUB_PORT_RESET 4
|
|
||||||
#define HUB_PORT_POWER 8
|
|
||||||
#define HUB_PORT_LOW_SPEED 9
|
|
||||||
#define HUB_C_PORT_CONNECTION 16
|
|
||||||
#define HUB_C_PORT_ENABLE 17
|
|
||||||
#define HUB_C_PORT_SUSPEND 18
|
|
||||||
#define HUB_C_PORT_OVER_CURRENT 19
|
|
||||||
#define HUB_C_PORT_RESET 20
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* USB HID Class Request Code */
|
|
||||||
#ifndef HID_GET_REPORT
|
|
||||||
#define HID_GET_REPORT 0x01
|
|
||||||
#define HID_GET_IDLE 0x02
|
|
||||||
#define HID_GET_PROTOCOL 0x03
|
|
||||||
#define HID_SET_REPORT 0x09
|
|
||||||
#define HID_SET_IDLE 0x0A
|
|
||||||
#define HID_SET_PROTOCOL 0x0B
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* USB CDC Class request code */
|
|
||||||
#ifndef CDC_GET_LINE_CODING
|
|
||||||
#define CDC_GET_LINE_CODING 0X21 /* This request allows the host to find out the currently configured line coding */
|
|
||||||
#define CDC_SET_LINE_CODING 0x20 /* Configures DTE rate, stop-bits, parity, and number-of-character */
|
|
||||||
#define CDC_SET_LINE_CTLSTE 0X22 /* This request generates RS-232/V.24 style control signals */
|
|
||||||
#define CDC_SEND_BREAK 0X23 /* Sends special carrier modulation used to specify RS-232 style break */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* USB UDisk */
|
|
||||||
#ifndef USB_BO_CBW_SIZE
|
|
||||||
#define USB_BO_CBW_SIZE 0x1F
|
|
||||||
#define USB_BO_CSW_SIZE 0x0D
|
|
||||||
#endif
|
|
||||||
#ifndef USB_BO_CBW_SIG0
|
|
||||||
#define USB_BO_CBW_SIG0 0x55
|
|
||||||
#define USB_BO_CBW_SIG1 0x53
|
|
||||||
#define USB_BO_CBW_SIG2 0x42
|
|
||||||
#define USB_BO_CBW_SIG3 0x43
|
|
||||||
#define USB_BO_CSW_SIG0 0x55
|
|
||||||
#define USB_BO_CSW_SIG1 0x53
|
|
||||||
#define USB_BO_CSW_SIG2 0x42
|
|
||||||
#define USB_BO_CSW_SIG3 0x53
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************/
|
|
||||||
/* USBFS Related Register Macro Definition */
|
|
||||||
|
|
||||||
/* R8_USB_CTRL */
|
|
||||||
#define USBFS_UC_HOST_MODE 0x80
|
|
||||||
#define USBFS_UC_LOW_SPEED 0x40
|
|
||||||
#define USBFS_UC_DEV_PU_EN 0x20
|
|
||||||
#define USBFS_UC_SYS_CTRL_MASK 0x30
|
|
||||||
#define USBFS_UC_SYS_CTRL0 0x00
|
|
||||||
#define USBFS_UC_SYS_CTRL1 0x10
|
|
||||||
#define USBFS_UC_SYS_CTRL2 0x20
|
|
||||||
#define USBFS_UC_SYS_CTRL3 0x30
|
|
||||||
#define USBFS_UC_INT_BUSY 0x08
|
|
||||||
#define USBFS_UC_RESET_SIE 0x04
|
|
||||||
#define USBFS_UC_CLR_ALL 0x02
|
|
||||||
#define USBFS_UC_DMA_EN 0x01
|
|
||||||
|
|
||||||
/* R8_USB_INT_EN */
|
|
||||||
#define USBFS_UIE_DEV_NAK 0x40
|
|
||||||
#define USBFS_UIE_FIFO_OV 0x10
|
|
||||||
#define USBFS_UIE_HST_SOF 0x08
|
|
||||||
#define USBFS_UIE_SUSPEND 0x04
|
|
||||||
#define USBFS_UIE_TRANSFER 0x02
|
|
||||||
#define USBFS_UIE_DETECT 0x01
|
|
||||||
#define USBFS_UIE_BUS_RST 0x01
|
|
||||||
|
|
||||||
/* R8_USB_DEV_AD */
|
|
||||||
#define USBFS_UDA_GP_BIT 0x80
|
|
||||||
#define USBFS_USB_ADDR_MASK 0x7F
|
|
||||||
|
|
||||||
/* R8_USB_MIS_ST */
|
|
||||||
#define USBFS_UMS_SOF_PRES 0x80
|
|
||||||
#define USBFS_UMS_SOF_ACT 0x40
|
|
||||||
#define USBFS_UMS_SIE_FREE 0x20
|
|
||||||
#define USBFS_UMS_R_FIFO_RDY 0x10
|
|
||||||
#define USBFS_UMS_BUS_RESET 0x08
|
|
||||||
#define USBFS_UMS_SUSPEND 0x04
|
|
||||||
#define USBFS_UMS_DM_LEVEL 0x02
|
|
||||||
#define USBFS_UMS_DEV_ATTACH 0x01
|
|
||||||
|
|
||||||
/* R8_USB_INT_FG */
|
|
||||||
#define USBFS_U_IS_NAK 0x80 // RO, indicate current USB transfer is NAK received
|
|
||||||
#define USBFS_U_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK
|
|
||||||
#define USBFS_U_SIE_FREE 0x20 // RO, indicate USB SIE free status
|
|
||||||
#define USBFS_UIF_FIFO_OV 0x10 // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear
|
|
||||||
#define USBFS_UIF_HST_SOF 0x08 // host SOF timer interrupt flag for USB host, direct bit address clear or write 1 to clear
|
|
||||||
#define USBFS_UIF_SUSPEND 0x04 // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear
|
|
||||||
#define USBFS_UIF_TRANSFER 0x02 // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear
|
|
||||||
#define USBFS_UIF_DETECT 0x01 // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear
|
|
||||||
#define USBFS_UIF_BUS_RST 0x01 // bus reset event interrupt flag for USB device mode, direct bit address clear or write 1 to clear
|
|
||||||
|
|
||||||
/* R8_USB_INT_ST */
|
|
||||||
#define USBFS_UIS_IS_NAK 0x80 // RO, indicate current USB transfer is NAK received for USB device mode
|
|
||||||
#define USBFS_UIS_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK
|
|
||||||
#define USBFS_UIS_TOKEN_MASK 0x30 // RO, bit mask of current token PID code received for USB device mode
|
|
||||||
#define USBFS_UIS_TOKEN_OUT 0x00
|
|
||||||
#define USBFS_UIS_TOKEN_IN 0x20
|
|
||||||
#define USBFS_UIS_TOKEN_SETUP 0x30
|
|
||||||
// bUIS_TOKEN1 & bUIS_TOKEN0: current token PID code received for USB device mode
|
|
||||||
// 00: OUT token PID received
|
|
||||||
// 10: IN token PID received
|
|
||||||
// 11: SETUP token PID received
|
|
||||||
#define USBFS_UIS_ENDP_MASK 0x0F // RO, bit mask of current transfer endpoint number for USB device mode
|
|
||||||
#define USBFS_UIS_H_RES_MASK 0x0F // RO, bit mask of current transfer handshake response for USB host mode: 0000=no response, time out from device, others=handshake response PID received
|
|
||||||
|
|
||||||
/* R32_USB_OTG_CR */
|
|
||||||
#define USBFS_CR_SESS_VTH 0x20
|
|
||||||
#define USBFS_CR_VBUS_VTH 0x10
|
|
||||||
#define USBFS_CR_OTG_EN 0x08
|
|
||||||
#define USBFS_CR_IDPU 0x04
|
|
||||||
#define USBFS_CR_CHARGE_VBUS 0x02
|
|
||||||
#define USBFS_CR_DISCHAR_VBUS 0x01
|
|
||||||
|
|
||||||
/* R32_USB_OTG_SR */
|
|
||||||
#define USBFS_SR_ID_DIG 0x08
|
|
||||||
#define USBFS_SR_SESS_END 0x04
|
|
||||||
#define USBFS_SR_SESS_VLD 0x02
|
|
||||||
#define USBFS_SR_VBUS_VLD 0x01
|
|
||||||
|
|
||||||
/* R8_UDEV_CTRL */
|
|
||||||
#define USBFS_UD_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
|
|
||||||
#define USBFS_UD_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level
|
|
||||||
#define USBFS_UD_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level
|
|
||||||
#define USBFS_UD_LOW_SPEED 0x04 // enable USB physical port low speed: 0=full speed, 1=low speed
|
|
||||||
#define USBFS_UD_GP_BIT 0x02 // general purpose bit
|
|
||||||
#define USBFS_UD_PORT_EN 0x01 // enable USB physical port I/O: 0=disable, 1=enable
|
|
||||||
|
|
||||||
/* R8_UEP4_1_MOD */
|
|
||||||
#define USBFS_UEP1_RX_EN 0x80 // enable USB endpoint 1 receiving (OUT)
|
|
||||||
#define USBFS_UEP1_TX_EN 0x40 // enable USB endpoint 1 transmittal (IN)
|
|
||||||
#define USBFS_UEP1_BUF_MOD 0x10 // buffer mode of USB endpoint 1
|
|
||||||
#define USBFS_UEP4_RX_EN 0x08 // enable USB endpoint 4 receiving (OUT)
|
|
||||||
#define USBFS_UEP4_TX_EN 0x04 // enable USB endpoint 4 transmittal (IN)
|
|
||||||
#define USBFS_UEP4_BUF_MOD 0x01
|
|
||||||
|
|
||||||
/* R8_UEP2_3_MOD */
|
|
||||||
#define USBFS_UEP3_RX_EN 0x80 // enable USB endpoint 3 receiving (OUT)
|
|
||||||
#define USBFS_UEP3_TX_EN 0x40 // enable USB endpoint 3 transmittal (IN)
|
|
||||||
#define USBFS_UEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3
|
|
||||||
#define USBFS_UEP2_RX_EN 0x08 // enable USB endpoint 2 receiving (OUT)
|
|
||||||
#define USBFS_UEP2_TX_EN 0x04 // enable USB endpoint 2 transmittal (IN)
|
|
||||||
#define USBFS_UEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2
|
|
||||||
|
|
||||||
/* R8_UEP5_6_MOD */
|
|
||||||
#define USBFS_UEP6_RX_EN 0x80 // enable USB endpoint 6 receiving (OUT)
|
|
||||||
#define USBFS_UEP6_TX_EN 0x40 // enable USB endpoint 6 transmittal (IN)
|
|
||||||
#define USBFS_UEP6_BUF_MOD 0x10 // buffer mode of USB endpoint 6
|
|
||||||
#define USBFS_UEP5_RX_EN 0x08 // enable USB endpoint 5 receiving (OUT)
|
|
||||||
#define USBFS_UEP5_TX_EN 0x04 // enable USB endpoint 5 transmittal (IN)
|
|
||||||
#define USBFS_UEP5_BUF_MOD 0x01 // buffer mode of USB endpoint 5
|
|
||||||
|
|
||||||
/* R8_UEP7_MOD */
|
|
||||||
#define USBFS_UEP7_RX_EN 0x08 // enable USB endpoint 7 receiving (OUT)
|
|
||||||
#define USBFS_UEP7_TX_EN 0x04 // enable USB endpoint 7 transmittal (IN)
|
|
||||||
#define USBFS_UEP7_BUF_MOD 0x01 // buffer mode of USB endpoint 7
|
|
||||||
|
|
||||||
/* R8_UEPn_TX_CTRL */
|
|
||||||
#define USBFS_UEP_T_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle
|
|
||||||
#define USBFS_UEP_T_TOG 0x04 // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1
|
|
||||||
#define USBFS_UEP_T_RES_MASK 0x03 // bit mask of handshake response type for USB endpoint X transmittal (IN)
|
|
||||||
#define USBFS_UEP_T_RES_ACK 0x00
|
|
||||||
#define USBFS_UEP_T_RES_NONE 0x01
|
|
||||||
#define USBFS_UEP_T_RES_NAK 0x02
|
|
||||||
#define USBFS_UEP_T_RES_STALL 0x03
|
|
||||||
// bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmittal (IN)
|
|
||||||
// 00: DATA0 or DATA1 then expecting ACK (ready)
|
|
||||||
// 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions
|
|
||||||
// 10: NAK (busy)
|
|
||||||
// 11: STALL (error)
|
|
||||||
// host aux setup
|
|
||||||
|
|
||||||
/* R8_UEPn_RX_CTRL, n=0-7 */
|
|
||||||
#define USBFS_UEP_R_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle
|
|
||||||
#define USBFS_UEP_R_TOG 0x04 // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1
|
|
||||||
#define USBFS_UEP_R_RES_MASK 0x03 // bit mask of handshake response type for USB endpoint X receiving (OUT)
|
|
||||||
#define USBFS_UEP_R_RES_ACK 0x00
|
|
||||||
#define USBFS_UEP_R_RES_NONE 0x01
|
|
||||||
#define USBFS_UEP_R_RES_NAK 0x02
|
|
||||||
#define USBFS_UEP_R_RES_STALL 0x03
|
|
||||||
// RB_UEP_R_RES1 & RB_UEP_R_RES0: handshake response type for USB endpoint X receiving (OUT)
|
|
||||||
// 00: ACK (ready)
|
|
||||||
// 01: no response, time out to host, for non-zero endpoint isochronous transactions
|
|
||||||
// 10: NAK (busy)
|
|
||||||
// 11: STALL (error)
|
|
||||||
|
|
||||||
/* R8_UHOST_CTRL */
|
|
||||||
#define USBFS_UH_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
|
|
||||||
#define USBFS_UH_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level
|
|
||||||
#define USBFS_UH_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level
|
|
||||||
#define USBFS_UH_LOW_SPEED 0x04 // enable USB port low speed: 0=full speed, 1=low speed
|
|
||||||
#define USBFS_UH_BUS_RESET 0x02 // control USB bus reset: 0=normal, 1=force bus reset
|
|
||||||
#define USBFS_UH_PORT_EN 0x01 // enable USB port: 0=disable, 1=enable port, automatic disabled if USB device detached
|
|
||||||
|
|
||||||
/* R32_UH_EP_MOD */
|
|
||||||
#define USBFS_UH_EP_TX_EN 0x40 // enable USB host OUT endpoint transmittal
|
|
||||||
#define USBFS_UH_EP_TBUF_MOD 0x10 // buffer mode of USB host OUT endpoint
|
|
||||||
// bUH_EP_TX_EN & bUH_EP_TBUF_MOD: USB host OUT endpoint buffer mode, buffer start address is UH_TX_DMA
|
|
||||||
// 0 x: disable endpoint and disable buffer
|
|
||||||
// 1 0: 64 bytes buffer for transmittal (OUT endpoint)
|
|
||||||
// 1 1: dual 64 bytes buffer by toggle bit bUH_T_TOG selection for transmittal (OUT endpoint), total=128bytes
|
|
||||||
#define USBFS_UH_EP_RX_EN 0x08 // enable USB host IN endpoint receiving
|
|
||||||
#define USBFS_UH_EP_RBUF_MOD 0x01 // buffer mode of USB host IN endpoint
|
|
||||||
// bUH_EP_RX_EN & bUH_EP_RBUF_MOD: USB host IN endpoint buffer mode, buffer start address is UH_RX_DMA
|
|
||||||
// 0 x: disable endpoint and disable buffer
|
|
||||||
// 1 0: 64 bytes buffer for receiving (IN endpoint)
|
|
||||||
// 1 1: dual 64 bytes buffer by toggle bit bUH_R_TOG selection for receiving (IN endpoint), total=128bytes
|
|
||||||
|
|
||||||
/* R16_UH_SETUP */
|
|
||||||
#define USBFS_UH_PRE_PID_EN 0x0400 // USB host PRE PID enable for low speed device via hub
|
|
||||||
#define USBFS_UH_SOF_EN 0x0004 // USB host automatic SOF enable
|
|
||||||
|
|
||||||
/* R8_UH_EP_PID */
|
|
||||||
#define USBFS_UH_TOKEN_MASK 0xF0 // bit mask of token PID for USB host transfer
|
|
||||||
#define USBFS_UH_ENDP_MASK 0x0F // bit mask of endpoint number for USB host transfer
|
|
||||||
|
|
||||||
/* R8_UH_RX_CTRL */
|
|
||||||
#define USBFS_UH_R_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
|
|
||||||
#define USBFS_UH_R_TOG 0x04 // expected data toggle flag of host receiving (IN): 0=DATA0, 1=DATA1
|
|
||||||
#define USBFS_UH_R_RES 0x01 // prepared handshake response type for host receiving (IN): 0=ACK (ready), 1=no response, time out to device, for isochronous transactions
|
|
||||||
|
|
||||||
/* R8_UH_TX_CTRL */
|
|
||||||
#define USBFS_UH_T_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
|
|
||||||
#define USBFS_UH_T_TOG 0x04 // prepared data toggle flag of host transmittal (SETUP/OUT): 0=DATA0, 1=DATA1
|
|
||||||
#define USBFS_UH_T_RES 0x01 // expected handshake response type for host transmittal (SETUP/OUT): 0=ACK (ready), 1=no response, time out from device, for isochronous transactions
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************/
|
|
||||||
/* Struct Definition */
|
|
||||||
|
|
||||||
/* USB Setup Request */
|
|
||||||
typedef struct __attribute__((packed)) _USB_SETUP_REQ
|
|
||||||
{
|
|
||||||
uint8_t bRequestType;
|
|
||||||
uint8_t bRequest;
|
|
||||||
uint16_t wValue;
|
|
||||||
uint16_t wIndex;
|
|
||||||
uint16_t wLength;
|
|
||||||
} USB_SETUP_REQ, *PUSB_SETUP_REQ;
|
|
||||||
|
|
||||||
/* USB Device Descriptor */
|
|
||||||
typedef struct __attribute__((packed)) _USB_DEVICE_DESCR
|
|
||||||
{
|
|
||||||
uint8_t bLength;
|
|
||||||
uint8_t bDescriptorType;
|
|
||||||
uint16_t bcdUSB;
|
|
||||||
uint8_t bDeviceClass;
|
|
||||||
uint8_t bDeviceSubClass;
|
|
||||||
uint8_t bDeviceProtocol;
|
|
||||||
uint8_t bMaxPacketSize0;
|
|
||||||
uint16_t idVendor;
|
|
||||||
uint16_t idProduct;
|
|
||||||
uint16_t bcdDevice;
|
|
||||||
uint8_t iManufacturer;
|
|
||||||
uint8_t iProduct;
|
|
||||||
uint8_t iSerialNumber;
|
|
||||||
uint8_t bNumConfigurations;
|
|
||||||
} USB_DEV_DESCR, *PUSB_DEV_DESCR;
|
|
||||||
|
|
||||||
/* USB Configuration Descriptor */
|
|
||||||
typedef struct __attribute__((packed)) _USB_CONFIG_DESCR
|
|
||||||
{
|
|
||||||
uint8_t bLength;
|
|
||||||
uint8_t bDescriptorType;
|
|
||||||
uint16_t wTotalLength;
|
|
||||||
uint8_t bNumInterfaces;
|
|
||||||
uint8_t bConfigurationValue;
|
|
||||||
uint8_t iConfiguration;
|
|
||||||
uint8_t bmAttributes;
|
|
||||||
uint8_t MaxPower;
|
|
||||||
} USB_CFG_DESCR, *PUSB_CFG_DESCR;
|
|
||||||
|
|
||||||
/* USB Interface Descriptor */
|
|
||||||
typedef struct __attribute__((packed)) _USB_INTERF_DESCR
|
|
||||||
{
|
|
||||||
uint8_t bLength;
|
|
||||||
uint8_t bDescriptorType;
|
|
||||||
uint8_t bInterfaceNumber;
|
|
||||||
uint8_t bAlternateSetting;
|
|
||||||
uint8_t bNumEndpoints;
|
|
||||||
uint8_t bInterfaceClass;
|
|
||||||
uint8_t bInterfaceSubClass;
|
|
||||||
uint8_t bInterfaceProtocol;
|
|
||||||
uint8_t iInterface;
|
|
||||||
} USB_ITF_DESCR, *PUSB_ITF_DESCR;
|
|
||||||
|
|
||||||
/* USB Endpoint Descriptor */
|
|
||||||
typedef struct __attribute__((packed)) _USB_ENDPOINT_DESCR
|
|
||||||
{
|
|
||||||
uint8_t bLength;
|
|
||||||
uint8_t bDescriptorType;
|
|
||||||
uint8_t bEndpointAddress;
|
|
||||||
uint8_t bmAttributes;
|
|
||||||
uint8_t wMaxPacketSizeL;
|
|
||||||
uint8_t wMaxPacketSizeH;
|
|
||||||
uint8_t bInterval;
|
|
||||||
} USB_ENDP_DESCR, *PUSB_ENDP_DESCR;
|
|
||||||
|
|
||||||
/* USB Configuration Descriptor Set */
|
|
||||||
typedef struct __attribute__((packed)) _USB_CONFIG_DESCR_LONG
|
|
||||||
{
|
|
||||||
USB_CFG_DESCR cfg_descr;
|
|
||||||
USB_ITF_DESCR itf_descr;
|
|
||||||
USB_ENDP_DESCR endp_descr[ 1 ];
|
|
||||||
} USB_CFG_DESCR_LONG, *PUSB_CFG_DESCR_LONG;
|
|
||||||
|
|
||||||
/* USB HUB Descriptor */
|
|
||||||
typedef struct __attribute__((packed)) _USB_HUB_DESCR
|
|
||||||
{
|
|
||||||
uint8_t bDescLength;
|
|
||||||
uint8_t bDescriptorType;
|
|
||||||
uint8_t bNbrPorts;
|
|
||||||
uint8_t wHubCharacteristicsL;
|
|
||||||
uint8_t wHubCharacteristicsH;
|
|
||||||
uint8_t bPwrOn2PwrGood;
|
|
||||||
uint8_t bHubContrCurrent;
|
|
||||||
uint8_t DeviceRemovable;
|
|
||||||
uint8_t PortPwrCtrlMask;
|
|
||||||
} USB_HUB_DESCR, *PUSB_HUB_DESCR;
|
|
||||||
|
|
||||||
/* USB HID Descriptor */
|
|
||||||
typedef struct __attribute__((packed)) _USB_HID_DESCR
|
|
||||||
{
|
|
||||||
uint8_t bLength;
|
|
||||||
uint8_t bDescriptorType;
|
|
||||||
uint16_t bcdHID;
|
|
||||||
uint8_t bCountryCode;
|
|
||||||
uint8_t bNumDescriptors;
|
|
||||||
uint8_t bDescriptorTypeX;
|
|
||||||
uint8_t wDescriptorLengthL;
|
|
||||||
uint8_t wDescriptorLengthH;
|
|
||||||
} USB_HID_DESCR, *PUSB_HID_DESCR;
|
|
||||||
|
|
||||||
/* USB UDisk */
|
|
||||||
typedef struct __attribute__((packed)) _UDISK_BOC_CBW
|
|
||||||
{
|
|
||||||
uint32_t mCBW_Sig;
|
|
||||||
uint32_t mCBW_Tag;
|
|
||||||
uint32_t mCBW_DataLen;
|
|
||||||
uint8_t mCBW_Flag;
|
|
||||||
uint8_t mCBW_LUN;
|
|
||||||
uint8_t mCBW_CB_Len;
|
|
||||||
uint8_t mCBW_CB_Buf[ 16 ];
|
|
||||||
} UDISK_BOC_CBW, *PXUDISK_BOC_CBW;
|
|
||||||
|
|
||||||
/* USB UDisk */
|
|
||||||
typedef struct __attribute__((packed)) _UDISK_BOC_CSW
|
|
||||||
{
|
|
||||||
uint32_t mCBW_Sig;
|
|
||||||
uint32_t mCBW_Tag;
|
|
||||||
uint32_t mCSW_Residue;
|
|
||||||
uint8_t mCSW_Status;
|
|
||||||
} UDISK_BOC_CSW, *PXUDISK_BOC_CSW;
|
|
||||||
/* Peripheral USB OTG FS */
|
|
||||||
#define __IO volatile
|
|
||||||
/* USBFS Registers */
|
|
||||||
typedef struct {
|
|
||||||
__IO uint8_t BASE_CTRL;
|
|
||||||
__IO uint8_t UDEV_CTRL;
|
|
||||||
__IO uint8_t INT_EN;
|
|
||||||
__IO uint8_t DEV_ADDR;
|
|
||||||
__IO uint8_t Reserve0;
|
|
||||||
__IO uint8_t MIS_ST;
|
|
||||||
__IO uint8_t INT_FG;
|
|
||||||
__IO uint8_t INT_ST;
|
|
||||||
__IO uint32_t RX_LEN;
|
|
||||||
__IO uint8_t UEP4_1_MOD;
|
|
||||||
__IO uint8_t UEP2_3_MOD;
|
|
||||||
__IO uint8_t UEP5_6_MOD;
|
|
||||||
__IO uint8_t UEP7_MOD;
|
|
||||||
__IO uint32_t UEP0_DMA;
|
|
||||||
__IO uint32_t UEP1_DMA;
|
|
||||||
__IO uint32_t UEP2_DMA;
|
|
||||||
__IO uint32_t UEP3_DMA;
|
|
||||||
__IO uint32_t UEP4_DMA;
|
|
||||||
__IO uint32_t UEP5_DMA;
|
|
||||||
__IO uint32_t UEP6_DMA;
|
|
||||||
__IO uint32_t UEP7_DMA;
|
|
||||||
__IO uint16_t UEP0_TX_LEN;
|
|
||||||
__IO uint8_t UEP0_TX_CTRL;
|
|
||||||
__IO uint8_t UEP0_RX_CTRL;
|
|
||||||
__IO uint16_t UEP1_TX_LEN;
|
|
||||||
__IO uint8_t UEP1_TX_CTRL;
|
|
||||||
__IO uint8_t UEP1_RX_CTRL;
|
|
||||||
__IO uint16_t UEP2_TX_LEN;
|
|
||||||
__IO uint8_t UEP2_TX_CTRL;
|
|
||||||
__IO uint8_t UEP2_RX_CTRL;
|
|
||||||
__IO uint16_t UEP3_TX_LEN;
|
|
||||||
__IO uint8_t UEP3_TX_CTRL;
|
|
||||||
__IO uint8_t UEP3_RX_CTRL;
|
|
||||||
__IO uint16_t UEP4_TX_LEN;
|
|
||||||
__IO uint8_t UEP4_TX_CTRL;
|
|
||||||
__IO uint8_t UEP4_RX_CTRL;
|
|
||||||
__IO uint16_t UEP5_TX_LEN;
|
|
||||||
__IO uint8_t UEP5_TX_CTRL;
|
|
||||||
__IO uint8_t UEP5_RX_CTRL;
|
|
||||||
__IO uint16_t UEP6_TX_LEN;
|
|
||||||
__IO uint8_t UEP6_TX_CTRL;
|
|
||||||
__IO uint8_t UEP6_RX_CTRL;
|
|
||||||
__IO uint16_t UEP7_TX_LEN;
|
|
||||||
__IO uint8_t UEP7_TX_CTRL;
|
|
||||||
__IO uint8_t UEP7_RX_CTRL;
|
|
||||||
__IO uint32_t Reserve1;
|
|
||||||
__IO uint32_t OTG_CR;
|
|
||||||
__IO uint32_t OTG_SR;
|
|
||||||
} USBFSD_TypeDef;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
__IO uint8_t BASE_CTRL;
|
|
||||||
__IO uint8_t HOST_CTRL;
|
|
||||||
__IO uint8_t INT_EN;
|
|
||||||
__IO uint8_t DEV_ADDR;
|
|
||||||
__IO uint8_t Reserve0;
|
|
||||||
__IO uint8_t MIS_ST;
|
|
||||||
__IO uint8_t INT_FG;
|
|
||||||
__IO uint8_t INT_ST;
|
|
||||||
__IO uint16_t RX_LEN;
|
|
||||||
__IO uint16_t Reserve1;
|
|
||||||
__IO uint8_t Reserve2;
|
|
||||||
__IO uint8_t HOST_EP_MOD;
|
|
||||||
__IO uint16_t Reserve3;
|
|
||||||
__IO uint32_t Reserve4;
|
|
||||||
__IO uint32_t Reserve5;
|
|
||||||
__IO uint32_t HOST_RX_DMA;
|
|
||||||
__IO uint32_t HOST_TX_DMA;
|
|
||||||
__IO uint32_t Reserve6;
|
|
||||||
__IO uint32_t Reserve7;
|
|
||||||
__IO uint32_t Reserve8;
|
|
||||||
__IO uint32_t Reserve9;
|
|
||||||
__IO uint32_t Reserve10;
|
|
||||||
__IO uint16_t Reserve11;
|
|
||||||
__IO uint16_t HOST_SETUP;
|
|
||||||
__IO uint8_t HOST_EP_PID;
|
|
||||||
__IO uint8_t Reserve12;
|
|
||||||
__IO uint8_t Reserve13;
|
|
||||||
__IO uint8_t HOST_RX_CTRL;
|
|
||||||
__IO uint16_t HOST_TX_LEN;
|
|
||||||
__IO uint8_t HOST_TX_CTRL;
|
|
||||||
__IO uint8_t Reserve14;
|
|
||||||
__IO uint32_t Reserve15;
|
|
||||||
__IO uint32_t Reserve16;
|
|
||||||
__IO uint32_t Reserve17;
|
|
||||||
__IO uint32_t Reserve18;
|
|
||||||
__IO uint32_t Reserve19;
|
|
||||||
__IO uint32_t OTG_CR;
|
|
||||||
__IO uint32_t OTG_SR;
|
|
||||||
} USBFSH_TypeDef;
|
|
||||||
|
|
||||||
|
|
||||||
#define USBFS_BASE ((uint32_t)0x50000000)
|
|
||||||
#define USBFSD ((USBFSD_TypeDef *)USBFS_BASE)
|
|
||||||
#define USBFSH ((USBFSH_TypeDef *)USBFS_BASE)
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /*_CH32V20X_USB_H */
|
|
|
@ -1,73 +0,0 @@
|
||||||
#ifndef FIFO_H
|
|
||||||
#define FIFO_H
|
|
||||||
/** Typ dbus_w_t je podobně definován jako sig_atomic_t v hlavičce signal.h.
|
|
||||||
* Je to prostě největší typ, ke kterému je "atomický" přístup. V GCC je definováno
|
|
||||||
* __SIG_ATOMIC_TYPE__, šlo by použít, ale je znaménkový.
|
|
||||||
* */
|
|
||||||
#ifdef __SIG_ATOMIC_TYPE__
|
|
||||||
typedef unsigned __SIG_ATOMIC_TYPE__ dbus_w_t;
|
|
||||||
#else
|
|
||||||
typedef unsigned int dbus_w_t; // pro AVR by to měl být uint8_t (šířka datové sběrnice)
|
|
||||||
#endif //__SIG_ATOMIC_TYPE__
|
|
||||||
/// Tahle podivná rekurzívní formule je použita pro validaci délky bufferu.
|
|
||||||
static constexpr bool isValidM (const int N, const dbus_w_t M) {
|
|
||||||
// constexpr má raději rekurzi než cyklus (c++11)
|
|
||||||
return (N > 12) ? false : (((1u << N) == M) ? true : isValidM (N+1, M));
|
|
||||||
}
|
|
||||||
/** @class FIFO
|
|
||||||
* @brief Jednoduchá fronta (kruhový buffer).
|
|
||||||
*
|
|
||||||
* V tomto přikladu je vidět, že synchronizace mezi přerušením a hlavní smyčkou programu
|
|
||||||
* může být tak jednoduchá, že je v podstatě neviditelná. Využívá se toho, že pokud
|
|
||||||
* do kruhového buferu zapisujeme jen z jednoho bodu a čteme také jen z jednoho bodu
|
|
||||||
* (vlákna), zápis probíhá nezávisle pomocí indexu m_head a čtení pomocí m_tail.
|
|
||||||
* Délka dat je dána rozdílem tt. indexů, pokud v průběhu výpočtu délky dojde k přerušení,
|
|
||||||
* v zásadě se nic špatného neděje, maximálně je délka určena špatně a to tak,
|
|
||||||
* že zápis nebo čtení je nutné opakovat. Důležité je, že po výpočtu se nová délka zapíše
|
|
||||||
* do paměti "atomicky". Takže např. pro 8-bit procesor musí být indexy jen 8-bitové.
|
|
||||||
* To není moc velké omezení, protože tyto procesory obvykle mají dost malou RAM, takže
|
|
||||||
* velikost bufferu stejně nebývá být větší než nějakých 64 položek.
|
|
||||||
* Opět nijak nevadí že přijde přerušení při zápisu nebo čtení položky - to se provádí
|
|
||||||
* dříve než změna indexu, zápis a čtení je vždy na jiném místě RAM. Celé je to uděláno
|
|
||||||
* jako šablona, takže je možné řadit do fronty i složitější věci než je pouhý byte.
|
|
||||||
* Druhým parametrem šablony je délka bufferu (aby to šlo konstruovat jako statický objekt),
|
|
||||||
* musí to být mocnina dvou v rozsahu 8 až 4096, default je 64. Mocnina 2 je zvolena proto,
|
|
||||||
* aby se místo zbytku po dělení mohl použít jen bitový and, což je rychlejší.
|
|
||||||
* */
|
|
||||||
template<typename T, const dbus_w_t M = 64> class FIFO {
|
|
||||||
T m_data [M];
|
|
||||||
volatile dbus_w_t m_head; //!< index pro zápis (hlava)
|
|
||||||
volatile dbus_w_t m_tail; //!< index pro čtení (ocas)
|
|
||||||
/// vrací skutečnou délku dostupných dat
|
|
||||||
constexpr dbus_w_t lenght () const { return (M + m_head - m_tail) & (M - 1); };
|
|
||||||
/// zvětší a saturuje index, takže se tento motá v kruhu @param n index
|
|
||||||
void sat_inc (volatile dbus_w_t & n) const { n = (n + 1) & (M - 1); };
|
|
||||||
public:
|
|
||||||
/// Konstruktor
|
|
||||||
explicit constexpr FIFO<T,M> () noexcept {
|
|
||||||
// pro 8-bit architekturu může být byte jako index poměrně malý
|
|
||||||
static_assert (1ul << (8 * sizeof(dbus_w_t) - 1) >= M, "atomic type too small");
|
|
||||||
// a omezíme pro jistotu i delku buferu na nějakou rozumnou delku
|
|
||||||
static_assert (isValidM (3, M), "M must be power of two in range <8,4096> or <8,128> for 8-bit data bus (AVR)");
|
|
||||||
m_head = 0;
|
|
||||||
m_tail = 0;
|
|
||||||
}
|
|
||||||
/// Čtení položky
|
|
||||||
/// @return true, pokud se úspěšně provede
|
|
||||||
const bool Read (T & c) {
|
|
||||||
if (lenght() == 0) return false;
|
|
||||||
c = m_data [m_tail];
|
|
||||||
sat_inc (m_tail);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
/// Zápis položky
|
|
||||||
/// @return true, pokud se úspěšně provede
|
|
||||||
const bool Write (const T & c) {
|
|
||||||
if (lenght() >= (M - 1)) return false;
|
|
||||||
m_data [m_head] = c;
|
|
||||||
sat_inc (m_head);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // FIFO_H
|
|
|
@ -1,56 +0,0 @@
|
||||||
#ifndef _GPIO_CLASS_H_
|
|
||||||
#define _GPIO_CLASS_H_
|
|
||||||
#include "CH32V20xxx.h"
|
|
||||||
|
|
||||||
enum GPIO_MODE : uint32_t {
|
|
||||||
GPIO_Speed_In = 0u,
|
|
||||||
GPIO_Speed_10MHz = 1u,
|
|
||||||
GPIO_Speed_2MHz = 2u,
|
|
||||||
GPIO_Speed_50MHz = 3u,
|
|
||||||
};
|
|
||||||
enum GPIO_CNF : uint32_t {
|
|
||||||
GPIO_AI_PPO = 0u,
|
|
||||||
GPIO_FI_ODO = 1u << 2,
|
|
||||||
GPIO_UPDI_MPPO = 2u << 2,
|
|
||||||
GPIO_none_MPDO = 3u << 2,
|
|
||||||
};
|
|
||||||
enum GPIOPuPd_TypeDef {
|
|
||||||
GPIO_PuPd_NOPULL = 0x00,
|
|
||||||
GPIO_PuPd_UP = 0x01,
|
|
||||||
GPIO_PuPd_DOWN = 0x02
|
|
||||||
};
|
|
||||||
|
|
||||||
class GpioClass {
|
|
||||||
GPIOA_Type & port;
|
|
||||||
const uint32_t pin;
|
|
||||||
public:
|
|
||||||
explicit constexpr GpioClass (GPIOA_Type & _port, const uint32_t _pin, const uint32_t _mode = GPIO_AI_PPO | GPIO_Speed_10MHz) noexcept
|
|
||||||
: port(_port), pin(_pin) {
|
|
||||||
/* Zapneme vše, ono je to dost jedno. */
|
|
||||||
RCC.APB2PCENR.modify([](RCC_Type::APB2PCENR_DEF & r)->auto {
|
|
||||||
r.B.IOPAEN = SET;
|
|
||||||
r.B.IOPBEN = SET;
|
|
||||||
//r.B.IOPCEN = SET;
|
|
||||||
return r.R;
|
|
||||||
});
|
|
||||||
const uint32_t pos = pin << 2;
|
|
||||||
port.CFGLR.modify([=](GPIOA_Type::CFGLR_DEF & r)->auto {
|
|
||||||
uint32_t t = r.R;
|
|
||||||
t &= ~(0xFu << pos);
|
|
||||||
t |= _mode << pos;
|
|
||||||
return t;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
void operator<< (const bool b) const {
|
|
||||||
port.BSHR.R = b ? 1u << pin : 1u << (pin + 16);
|
|
||||||
}
|
|
||||||
operator bool () const {
|
|
||||||
return port.INDR.R & (1u << pin);
|
|
||||||
}
|
|
||||||
void setPuPd (GPIOPuPd_TypeDef p) {
|
|
||||||
if (p != GPIO_PuPd_UP) return;
|
|
||||||
port.OUTDR.R |= 1u << pin;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _GPIO_CLASS_H_
|
|
|
@ -1,85 +0,0 @@
|
||||||
#include "print.h"
|
|
||||||
|
|
||||||
#define sleep()
|
|
||||||
|
|
||||||
static const char * hexStr = "0123456789ABCDEF";
|
|
||||||
static const uint16_t numLen[] = {1, 32, 1, 11, 8, 0};
|
|
||||||
|
|
||||||
Print::Print (PrintBases b) : BaseLayer () {
|
|
||||||
base = b;
|
|
||||||
}
|
|
||||||
// Výstup blokujeme podle toho, co se vrací ze spodní vrstvy
|
|
||||||
uint32_t Print::BlockDown (const char * buf, uint32_t len) {
|
|
||||||
uint32_t n, ofs = 0, req = len;
|
|
||||||
for (;;) {
|
|
||||||
// spodní vrstva může vrátit i nulu, pokud je FIFO plné
|
|
||||||
n = BaseLayer::Down (buf + ofs, req);
|
|
||||||
ofs += n; // Posuneme ukazatel
|
|
||||||
req -= n; // Zmenšíme další požadavek
|
|
||||||
if (!req) break;
|
|
||||||
sleep(); // A klidně můžeme spát
|
|
||||||
}
|
|
||||||
return ofs;
|
|
||||||
}
|
|
||||||
|
|
||||||
Print& Print::operator<< (const char * str) {
|
|
||||||
uint32_t i = 0;
|
|
||||||
while (str[i++]); // strlen
|
|
||||||
BlockDown (str, --i);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Print& Print::operator<< (const int num) {
|
|
||||||
uint32_t i = BUFLEN;
|
|
||||||
|
|
||||||
if (base == DEC) {
|
|
||||||
unsigned int u;
|
|
||||||
if (num < 0) u = -num;
|
|
||||||
else u = num;
|
|
||||||
do {
|
|
||||||
// Knihovní div() je nevhodné - dělí 2x.
|
|
||||||
// Přímočaré a funkční řešení
|
|
||||||
uint32_t rem;
|
|
||||||
rem = u % (unsigned) DEC; // 1.dělení
|
|
||||||
u = u / (unsigned) DEC; // 2.dělení
|
|
||||||
buf [--i] = hexStr [rem];
|
|
||||||
} while (u);
|
|
||||||
if (num < 0) buf [--i] = '-';
|
|
||||||
} else {
|
|
||||||
uint32_t m = (1U << (uint32_t) base) - 1U;
|
|
||||||
uint32_t l = (uint32_t) numLen [(int) base];
|
|
||||||
uint32_t u = (uint32_t) num;
|
|
||||||
for (unsigned n=0; n<l; n++) {
|
|
||||||
buf [--i] = hexStr [u & m];
|
|
||||||
u >>= (unsigned) base;
|
|
||||||
}
|
|
||||||
if (base == BIN) buf [--i] = 'b';
|
|
||||||
if (base == HEX) buf [--i] = 'x';
|
|
||||||
buf [--i] = '0';
|
|
||||||
}
|
|
||||||
BlockDown (buf+i, BUFLEN-i);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Print& Print::operator<< (const PrintBases num) {
|
|
||||||
base = num;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
void Print::out (const void * p, uint32_t l) {
|
|
||||||
const unsigned char* q = (const unsigned char*) p;
|
|
||||||
unsigned char uc;
|
|
||||||
uint32_t k, n = 0;
|
|
||||||
for (uint32_t i=0; i<l; i++) {
|
|
||||||
uc = q[i];
|
|
||||||
buf[n++] = '<';
|
|
||||||
k = uc >> 4;
|
|
||||||
buf[n++] = hexStr [k];
|
|
||||||
k = uc & 0x0f;
|
|
||||||
buf[n++] = hexStr [k];
|
|
||||||
buf[n++] = '>';
|
|
||||||
}
|
|
||||||
buf[n++] = '\r';
|
|
||||||
buf[n++] = '\n';
|
|
||||||
BlockDown (buf, n);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
#ifndef PRINT_H
|
|
||||||
#define PRINT_H
|
|
||||||
|
|
||||||
#include "baselayer.h"
|
|
||||||
|
|
||||||
#define EOL "\r\n"
|
|
||||||
#define BUFLEN 64
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* @brief Něco jako ostream.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// Základy pro zobrazení čísla.
|
|
||||||
enum PrintBases {
|
|
||||||
BIN=1, OCT=3, DEC=10, HEX=4
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class Print
|
|
||||||
* @brief Třída pro výpisy do Down().
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* V main pak přibude jen definice instance této třídy
|
|
||||||
* @code
|
|
||||||
static Print print;
|
|
||||||
* @endcode
|
|
||||||
* a ukázka, jak se s tím pracuje:
|
|
||||||
* @snippet main.cpp Main print example
|
|
||||||
* Nic na tom není - operátor << má přetížení pro string, číslo a volbu formátu čísla (enum PrintBases).
|
|
||||||
* Výstup je pak do bufferu a aby nám to "neutíkalo", tedy aby se vypsalo vše,
|
|
||||||
* zavedeme blokování, vycházející z toho, že spodní třída vrátí jen počet bytů,
|
|
||||||
* které skutečně odeslala. Při čekání spí, takže nepoužívat v přerušení.
|
|
||||||
* @snippet src/print.cpp Block example
|
|
||||||
* Toto blokování pak není použito ve vrchních třídách stacku,
|
|
||||||
* blokovaná metoda je BlockDown(). Pokud bychom použili přímo Down(), blokování by pak
|
|
||||||
* používaly všechny vrstvy nad tím. A protože mohou Down() používat v přerušení, byl by problém.
|
|
||||||
*
|
|
||||||
* Metody pro výpisy jsou sice dost zjednodušené, ale zase to nezabere
|
|
||||||
* moc místa - pro ladění se to použít dá. Délka vypisovaného stringu není omezena
|
|
||||||
* délkou použitého buferu.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Print : public BaseLayer {
|
|
||||||
public:
|
|
||||||
/// Konstruktor @param b Default decimální výpisy.
|
|
||||||
Print (PrintBases b = DEC);
|
|
||||||
/// Blokování výstupu
|
|
||||||
/// @param buf Ukazatel na data
|
|
||||||
/// @param len Délka přenášených dat
|
|
||||||
/// @return Počet přenesených bytů (rovno len)
|
|
||||||
uint32_t BlockDown (const char * buf, uint32_t len);
|
|
||||||
/// Výstup řetězce bytů
|
|
||||||
/// @param str Ukazatel na řetězec
|
|
||||||
/// @return Odkaz na tuto třídu kvůli řetězení.
|
|
||||||
Print & operator << (const char * str);
|
|
||||||
/// Výstup celého čísla podle base
|
|
||||||
/// @param num Číslo
|
|
||||||
/// @return Odkaz na tuto třídu kvůli řetězení.
|
|
||||||
Print & operator << (const int num);
|
|
||||||
/// Změna základu pro výstup čísla
|
|
||||||
/// @param num enum PrintBases
|
|
||||||
/// @return Odkaz na tuto třídu kvůli řetězení.
|
|
||||||
Print & operator << (const PrintBases num);
|
|
||||||
void out (const void* p, uint32_t l);
|
|
||||||
private:
|
|
||||||
PrintBases base; //!< Základ pro výstup čísla.
|
|
||||||
char buf[BUFLEN]; //!< Buffer pro výstup čísla.
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // PRINT_H
|
|
|
@ -1,116 +0,0 @@
|
||||||
ENTRY( Init )
|
|
||||||
MEMORY
|
|
||||||
{
|
|
||||||
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K
|
|
||||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
|
|
||||||
}
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
.init :
|
|
||||||
{
|
|
||||||
_sinit = .;
|
|
||||||
. = ALIGN(4);
|
|
||||||
KEEP(*(SORT_NONE(.init)))
|
|
||||||
. = ALIGN(4);
|
|
||||||
_einit = .;
|
|
||||||
} >FLASH AT>FLASH
|
|
||||||
.text :
|
|
||||||
{
|
|
||||||
. = ALIGN(4);
|
|
||||||
*(.text.vector)
|
|
||||||
*(.text)
|
|
||||||
*(.text.*)
|
|
||||||
*(.rodata)
|
|
||||||
*(.rodata*)
|
|
||||||
*(.gnu.linkonce.t.*)
|
|
||||||
. = ALIGN(4);
|
|
||||||
} >FLASH AT>FLASH
|
|
||||||
.fini :
|
|
||||||
{
|
|
||||||
KEEP(*(SORT_NONE(.fini)))
|
|
||||||
. = ALIGN(4);
|
|
||||||
} >FLASH AT>FLASH
|
|
||||||
PROVIDE( _etext = . );
|
|
||||||
PROVIDE( _eitcm = . );
|
|
||||||
.preinit_array :
|
|
||||||
{
|
|
||||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
|
||||||
KEEP (*(.preinit_array))
|
|
||||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
|
||||||
} >FLASH AT>FLASH
|
|
||||||
.init_array :
|
|
||||||
{
|
|
||||||
PROVIDE_HIDDEN (__init_array_start = .);
|
|
||||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
|
||||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
|
||||||
PROVIDE_HIDDEN (__init_array_end = .);
|
|
||||||
} >FLASH AT>FLASH
|
|
||||||
.fini_array :
|
|
||||||
{
|
|
||||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
|
||||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
|
||||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
|
||||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
|
||||||
} >FLASH AT>FLASH
|
|
||||||
.ctors :
|
|
||||||
{
|
|
||||||
KEEP (*crtbegin.o(.ctors))
|
|
||||||
KEEP (*crtbegin?.o(.ctors))
|
|
||||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
|
||||||
KEEP (*(SORT(.ctors.*)))
|
|
||||||
KEEP (*(.ctors))
|
|
||||||
} >FLASH AT>FLASH
|
|
||||||
.dtors :
|
|
||||||
{
|
|
||||||
KEEP (*crtbegin.o(.dtors))
|
|
||||||
KEEP (*crtbegin?.o(.dtors))
|
|
||||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
|
||||||
KEEP (*(SORT(.dtors.*)))
|
|
||||||
KEEP (*(.dtors))
|
|
||||||
} >FLASH AT>FLASH
|
|
||||||
.dalign :
|
|
||||||
{
|
|
||||||
. = ALIGN(4);
|
|
||||||
PROVIDE(_data_vma = .);
|
|
||||||
} >RAM AT>FLASH
|
|
||||||
.dlalign :
|
|
||||||
{
|
|
||||||
. = ALIGN(4);
|
|
||||||
PROVIDE(_data_lma = .);
|
|
||||||
} >FLASH AT>FLASH
|
|
||||||
.data :
|
|
||||||
{
|
|
||||||
. = ALIGN(4);
|
|
||||||
*(.gnu.linkonce.r.*)
|
|
||||||
*(.data .data.*)
|
|
||||||
*(.gnu.linkonce.d.*)
|
|
||||||
. = ALIGN(8);
|
|
||||||
PROVIDE( __global_pointer$ = . + 0x800 );
|
|
||||||
*(.sdata .sdata.*)
|
|
||||||
*(.sdata2*)
|
|
||||||
*(.gnu.linkonce.s.*)
|
|
||||||
. = ALIGN(8);
|
|
||||||
*(.srodata.cst16)
|
|
||||||
*(.srodata.cst8)
|
|
||||||
*(.srodata.cst4)
|
|
||||||
*(.srodata.cst2)
|
|
||||||
*(.srodata .srodata.*)
|
|
||||||
. = ALIGN(4);
|
|
||||||
PROVIDE( _edata = .);
|
|
||||||
} >RAM AT>FLASH
|
|
||||||
.bss :
|
|
||||||
{
|
|
||||||
. = ALIGN(4);
|
|
||||||
PROVIDE( _sbss = .);
|
|
||||||
*(.sbss*)
|
|
||||||
*(.gnu.linkonce.sb.*)
|
|
||||||
*(.bss*)
|
|
||||||
*(.gnu.linkonce.b.*)
|
|
||||||
*(COMMON*)
|
|
||||||
. = ALIGN(4);
|
|
||||||
PROVIDE( _ebss = .);
|
|
||||||
} >RAM AT>FLASH
|
|
||||||
PROVIDE( _end = _ebss);
|
|
||||||
PROVIDE( end = . );
|
|
||||||
PROVIDE( _eusrstack = ORIGIN(RAM) + LENGTH(RAM));
|
|
||||||
}
|
|
|
@ -1,264 +0,0 @@
|
||||||
#include "system.h"
|
|
||||||
typedef __SIZE_TYPE__ size_t;
|
|
||||||
extern "C" {
|
|
||||||
extern void handle_reset () __attribute__((naked,nothrow,used));
|
|
||||||
extern void user_init () __attribute__((used));
|
|
||||||
extern int main () __attribute__((used));
|
|
||||||
// This is required to allow pure virtual functions to be defined.
|
|
||||||
extern void __cxa_pure_virtual() { while (1); }
|
|
||||||
|
|
||||||
// These magic symbols are provided by the linker.
|
|
||||||
extern uint32_t _sbss;
|
|
||||||
extern uint32_t _ebss;
|
|
||||||
extern uint32_t _data_lma;
|
|
||||||
extern uint32_t _data_vma;
|
|
||||||
extern uint32_t _edata;
|
|
||||||
|
|
||||||
extern void (*__preinit_array_start[]) (void) __attribute__((weak));
|
|
||||||
extern void (*__preinit_array_end[]) (void) __attribute__((weak));
|
|
||||||
extern void (*__init_array_start[]) (void) __attribute__((weak));
|
|
||||||
extern void (*__init_array_end[]) (void) __attribute__((weak));
|
|
||||||
|
|
||||||
static void __init_array () {
|
|
||||||
uint32_t * dst, * end;
|
|
||||||
|
|
||||||
/* Zero fill the bss section */
|
|
||||||
dst = &_sbss;
|
|
||||||
end = &_ebss;
|
|
||||||
while (dst < end) * dst++ = 0U;
|
|
||||||
/* Copy data section from flash to RAM */
|
|
||||||
uint32_t * src;
|
|
||||||
src = &_data_lma;
|
|
||||||
dst = &_data_vma;
|
|
||||||
end = &_edata;
|
|
||||||
if (src != dst) {
|
|
||||||
while (dst < end) * dst++ = * src++;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t count;
|
|
||||||
/* Pro Cortex-Mx bylo toto zbytečné, lze předpokládat, že je to tak i zde.
|
|
||||||
count = __preinit_array_end - __preinit_array_start;
|
|
||||||
for (unsigned i = 0; i < count; i++) __preinit_array_start[i]();
|
|
||||||
*/
|
|
||||||
count = __init_array_end - __init_array_start;
|
|
||||||
for (unsigned i = 0; i < count; i++) __init_array_start[i]();
|
|
||||||
}
|
|
||||||
// If you don't override a specific handler, it will just spin forever.
|
|
||||||
void DefaultIRQHandler( void ) {
|
|
||||||
// Infinite Loop
|
|
||||||
for (;;);
|
|
||||||
}
|
|
||||||
void NMI_RCC_CSS_IRQHandler( void ) {
|
|
||||||
RCC.INTR.B.CSSC = RESET; // clear the clock security int flag
|
|
||||||
}
|
|
||||||
#define ALIAS(f) __attribute__((nothrow,weak,alias(#f),used))
|
|
||||||
void Ecall_M_Mode_Handler( void ) ALIAS(DefaultIRQHandler);
|
|
||||||
void Ecall_U_Mode_Handler( void ) ALIAS(DefaultIRQHandler);
|
|
||||||
void Break_Point_Handler( void ) ALIAS(DefaultIRQHandler);
|
|
||||||
|
|
||||||
void NMI_Handler( void ) ALIAS(NMI_RCC_CSS_IRQHandler);
|
|
||||||
void HardFault_Handler( void ) ALIAS(DefaultIRQHandler);
|
|
||||||
void SysTick_Handler( void ) ALIAS(DefaultIRQHandler);
|
|
||||||
void SW_Handler( void ) ALIAS(DefaultIRQHandler);
|
|
||||||
|
|
||||||
void WWDG_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void PVD_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TAMPER_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void RTC_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void FLASH_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void RCC_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void EXTI0_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void EXTI1_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void EXTI2_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void EXTI3_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void EXTI4_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void DMA1_Channel1_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void DMA1_Channel2_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void DMA1_Channel3_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void DMA1_Channel4_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void DMA1_Channel5_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void DMA1_Channel6_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void DMA1_Channel7_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void DMA1_Channel8_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void ADC1_2_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void USB_HP_CAN1_TX_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void USB_LP_CAN1_RX0_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void CAN1_RX1_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void CAN1_SCE_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void EXTI9_5_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM1_BRK_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM1_UP_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM1_TRG_COM_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM1_CC_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM2_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM3_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM4_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void I2C1_EV_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void I2C1_ER_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void I2C2_EV_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void I2C2_ER_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void SPI1_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void SPI2_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void USART1_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void USART2_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void USART3_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void EXTI15_10_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void RTCAlarm_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void USBWakeUp_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM8_BRK_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM8_UP__IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM8_TRG_COM_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM8_CC_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM5_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void SPI3_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void UART4_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void UART5_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void ETH_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void ETH_WKUP_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void USBFS_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void USBFSWakeUp_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void USBHD_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void UART6_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void UART7_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void UART8_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM9_BRK_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM9_UP__IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM9_TRG_COM_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM9_CC_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM10_BRK_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM10_UP__IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM10_TRG_COM_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
void TIM10_CC_IRQHandler (void) ALIAS(DefaultIRQHandler);
|
|
||||||
|
|
||||||
void ETHWakeUp_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
|
||||||
void OSC32KCal_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
|
||||||
void OSCWakeUp_IRQHandler( void ) ALIAS(DefaultIRQHandler);
|
|
||||||
|
|
||||||
|
|
||||||
typedef void (*pHandler) (void);
|
|
||||||
void Init() __attribute__((used,section(".init")));
|
|
||||||
extern const pHandler InterruptVector [] __attribute__((section(".text.vector"),aligned(8)));
|
|
||||||
};
|
|
||||||
const pHandler InterruptVector [] = {
|
|
||||||
Init,
|
|
||||||
0,
|
|
||||||
NMI_Handler, /* NMI */
|
|
||||||
HardFault_Handler, /* Hard Fault */
|
|
||||||
0,
|
|
||||||
Ecall_M_Mode_Handler, /* Ecall M Mode */
|
|
||||||
0,0,
|
|
||||||
Ecall_U_Mode_Handler, /* Ecall U Mode */
|
|
||||||
Break_Point_Handler, /* Break Point */
|
|
||||||
0,0,
|
|
||||||
SysTick_Handler, /* SysTick Handler */
|
|
||||||
0,
|
|
||||||
SW_Handler, /* SW Handler */
|
|
||||||
0,
|
|
||||||
/* External Interrupts */
|
|
||||||
WWDG_IRQHandler, /* Window Watchdog */
|
|
||||||
PVD_IRQHandler, /* PVD through EXTI Line detect */
|
|
||||||
TAMPER_IRQHandler, /* TAMPER */
|
|
||||||
RTC_IRQHandler, /* RTC */
|
|
||||||
FLASH_IRQHandler, /* Flash */
|
|
||||||
RCC_IRQHandler, /* RCC */
|
|
||||||
EXTI0_IRQHandler, /* EXTI Line 0 */
|
|
||||||
EXTI1_IRQHandler, /* EXTI Line 1 */
|
|
||||||
EXTI2_IRQHandler, /* EXTI Line 2 */
|
|
||||||
EXTI3_IRQHandler, /* EXTI Line 3 */
|
|
||||||
EXTI4_IRQHandler, /* EXTI Line 4 */
|
|
||||||
DMA1_Channel1_IRQHandler, /* DMA1 Channel 1 */
|
|
||||||
DMA1_Channel2_IRQHandler, /* DMA1 Channel 2 */
|
|
||||||
DMA1_Channel3_IRQHandler, /* DMA1 Channel 3 */
|
|
||||||
DMA1_Channel4_IRQHandler, /* DMA1 Channel 4 */
|
|
||||||
DMA1_Channel5_IRQHandler, /* DMA1 Channel 5 */
|
|
||||||
DMA1_Channel6_IRQHandler, /* DMA1 Channel 6 */
|
|
||||||
DMA1_Channel7_IRQHandler, /* DMA1 Channel 7 */
|
|
||||||
ADC1_2_IRQHandler, /* ADC1_2 */
|
|
||||||
|
|
||||||
USB_HP_CAN1_TX_IRQHandler, /* USB HP and CAN1 TX */
|
|
||||||
USB_LP_CAN1_RX0_IRQHandler, /* USB LP and CAN1RX0 */
|
|
||||||
CAN1_RX1_IRQHandler, /* CAN1 RX1 */
|
|
||||||
CAN1_SCE_IRQHandler, /* CAN1 SCE */
|
|
||||||
|
|
||||||
EXTI9_5_IRQHandler, /* EXTI Line 9..5 */
|
|
||||||
TIM1_BRK_IRQHandler, /* TIM1 Break */
|
|
||||||
TIM1_UP_IRQHandler, /* TIM1 Update */
|
|
||||||
TIM1_TRG_COM_IRQHandler, /* TIM1 Trigger and Commutation */
|
|
||||||
TIM1_CC_IRQHandler, /* TIM1 Capture Compare */
|
|
||||||
TIM2_IRQHandler, /* TIM2 */
|
|
||||||
TIM3_IRQHandler, /* TIM3 */
|
|
||||||
TIM4_IRQHandler, /* TIM4 */
|
|
||||||
I2C1_EV_IRQHandler, /* I2C1 Event */
|
|
||||||
I2C1_ER_IRQHandler, /* I2C1 Error */
|
|
||||||
I2C2_EV_IRQHandler, /* I2C2 Event */
|
|
||||||
I2C2_ER_IRQHandler, /* I2C2 Error */
|
|
||||||
SPI1_IRQHandler, /* SPI1 */
|
|
||||||
SPI2_IRQHandler, /* SPI2 */
|
|
||||||
USART1_IRQHandler, /* USART1 */
|
|
||||||
USART2_IRQHandler, /* USART2 */
|
|
||||||
USART3_IRQHandler, /* USART3 */
|
|
||||||
EXTI15_10_IRQHandler, /* EXTI Line 15..10 */
|
|
||||||
RTCAlarm_IRQHandler, /* RTC Alarm through EXTI Line */
|
|
||||||
|
|
||||||
USBWakeUp_IRQHandler, /* USB Wake up from suspend */
|
|
||||||
USBFS_IRQHandler, /* USBHD Break */
|
|
||||||
|
|
||||||
USBFSWakeUp_IRQHandler, /* USBHD Wake up from suspend */
|
|
||||||
ETH_IRQHandler, /* ETH global */
|
|
||||||
ETHWakeUp_IRQHandler, /* ETH Wake up */
|
|
||||||
0, /* BLE BB */
|
|
||||||
0, /* BLE LLE */
|
|
||||||
TIM5_IRQHandler, /* TIM5 */
|
|
||||||
UART4_IRQHandler, /* UART4 */
|
|
||||||
DMA1_Channel8_IRQHandler, /* DMA1 Channel8 */
|
|
||||||
OSC32KCal_IRQHandler, /* OSC32KCal */
|
|
||||||
OSCWakeUp_IRQHandler, /* OSC Wake Up */
|
|
||||||
|
|
||||||
};
|
|
||||||
void Init() {
|
|
||||||
asm volatile( R"---(
|
|
||||||
.align 1
|
|
||||||
_start:
|
|
||||||
j handle_reset
|
|
||||||
)---");
|
|
||||||
}
|
|
||||||
void handle_reset() noexcept {
|
|
||||||
asm volatile(R"---(
|
|
||||||
.option push
|
|
||||||
.option norelax
|
|
||||||
la gp, __global_pointer$
|
|
||||||
.option pop
|
|
||||||
la sp, _eusrstack
|
|
||||||
)---"
|
|
||||||
#if __GNUC__ > 10
|
|
||||||
".option arch, +zicsr\n"
|
|
||||||
#endif
|
|
||||||
// Setup the interrupt vector, processor status and INTSYSCR.
|
|
||||||
R"---(
|
|
||||||
/* Configure pipelining and instruction prediction */
|
|
||||||
li t0, 0x1f
|
|
||||||
csrw 0xbc0, t0
|
|
||||||
|
|
||||||
/* Enabled nested and hardware stack */
|
|
||||||
li t0, 0x88
|
|
||||||
csrs mstatus, t0
|
|
||||||
|
|
||||||
/* Configure the interrupt vector table recognition mode and entry address mode */
|
|
||||||
la t0, InterruptVector
|
|
||||||
ori t0, t0, 3
|
|
||||||
csrw mtvec, t0
|
|
||||||
|
|
||||||
/* Takhle RISC-V přejde do uživatelského programu. */
|
|
||||||
csrw mepc, %[main]
|
|
||||||
mret
|
|
||||||
)---"
|
|
||||||
: : [main]"r"(user_init)/*, [InterruptVector]"r"(InterruptVector)*/
|
|
||||||
: "t0", "memory" );
|
|
||||||
}
|
|
||||||
void user_init () {
|
|
||||||
SystemInit();
|
|
||||||
SystemCoreClockUpdate();
|
|
||||||
__init_array();
|
|
||||||
main ();
|
|
||||||
for (;;);
|
|
||||||
}
|
|
|
@ -1,147 +0,0 @@
|
||||||
//#include "CH32V20xxx.h"
|
|
||||||
#include "system.h"
|
|
||||||
extern "C" void SystemInit ();
|
|
||||||
enum CLKSRC : uint32_t {
|
|
||||||
CLK_HSI = 0u,
|
|
||||||
CLK_HSE,
|
|
||||||
CLK_PLL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static constexpr unsigned HSI_VALUE = 8000000u; /* Value of the Internal oscillator in Hz */
|
|
||||||
static constexpr unsigned HSE_VALUE = 8000000u; /* Value of the External oscillator in Hz */
|
|
||||||
/* In the following line adjust the External High Speed oscillator (HSE) Startup Timeout value */
|
|
||||||
static constexpr unsigned SYSCLK_FREQ_96MHz_HSE = SYSTEM_CORE_CLOCK;
|
|
||||||
static constexpr unsigned HSE_STARTUP_TIMEOUT = 0x1000u; /* Time out for HSE start up */
|
|
||||||
// HSE i HSI mají frekvenci 8 MHz
|
|
||||||
static constexpr uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
|
|
||||||
|
|
||||||
uint32_t SystemCoreClock = SYSCLK_FREQ_96MHz_HSE; /* System Clock Frequency (Core Clock) */
|
|
||||||
|
|
||||||
static void SetSysClockTo96_HSE(void) {
|
|
||||||
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
|
||||||
|
|
||||||
RCC.CTLR.B.HSEON = SET;
|
|
||||||
|
|
||||||
/* Wait till HSE is ready and if Time out is reached exit */
|
|
||||||
do {
|
|
||||||
HSEStatus = RCC.CTLR.B.HSERDY;
|
|
||||||
StartUpCounter++;
|
|
||||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
|
||||||
|
|
||||||
if ((RCC.CTLR.B.HSERDY) != RESET) {
|
|
||||||
HSEStatus = (uint32_t)0x01;
|
|
||||||
} else {
|
|
||||||
HSEStatus = (uint32_t)0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HSEStatus == (uint32_t)0x01) {
|
|
||||||
RCC.CFGR0.modify([](RCC_Type::CFGR0_DEF & r) -> auto {
|
|
||||||
r.B.HPRE = 0u; /* HCLK = SYSCLK */
|
|
||||||
r.B.PPRE2 = 0u; /* PCLK2 = HCLK */
|
|
||||||
r.B.PPRE1 = 4u; /* PCLK1 = HCLK */
|
|
||||||
/* CH32V20x_D6-PLL configuration: PLLCLK = HSE * 12 = 96 MHz (HSE=8MHZ)
|
|
||||||
* CH32V20x_D8-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz (HSE=32MHZ)
|
|
||||||
* CH32V20x_D8W-PLL configuration: PLLCLK = HSE/4 * 12 = 96 MHz (HSE=32MHZ)
|
|
||||||
*/
|
|
||||||
r.B.PLLSRC = SET;
|
|
||||||
r.B.PLLXTPRE = RESET;
|
|
||||||
r.B.PLLMUL = 10u;
|
|
||||||
return r.R;
|
|
||||||
});
|
|
||||||
/* Enable PLL */
|
|
||||||
RCC.CTLR.B.PLLON = SET;
|
|
||||||
/* Wait till PLL is ready */
|
|
||||||
while((RCC.CTLR.B.PLLRDY) == RESET) {}
|
|
||||||
/* Select PLL as system clock source */
|
|
||||||
RCC.CFGR0.B.SW = CLK_PLL;
|
|
||||||
/* Wait till PLL is used as system clock source */
|
|
||||||
while (RCC.CFGR0.B.SWS != CLK_PLL) {}
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* If HSE fails to start-up, the application will have wrong clock
|
|
||||||
* configuration. User can add here some code to deal with this error
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SystemInit(void) {
|
|
||||||
RCC.CTLR.R |= 0x00000001u;
|
|
||||||
RCC.CFGR0.R &= 0xF0FF0000u;
|
|
||||||
RCC.CTLR.R &= 0xFEF6FFFFu;
|
|
||||||
RCC.CTLR.R &= 0xFFFBFFFFu;
|
|
||||||
RCC.CFGR0.R &= 0xFF00FFFFu;
|
|
||||||
RCC.INTR.R = 0x009F0000u;
|
|
||||||
SetSysClockTo96_HSE();
|
|
||||||
}
|
|
||||||
/*********************************************************************
|
|
||||||
* @fn SystemCoreClockUpdate
|
|
||||||
*
|
|
||||||
* @brief Update SystemCoreClock variable according to Clock Register Values.
|
|
||||||
*
|
|
||||||
* @return none
|
|
||||||
*/
|
|
||||||
void SystemCoreClockUpdate (void) {
|
|
||||||
uint32_t tmp = 0, pllmull = 0, pllsource = 0, Pll_6_5 = 0;
|
|
||||||
|
|
||||||
tmp = RCC.CFGR0.B.SWS;
|
|
||||||
|
|
||||||
switch (tmp) {
|
|
||||||
case 0x00:
|
|
||||||
SystemCoreClock = HSI_VALUE;
|
|
||||||
break;
|
|
||||||
case 0x01:
|
|
||||||
SystemCoreClock = HSE_VALUE;
|
|
||||||
break;
|
|
||||||
case 0x02:
|
|
||||||
pllmull = RCC.CFGR0.B.PLLMUL;
|
|
||||||
pllsource = RCC.CFGR0.B.PLLSRC;
|
|
||||||
pllmull += 2u;
|
|
||||||
|
|
||||||
if(pllmull == 17) pllmull = 18;
|
|
||||||
|
|
||||||
if (pllsource == 0u) {
|
|
||||||
if(EXTEND.EXTEND_CTR.B.PLL_HSI_PRE){
|
|
||||||
SystemCoreClock = HSI_VALUE * pllmull;
|
|
||||||
} else {
|
|
||||||
SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (RCC.CFGR0.B.PLLXTPRE) {
|
|
||||||
SystemCoreClock = (HSE_VALUE >> 1) * pllmull;
|
|
||||||
} else {
|
|
||||||
SystemCoreClock = HSE_VALUE * pllmull;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Pll_6_5 == 1) SystemCoreClock = (SystemCoreClock / 2);
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
SystemCoreClock = HSI_VALUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp = AHBPrescTable[RCC.CFGR0.B.HPRE];
|
|
||||||
SystemCoreClock >>= tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t p_us = 0u;
|
|
||||||
void delay_init () {
|
|
||||||
p_us = SystemCoreClock / 8000000;
|
|
||||||
}
|
|
||||||
void delay_us (const unsigned dly) {
|
|
||||||
const uint32_t i = (uint32_t) dly * p_us;
|
|
||||||
SysTick.SR &= ~(1 << 0);
|
|
||||||
SysTick.CMPLR = i;
|
|
||||||
SysTick.CTLR.modify([](SysTick_Type::CTLR_DEF & r) -> uint32_t {
|
|
||||||
r.B.MODE = SET;
|
|
||||||
r.B.INIT = SET;
|
|
||||||
return r.R;
|
|
||||||
});
|
|
||||||
SysTick.CTLR.B.STE = SET;
|
|
||||||
|
|
||||||
while((SysTick.SR & (1u << 0)) != (1u << 0));
|
|
||||||
SysTick.CTLR.B.STE = RESET;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
#ifndef SYSTEM_H
|
|
||||||
#define SYSTEM_H
|
|
||||||
#include "CH32V20xxx.h"
|
|
||||||
struct NVIC_Type {
|
|
||||||
__I uint32_t ISR[8];
|
|
||||||
__I uint32_t IPR[8];
|
|
||||||
__IO uint32_t ITHRESDR;
|
|
||||||
__IO uint32_t RESERVED;
|
|
||||||
__IO uint32_t CFGR;
|
|
||||||
__I uint32_t GISR;
|
|
||||||
__IO uint8_t VTFIDR[4];
|
|
||||||
uint8_t RESERVED0[12];
|
|
||||||
__IO uint32_t VTFADDR[4];
|
|
||||||
uint8_t RESERVED1[0x90];
|
|
||||||
__O uint32_t IENR[8];
|
|
||||||
uint8_t RESERVED2[0x60];
|
|
||||||
__O uint32_t IRER[8];
|
|
||||||
uint8_t RESERVED3[0x60];
|
|
||||||
__O uint32_t IPSR[8];
|
|
||||||
uint8_t RESERVED4[0x60];
|
|
||||||
__O uint32_t IPRR[8];
|
|
||||||
uint8_t RESERVED5[0x60];
|
|
||||||
__IO uint32_t IACTR[8];
|
|
||||||
uint8_t RESERVED6[0xE0];
|
|
||||||
__IO uint8_t IPRIOR[256];
|
|
||||||
uint8_t RESERVED7[0x810];
|
|
||||||
__IO uint32_t SCTLR;
|
|
||||||
void EnableIRQ (IRQn IRQ) {
|
|
||||||
IENR [((uint32_t)(IRQ) >> 5)] = (1 << ((uint32_t)(IRQ) & 0x1F));
|
|
||||||
}
|
|
||||||
void DisableIRQ (IRQn IRQ) {
|
|
||||||
IRER [((uint32_t)(IRQ) >> 5)] = (1 << ((uint32_t)(IRQ) & 0x1F));
|
|
||||||
}
|
|
||||||
void SetPriority(IRQn IRQ, uint8_t priority) {
|
|
||||||
IPRIOR[(uint32_t)(IRQ)] = priority;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
static NVIC_Type & NVIC = * reinterpret_cast<NVIC_Type * const> (0xE000E000);
|
|
||||||
struct SysTick_Type {
|
|
||||||
union CTLR_DEF {
|
|
||||||
struct {
|
|
||||||
__IO ONE_BIT STE : 1; //!<[00] System counter enable
|
|
||||||
__IO ONE_BIT STIE : 1; //!<[01] System counter interrupt enable
|
|
||||||
__IO ONE_BIT STCLK : 1; //!<[02] System selects the clock source
|
|
||||||
__IO ONE_BIT STRE : 1; //!<[03] System reload register
|
|
||||||
__IO ONE_BIT MODE : 1; //!<[04] System Mode
|
|
||||||
__IO ONE_BIT INIT : 1; //!<[05] System Initialization update
|
|
||||||
uint32_t UNUSED0 : 25; //!<[06]
|
|
||||||
__IO ONE_BIT SWIE : 1; //!<[31] System software triggered interrupts enable
|
|
||||||
} B;
|
|
||||||
__IO uint32_t R;
|
|
||||||
template<typename F> void modify (F f) volatile {
|
|
||||||
CTLR_DEF r; r.R = R;
|
|
||||||
R = f (r);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
__IO CTLR_DEF CTLR ; //!< [1000](04)[0x00000000]
|
|
||||||
__IO uint32_t SR ; //!< [1004](04)[0x00000000]
|
|
||||||
__IO uint32_t CNTL ; //!< [1008](04)[0x00000000]
|
|
||||||
__IO uint32_t CNTH ; //!< [100c](04)[0x00000000]
|
|
||||||
__IO uint32_t CMPLR ; //!< [1010](04)[0x00000000]
|
|
||||||
__IO uint32_t CMPHR ; //!< [1014](04)[0x00000000]
|
|
||||||
|
|
||||||
void Config (const uint32_t ticks) {
|
|
||||||
CNTL = 0u;
|
|
||||||
CNTH = 0u;
|
|
||||||
CMPLR = ticks - 1u;
|
|
||||||
CMPHR = 0u;
|
|
||||||
CTLR.modify ([] (CTLR_DEF & r) -> auto { // TODO ???
|
|
||||||
r.B.STE = SET;
|
|
||||||
r.B.STIE = SET;
|
|
||||||
r.B.STCLK = SET;
|
|
||||||
r.B.STRE = SET;
|
|
||||||
return r.R;
|
|
||||||
});
|
|
||||||
NVIC.EnableIRQ (SysTicK_IRQn);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
static SysTick_Type & SysTick = * reinterpret_cast<SysTick_Type * const> (0xE000F000);
|
|
||||||
static constexpr unsigned SYSTEM_CORE_CLOCK = 96'000'000u;
|
|
||||||
extern "C" {
|
|
||||||
extern uint32_t SystemCoreClock;
|
|
||||||
extern void SystemCoreClockUpdate (void);
|
|
||||||
extern void SystemInit(void);
|
|
||||||
extern void delay_init ();
|
|
||||||
extern void delay_us (const unsigned dly);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // SYSTEM_H
|
|
|
@ -1,25 +0,0 @@
|
||||||
# Use clang / llvm toolchain
|
|
||||||
#
|
|
||||||
CC = clang
|
|
||||||
CXX = clang++
|
|
||||||
LD = ld.lld
|
|
||||||
SIZE = llvm-size
|
|
||||||
DUMP = riscv64-unknown-elf-objdump
|
|
||||||
COPY = riscv64-unknown-elf-objcopy
|
|
||||||
AS = riscv64-unknown-elf-as
|
|
||||||
|
|
||||||
#OBJS += startup.o system.o
|
|
||||||
CCPU = -march=rv32imac -mabi=ilp32
|
|
||||||
MCPU = $(CCPU)
|
|
||||||
TRIP = riscv32-unknown-none-elf
|
|
||||||
CFLAGS+= -Oz
|
|
||||||
CFLAGS+= -fmessage-length=0 -fsigned-char -I/usr/include/newlib
|
|
||||||
#CFLAGS+= -fconstexpr-steps=2097152
|
|
||||||
CFLAGS+= --target=$(TRIP) $(MCPU)
|
|
||||||
LFLAGS+= --Map=$(@:%.elf=%.map) --gc-sections
|
|
||||||
# 16-bit instrukce se do toho asi dostanou až na úrovni LLVM linkeru.
|
|
||||||
# Bohužel to není nikde pořádně popsáno.
|
|
||||||
LFLAGS+= -mllvm -mattr=+c
|
|
||||||
LFLAGS+= -nostdlib
|
|
||||||
#LDLIBS+= -L$(SRCDIR)/Ld -T Link.ld
|
|
||||||
LDLIBS+= -L./ch32v203 -T script.ld
|
|
|
@ -1,21 +0,0 @@
|
||||||
# Use gcc / binutils toolchain
|
|
||||||
PREFIX = riscv64-unknown-elf-
|
|
||||||
CC = $(PREFIX)gcc
|
|
||||||
CXX = $(PREFIX)g++
|
|
||||||
LD = $(PREFIX)gcc
|
|
||||||
AS = $(PREFIX)as
|
|
||||||
SIZE = $(PREFIX)size
|
|
||||||
DUMP = $(PREFIX)objdump
|
|
||||||
COPY = $(PREFIX)objcopy
|
|
||||||
#OBJS += startup.o system.o
|
|
||||||
CFLAGS+= -Os
|
|
||||||
CCPU = -march=rv32imac -mabi=ilp32
|
|
||||||
MCPU = $(CCPU)
|
|
||||||
|
|
||||||
CFLAGS+= $(MCPU) -fmessage-length=0 -I/usr/include/newlib
|
|
||||||
LFLAGS+= -Wl,--Map=$(@:%.elf=%.map),--gc-sections
|
|
||||||
#LFLAGS+= -Wl,--print-sysroot -- chyba ld ?
|
|
||||||
LFLAGS+= -O3 $(MCPU) -nostartfiles -nostdlib
|
|
||||||
#LFLAGS+= -L${HOME}/Downloads/MRS_Toolchain_Linux_x64_V1.91/RISC-V_Embedded_GCC/riscv-none-embed/lib/rv32imac/ilp32 -lprintf -lc
|
|
||||||
#LDLIBS+= -L$(SRCDIR)/Ld -T Link.ld
|
|
||||||
LDLIBS+= -L./ch32v203 -T script.ld
|
|
|
@ -1,21 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
typedef __SIZE_TYPE__ size_t;
|
|
||||||
size_t strlen (const char *s) {
|
|
||||||
size_t l = 0;
|
|
||||||
while (*s++) l++;
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
void *memcpy (void *dest, const void *src, size_t n) {
|
|
||||||
const char *s = (const char *) src;
|
|
||||||
char *d = (char *) dest;
|
|
||||||
int i;
|
|
||||||
for (i=0; i<n; i++) d[i] = s[i];
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
void *memset (void *s, int c, size_t n) {
|
|
||||||
char *p = (char *) s;
|
|
||||||
int i;
|
|
||||||
for (i=0; i<n; i++) p[i] = c;
|
|
||||||
return s;
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
#include "cdc_class.h"
|
|
||||||
#include "print.h"
|
|
||||||
static cdc_class cdc;
|
|
||||||
static Print out;
|
|
||||||
int main () {
|
|
||||||
cdc.init();
|
|
||||||
out += cdc;
|
|
||||||
int n = 0;
|
|
||||||
for (;;) {
|
|
||||||
out << "Loop pass : " << n++ << EOL;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
strings = [["MyManuInfo","Kizarm labs."],["MyProdInfo","USB <=> Serial"],["MySerNumInfo","0123456789"],]
|
|
||||||
|
|
||||||
def print_string (s):
|
|
||||||
name = bytearray (s[1], 'utf-8')
|
|
||||||
r = 'const uint8_t {0:s} [] = {{\n '.format (s[0])
|
|
||||||
r += '0x{0:02X},0x03,'.format (2 * (len (name) + 1))
|
|
||||||
for e in name:
|
|
||||||
r += '\'{0:c}\',0,'.format (e)
|
|
||||||
r = r[:-1]
|
|
||||||
r += '\n};\n'
|
|
||||||
return r
|
|
||||||
|
|
||||||
def print_strings (filename):
|
|
||||||
r = ''
|
|
||||||
for s in strings: r += print_string (s)
|
|
||||||
#print (r)
|
|
||||||
f = open (filename, 'w')
|
|
||||||
f.write (r)
|
|
||||||
f.close
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
print_strings ('mystrings.inc')
|
|
|
@ -1,69 +0,0 @@
|
||||||
/********************************** (C) COPYRIGHT *******************************
|
|
||||||
* File Name : usb_desc.c
|
|
||||||
* Author : WCH
|
|
||||||
* Version : V1.0.0
|
|
||||||
* Date : 2022/08/20
|
|
||||||
* Description : usb device descriptor,configuration descriptor,
|
|
||||||
* string descriptors and other descriptors.
|
|
||||||
*********************************************************************************
|
|
||||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
|
||||||
* Attention: This software (modified or not) and binary are used for
|
|
||||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
#include "usb_desc.h"
|
|
||||||
|
|
||||||
/* Device Descriptor */
|
|
||||||
const uint8_t MyDevDescr[] =
|
|
||||||
{
|
|
||||||
0x12, // bLength
|
|
||||||
0x01, // bDescriptorType (Device)
|
|
||||||
0x10, 0x01, // bcdUSB 1.10
|
|
||||||
0x02, // bDeviceClass
|
|
||||||
0x00, // bDeviceSubClass
|
|
||||||
0x00, // bDeviceProtocol
|
|
||||||
DEF_USBD_UEP0_SIZE, // bMaxPacketSize0 64
|
|
||||||
(uint8_t)DEF_USB_VID, (uint8_t)(DEF_USB_VID >> 8), // idVendor 0x1A86
|
|
||||||
(uint8_t)DEF_USB_PID, (uint8_t)(DEF_USB_PID >> 8), // idProduct 0x5537
|
|
||||||
DEF_IC_PRG_VER, 0x00, // bcdDevice 0.01
|
|
||||||
0x01, // iManufacturer (String Index)
|
|
||||||
0x02, // iProduct (String Index)
|
|
||||||
0x03, // iSerialNumber (String Index)
|
|
||||||
0x01, // bNumConfigurations 1
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Configuration Descriptor */
|
|
||||||
const uint8_t MyCfgDescr[] =
|
|
||||||
{
|
|
||||||
/* Configure descriptor */
|
|
||||||
0x09, 0x02, 0x43, 0x00, 0x02, 0x01, 0x00, 0x80, 0x32,
|
|
||||||
|
|
||||||
/* Interface 0 (CDC) descriptor */
|
|
||||||
0x09, 0x04, 0x00, 0x00, 0x01, 0x02, 0x02, 0x01, 0x00,
|
|
||||||
|
|
||||||
/* Functional Descriptors */
|
|
||||||
0x05, 0x24, 0x00, 0x10, 0x01,
|
|
||||||
|
|
||||||
/* Length/management descriptor (data class interface 1) */
|
|
||||||
0x05, 0x24, 0x01, 0x00, 0x01,
|
|
||||||
0x04, 0x24, 0x02, 0x02,
|
|
||||||
0x05, 0x24, 0x06, 0x00, 0x01,
|
|
||||||
|
|
||||||
/* Interrupt upload endpoint descriptor */
|
|
||||||
0x07, 0x05, 0x81, 0x03, (uint8_t)DEF_USBD_ENDP1_SIZE, (uint8_t)( DEF_USBD_ENDP1_SIZE >> 8 ), 0x01,
|
|
||||||
|
|
||||||
/* Interface 1 (data interface) descriptor */
|
|
||||||
0x09, 0x04, 0x01, 0x00, 0x02, 0x0A, 0x00, 0x00, 0x00,
|
|
||||||
|
|
||||||
/* Endpoint descriptor */
|
|
||||||
0x07, 0x05, 0x02, 0x02, (uint8_t)DEF_USBD_ENDP2_SIZE, (uint8_t)( DEF_USBD_ENDP2_SIZE >> 8 ), 0x00,
|
|
||||||
|
|
||||||
/* Endpoint descriptor */
|
|
||||||
0x07, 0x05, 0x83, 0x02, (uint8_t)DEF_USBD_ENDP3_SIZE, (uint8_t)( DEF_USBD_ENDP3_SIZE >> 8 ), 0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Language Descriptor */
|
|
||||||
const uint8_t MyLangDescr[] = {
|
|
||||||
0x04, 0x03, 0x09, 0x04
|
|
||||||
};
|
|
||||||
#include "mystrings.inc"
|
|
|
@ -1,67 +0,0 @@
|
||||||
/********************************** (C) COPYRIGHT *******************************
|
|
||||||
* File Name : usb_desc.h
|
|
||||||
* Author : WCH
|
|
||||||
* Version : V1.0.0
|
|
||||||
* Date : 2022/08/20
|
|
||||||
* Description : header file of usb_desc.c
|
|
||||||
*********************************************************************************
|
|
||||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
|
||||||
* Attention: This software (modified or not) and binary are used for
|
|
||||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
#ifndef USER_USB_DESC_H_
|
|
||||||
#define USER_USB_DESC_H_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
/* global define */
|
|
||||||
/* file version */
|
|
||||||
#define DEF_FILE_VERSION 0x01
|
|
||||||
/* usb device info define */
|
|
||||||
#define DEF_USB_VID 0x1A86
|
|
||||||
#define DEF_USB_PID 0xFE0C
|
|
||||||
/* USB device descriptor, device serial number(bcdDevice) */
|
|
||||||
#define DEF_IC_PRG_VER DEF_FILE_VERSION
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
/* usb device endpoint size define */
|
|
||||||
#define DEF_USBD_UEP0_SIZE 64 /* usb hs/fs device end-point 0 size */
|
|
||||||
/* FS */
|
|
||||||
#define DEF_USBD_FS_PACK_SIZE 64 /* usb fs device max bluk/int pack size */
|
|
||||||
#define DEF_USBD_FS_ISO_PACK_SIZE 1023 /* usb fs device max iso pack size */
|
|
||||||
/* LS */
|
|
||||||
#define DEF_USBD_LS_UEP0_SIZE 8 /* usb ls device end-point 0 size */
|
|
||||||
#define DEF_USBD_LS_PACK_SIZE 64 /* usb ls device max int pack size */
|
|
||||||
|
|
||||||
/* Pack size */
|
|
||||||
#define DEF_USBD_ENDP1_SIZE DEF_USBD_FS_PACK_SIZE
|
|
||||||
#define DEF_USBD_ENDP2_SIZE DEF_USBD_FS_PACK_SIZE
|
|
||||||
#define DEF_USBD_ENDP3_SIZE DEF_USBD_FS_PACK_SIZE
|
|
||||||
#define DEF_USBD_ENDP4_SIZE DEF_USBD_FS_PACK_SIZE
|
|
||||||
#define DEF_USBD_ENDP5_SIZE DEF_USBD_FS_PACK_SIZE
|
|
||||||
#define DEF_USBD_ENDP6_SIZE DEF_USBD_FS_PACK_SIZE
|
|
||||||
#define DEF_USBD_ENDP7_SIZE DEF_USBD_FS_PACK_SIZE
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
/* usb device Descriptor length, length of usb descriptors, if one descriptor not
|
|
||||||
* exists , set the length to 0 */
|
|
||||||
#define DEF_USBD_DEVICE_DESC_LEN ((uint8_t)MyDevDescr[0])
|
|
||||||
#define DEF_USBD_CONFIG_DESC_LEN ((uint16_t)MyCfgDescr[2] + (uint16_t)(MyCfgDescr[3] << 8))
|
|
||||||
#define DEF_USBD_REPORT_DESC_LEN 0
|
|
||||||
#define DEF_USBD_LANG_DESC_LEN ((uint16_t)MyLangDescr[0])
|
|
||||||
#define DEF_USBD_MANU_DESC_LEN ((uint16_t)MyManuInfo[0])
|
|
||||||
#define DEF_USBD_PROD_DESC_LEN ((uint16_t)MyProdInfo[0])
|
|
||||||
#define DEF_USBD_SN_DESC_LEN ((uint16_t)MySerNumInfo[0])
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
/* external variables */
|
|
||||||
extern const uint8_t MyDevDescr[ ];
|
|
||||||
extern const uint8_t MyCfgDescr[ ];
|
|
||||||
extern const uint8_t MyLangDescr[ ];
|
|
||||||
extern const uint8_t MyManuInfo[ ];
|
|
||||||
extern const uint8_t MyProdInfo[ ];
|
|
||||||
extern const uint8_t MySerNumInfo[ ];
|
|
||||||
|
|
||||||
#endif /* USER_USB_DESC_H_ */
|
|
Loading…
Reference in a new issue