diff --git a/V203F6P6/ch32v203/system.cpp b/V203F6P6/ch32v203/system.cpp index 68818bd..4ef464f 100644 --- a/V203F6P6/ch32v203/system.cpp +++ b/V203F6P6/ch32v203/system.cpp @@ -141,6 +141,9 @@ void delay_us (const unsigned dly) { while((SysTick.SR & (1u << 0)) != (1u << 0)); SysTick.CTLR.B.STE = RESET; } +void Delay_Ms (const unsigned dly) { + delay_us(1000 * dly); +} void set_timeout_us (const uint32_t time) { SysTick.CTLR.B.STE = RESET; timeout = false; diff --git a/V203F6P6/ch32v203/system.h b/V203F6P6/ch32v203/system.h index b44ccf1..3df1e0f 100644 --- a/V203F6P6/ch32v203/system.h +++ b/V203F6P6/ch32v203/system.h @@ -86,6 +86,7 @@ extern "C" { extern void SystemInit(void); extern void delay_init (); extern void delay_us (const unsigned dly); + extern void Delay_Ms (const unsigned dly); extern void set_timeout_us (const uint32_t time); extern bool is_timeout (); }; diff --git a/V203F6P6/ch32v203/usart.cpp b/V203F6P6/ch32v203/usart.cpp index 7595481..d477e9c 100644 --- a/V203F6P6/ch32v203/usart.cpp +++ b/V203F6P6/ch32v203/usart.cpp @@ -87,4 +87,16 @@ uint32_t Usart::Down(const char * data, const uint32_t len) { }); return n; } - +void Usart::setBaud (const uint32_t baud) { + USART2.CTLR1.B.UE = RESET; + const uint32_t tmp = HCLK / baud; + USART2.BRR.R = tmp; + USART2.CTLR1.B.UE = SET; +} +bool Usart::IOCtrl (const CTRL_TYPES_DEF type, const void * data, const uint32_t len) { + if (type == USB_USART_SET_PARAM) { + const USB_CDC_LineCoding * lc = reinterpret_cast(data); + setBaud (lc->baud); + } + return true; +} diff --git a/V203F6P6/ch32v203/usbd/Makefile b/V203F6P6/ch32v203/usbd/Makefile new file mode 100644 index 0000000..e80e844 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/Makefile @@ -0,0 +1,38 @@ +FLAGS = -c -ggdb -Os +CPU ?= -march=rv32imac -mabi=ilp32 +CROSS = riscv64-unknown-elf- +FLAGS+= $(CPU) +FLAGS+= -ffunction-sections -fdata-sections +FLAGS+= -mno-save-restore -fmessage-length=0 +FLAGS+= -I/usr/include/newlib -I. -I.. -I../../common -I./inc +AS = $(CROSS)as +CC = $(CROSS)gcc +CC += $(FLAGS) +CXX = $(CROSS)g++ +CXX += $(FLAGS) -fno-exceptions -fno-rtti +AR = $(CROSS)ar +VPATH = ./src + +OBJS = cdc_class.o +OBJS += hw_config.o usb_endp.o usb_istr.o usb_prop.o usb_pwr.o +OBJS += usb_core.o usb_init.o usb_int.o usb_mem.o usb_regs.o usb_sil.o + +DSTLIB = libusbd.a + +%.o: %.S + $(AS) $< -o $@ +%.o: %.c + $(CC) $< -o $@ +%.o: %.cpp + $(CXX) $< -o $@ + +$(DSTLIB): $(OBJS) + $(AR) rcs $(DSTLIB) $(OBJS) + + +.PHONY: all clean + +all: $(DSTLIB) + +clean: + -rm -f *.o diff --git a/V203F6P6/ch32v203/usbd/cdc_class.h b/V203F6P6/ch32v203/usbd/cdc_class.h new file mode 100644 index 0000000..40ac3fa --- /dev/null +++ b/V203F6P6/ch32v203/usbd/cdc_class.h @@ -0,0 +1,23 @@ +#ifndef CDC_CLASS_H +#define CDC_CLASS_H +#include "baselayer.h" +#include "ctrlinterface.h" +#include "fifo.h" + +class cdc_class : public BaseLayer { + CDC_CtrlInterface * ctrli; + volatile bool ep3Busy, Ready; + uint8_t rxbuffer [256]; +public: + explicit cdc_class (); + void attach (CDC_CtrlInterface & i) { ctrli = & i; } + void init (); + void ep2outHandler (); + void ep3inHandler (); + void ctrl (const CTRL_TYPES_DEF type, const void * data, const uint32_t len); + uint32_t Down (const char * data, const uint32_t len) override; +protected: +}; +extern cdc_class * cdc_instance; + +#endif // CDC_CLASS_H diff --git a/V203F6P6/ch32v203/usbd/inc/ch32v20x.h b/V203F6P6/ch32v203/usbd/inc/ch32v20x.h new file mode 100644 index 0000000..c64b103 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/inc/ch32v20x.h @@ -0,0 +1,16 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : ch32v20x.h + * Author : WCH + * Version : V1.0.0 + * Date : 2024/01/31 + * Description : CH32V20x Device Peripheral Access Layer Header File. + ********************************************************************************* + * 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_H +#define __CH32V20x_H +/* Tady pouze, protože je to použito v usb hlavičkách */ +#include "core_riscv.h" +#endif diff --git a/V203F6P6/ch32v203/usbd/inc/core_riscv.h b/V203F6P6/ch32v203/usbd/inc/core_riscv.h new file mode 100644 index 0000000..6cda3d0 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/inc/core_riscv.h @@ -0,0 +1,320 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : core_riscv.h + * Author : WCH + * Version : V1.0.1 + * Date : 2023/11/11 + * Description : RISC-V V4 Core Peripheral Access Layer Header File for CH32V20x +********************************************************************************* +* 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 __CORE_RISCV_H__ +#define __CORE_RISCV_H__ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* IO definitions */ +#ifdef __cplusplus + #define __I volatile /* defines 'read only' permissions */ +#else + #define __I volatile const /* defines 'read only' permissions */ +#endif +#define __O volatile /* defines 'write only' permissions */ +#define __IO volatile /* defines 'read / write' permissions */ + +/* Standard Peripheral Library old types (maintained for legacy purpose) */ +typedef __I uint64_t vuc64; /* Read Only */ +typedef __I uint32_t vuc32; /* Read Only */ +typedef __I uint16_t vuc16; /* Read Only */ +typedef __I uint8_t vuc8; /* Read Only */ + +typedef const uint64_t uc64; /* Read Only */ +typedef const uint32_t uc32; /* Read Only */ +typedef const uint16_t uc16; /* Read Only */ +typedef const uint8_t uc8; /* Read Only */ + +typedef __I int64_t vsc64; /* Read Only */ +typedef __I int32_t vsc32; /* Read Only */ +typedef __I int16_t vsc16; /* Read Only */ +typedef __I int8_t vsc8; /* Read Only */ + +typedef const int64_t sc64; /* Read Only */ +typedef const int32_t sc32; /* Read Only */ +typedef const int16_t sc16; /* Read Only */ +typedef const int8_t sc8; /* Read Only */ + +typedef __IO uint64_t vu64; +typedef __IO uint32_t vu32; +typedef __IO uint16_t vu16; +typedef __IO uint8_t vu8; + +typedef uint64_t u64; +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; + +typedef __IO int64_t vs64; +typedef __IO int32_t vs32; +typedef __IO int16_t vs16; +typedef __IO int8_t vs8; + +typedef int64_t s64; +typedef int32_t s32; +typedef int16_t s16; +typedef int8_t s8; + +#define RV_STATIC_INLINE static inline + +typedef enum {NoREADY = 0, READY = !NoREADY} ErrorStatus; + +typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; +/********************************************************************* + * @fn __enable_irq + * + * @brief Enable Global Interrupt + * + * @return none + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __enable_irq() +{ + __asm volatile ("csrs 0x800, %0" : : "r" (0x88) ); +} + +/********************************************************************* + * @fn __disable_irq + * + * @brief Disable Global Interrupt + * + * @return none + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __disable_irq() +{ + __asm volatile ("csrc 0x800, %0" : : "r" (0x88) ); +} + +/********************************************************************* + * @fn __NOP + * + * @brief nop + * + * @return none + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __NOP() +{ + __asm volatile ("nop"); +} + +/********************************************************************* + * @fn __AMOADD_W + * + * @brief Atomic Add with 32bit value + * Atomically ADD 32bit value with value in memory using amoadd.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be ADDed + * + * @return return memory value + add value + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOADD_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amoadd.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOAND_W + * + * @brief Atomic And with 32bit value + * Atomically AND 32bit value with value in memory using amoand.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be ANDed + * + * @return return memory value & and value + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOAND_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amoand.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOMAX_W + * + * @brief Atomic signed MAX with 32bit value + * Atomically signed max compare 32bit value with value in memory using amomax.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be compared + * + * @return the bigger value + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOMAX_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amomax.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOMAXU_W + * + * @brief Atomic unsigned MAX with 32bit value + * Atomically unsigned max compare 32bit value with value in memory using amomaxu.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be compared + * + * @return return the bigger value + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t __AMOMAXU_W(volatile uint32_t *addr, uint32_t value) +{ + uint32_t result; + + __asm volatile ("amomaxu.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOMIN_W + * + * @brief Atomic signed MIN with 32bit value + * Atomically signed min compare 32bit value with value in memory using amomin.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be compared + * + * @return the smaller value + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOMIN_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amomin.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOMINU_W + * + * @brief Atomic unsigned MIN with 32bit value + * Atomically unsigned min compare 32bit value with value in memory using amominu.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be compared + * + * @return the smaller value + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t __AMOMINU_W(volatile uint32_t *addr, uint32_t value) +{ + uint32_t result; + + __asm volatile ("amominu.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOOR_W + * + * @brief Atomic OR with 32bit value + * Atomically OR 32bit value with value in memory using amoor.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be ORed + * + * @return return memory value | and value + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOOR_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amoor.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/********************************************************************* + * @fn __AMOSWAP_W + * + * @brief Atomically swap new 32bit value into memory using amoswap.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * newval - New value to be stored into the address + * + * @return return the original value in memory + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t __AMOSWAP_W(volatile uint32_t *addr, uint32_t newval) +{ + uint32_t result; + + __asm volatile ("amoswap.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(newval) : "memory"); + return result; +} + +/********************************************************************* + * @fn __AMOXOR_W + * + * @brief Atomic XOR with 32bit value + * Atomically XOR 32bit value with value in memory using amoxor.d. + * + * @param addr - Address pointer to data, address need to be 4byte aligned + * value - value to be XORed + * + * @return return memory value ^ and value + */ +__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOXOR_W(volatile int32_t *addr, int32_t value) +{ + int32_t result; + + __asm volatile ("amoxor.w %0, %2, %1" : \ + "=r"(result), "+A"(*addr) : "r"(value) : "memory"); + return *addr; +} + +/* Core_Exported_Functions */ +extern uint32_t __get_MSTATUS(void); +extern void __set_MSTATUS(uint32_t value); +extern uint32_t __get_MISA(void); +extern void __set_MISA(uint32_t value); +extern uint32_t __get_MTVEC(void); +extern void __set_MTVEC(uint32_t value); +extern uint32_t __get_MSCRATCH(void); +extern void __set_MSCRATCH(uint32_t value); +extern uint32_t __get_MEPC(void); +extern void __set_MEPC(uint32_t value); +extern uint32_t __get_MCAUSE(void); +extern void __set_MCAUSE(uint32_t value); +extern uint32_t __get_MTVAL(void); +extern void __set_MTVAL(uint32_t value); +extern uint32_t __get_MVENDORID(void); +extern uint32_t __get_MARCHID(void); +extern uint32_t __get_MIMPID(void); +extern uint32_t __get_MHARTID(void); +extern uint32_t __get_SP(void); + +#ifdef __cplusplus +} +#endif + +#endif + + + + + diff --git a/V203F6P6/ch32v203/usbd/inc/hw_config.h b/V203F6P6/ch32v203/usbd/inc/hw_config.h new file mode 100644 index 0000000..aaa1eb4 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/inc/hw_config.h @@ -0,0 +1,46 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : hw_config.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : Configuration file for USB. +********************************************************************************* +* 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 __HW_CONFIG_H +#define __HW_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +#include "core_riscv.h" +#include "usb_type.h" + +#ifdef DEBUG +#define printf_usb(X...) printf(X) +#else +#define printf_usb(X...) +#endif + +void DeviceInit(); +void Set_USBConfig(void); +void Enter_LowPowerMode(void); +void Leave_LowPowerMode(void); +void USB_Interrupts_Config(void); +void USB_Port_Set(FunctionalState NewState, FunctionalState Pin_In_IPU); + +#ifdef __cplusplus +}; +#endif //__cplusplus +#endif /* __HW_CONFIG_H */ + + + + + + + + diff --git a/V203F6P6/ch32v203/usbd/inc/usb_conf.h b/V203F6P6/ch32v203/usbd/inc/usb_conf.h new file mode 100644 index 0000000..6772432 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/inc/usb_conf.h @@ -0,0 +1,84 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_conf.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : This file contains all the functions prototypes for the + * USB configration 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 __USB_CONF_H +#define __USB_CONF_H +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + + +#define EP_NUM (15) + +/* Buffer Description Table */ +/* buffer table base address */ +/* buffer table base address */ +#define BTABLE_ADDRESS (0x00) + +/* EP0 */ +/* rx/tx buffer base address */ +#define ENDP0_RXADDR (0x40) +#define ENDP0_TXADDR (0x80) + +/* EP1 */ +/* tx buffer base address */ +#define ENDP1_TXADDR (0xC0) +#define ENDP2_RXADDR (ENDP1_TXADDR + 0x40) +#define ENDP3_TXADDR (ENDP2_RXADDR + 0x40) + + +/* ISTR events */ +/* IMR_MSK */ +/* mask defining which events has to be handled */ +/* by the device application software */ +#define IMR_MSK (CNTR_CTRM | CNTR_WKUPM | CNTR_SUSPM | CNTR_ERRM | CNTR_SOFM \ + | CNTR_ESOFM | CNTR_RESETM ) + +/* #define CTR_CALLBACK */ +/* #define DOVR_CALLBACK */ +/* #define ERR_CALLBACK */ +/* #define WKUP_CALLBACK */ +/* #define SUSP_CALLBACK */ +/* #define RESET_CALLBAC K*/ +/* #define SOF_CALLBACK */ +/* #define ESOF_CALLBACK */ + + +/* CTR service routines */ +/* associated to defined endpoints */ +// #define EP1_IN_Callback NOP_Process +#define EP2_IN_Callback NOP_Process +// #define EP3_IN_Callback NOP_Process +#define EP4_IN_Callback NOP_Process +#define EP5_IN_Callback NOP_Process +#define EP6_IN_Callback NOP_Process +#define EP7_IN_Callback NOP_Process + +#define EP1_OUT_Callback NOP_Process +// #define EP2_OUT_Callback NOP_Process +#define EP3_OUT_Callback NOP_Process +#define EP4_OUT_Callback NOP_Process +#define EP5_OUT_Callback NOP_Process +#define EP6_OUT_Callback NOP_Process +#define EP7_OUT_Callback NOP_Process + +#ifdef __cplusplus +}; +#endif //__cplusplus + +#endif /* __USB_CONF_H */ + + + + + + diff --git a/V203F6P6/ch32v203/usbd/inc/usb_core.h b/V203F6P6/ch32v203/usbd/inc/usb_core.h new file mode 100644 index 0000000..f4f2036 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/inc/usb_core.h @@ -0,0 +1,191 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_core.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : This file contains all the functions prototypes for the + * USB cor 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 __USB_CORE_H +#define __USB_CORE_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v20x.h" + + +typedef enum _CONTROL_STATE +{ + WAIT_SETUP, /* 0 */ + SETTING_UP, /* 1 */ + IN_DATA, /* 2 */ + OUT_DATA, /* 3 */ + LAST_IN_DATA, /* 4 */ + LAST_OUT_DATA, /* 5 */ + WAIT_STATUS_IN, /* 7 */ + WAIT_STATUS_OUT, /* 8 */ + STALLED, /* 9 */ + PAUSE /* 10 */ +} CONTROL_STATE; /* The state machine states of a control pipe */ + +typedef struct OneDescriptor +{ + uint8_t *Descriptor; + uint16_t Descriptor_Size; +} +ONE_DESCRIPTOR, *PONE_DESCRIPTOR; + +typedef enum _RESULT +{ + USB_SUCCESS = 0, /* Process successfully */ + USB_ERROR, + USB_UNSUPPORT, + USB_NOT_READY /* The process has not been finished, endpoint will be + NAK to further request */ +} RESULT; + + +/* Definitions for endpoint level */ +typedef struct _ENDPOINT_INFO +{ + uint16_t Usb_wLength; + uint16_t Usb_wOffset; + uint16_t PacketSize; + uint8_t *(*CopyData)(uint16_t Length); +}ENDPOINT_INFO; + +/* Definitions for device level */ +typedef struct _DEVICE +{ + uint8_t Total_Endpoint; /* Number of endpoints that are used */ + uint8_t Total_Configuration;/* Number of configuration available */ +} +DEVICE; + +typedef union +{ + uint16_t w; + struct BW + { + uint8_t bb1; + uint8_t bb0; + } + bw; +} uint16_t_uint8_t; + +typedef struct _DEVICE_INFO +{ + uint8_t USBbmRequestType; /* bmRequestType */ + uint8_t USBbRequest; /* bRequest */ + uint16_t_uint8_t USBwValues; /* wValue */ + uint16_t_uint8_t USBwIndexs; /* wIndex */ + uint16_t_uint8_t USBwLengths; /* wLength */ + + uint8_t ControlState; /* of type CONTROL_STATE */ + uint8_t Current_Feature; + uint8_t Current_Configuration; /* Selected configuration */ + uint8_t Current_Interface; /* Selected interface of current configuration */ + uint8_t Current_AlternateSetting;/* Selected Alternate Setting of current + interface*/ + + ENDPOINT_INFO Ctrl_Info; +}DEVICE_INFO; + +typedef struct _DEVICE_PROP +{ + void (*Init)(void); /* Initialize the device */ + void (*Reset)(void); /* Reset routine of this device */ + void (*Process_Status_IN)(void); + void (*Process_Status_OUT)(void); + + RESULT (*Class_Data_Setup)(uint8_t RequestNo); + + RESULT (*Class_NoData_Setup)(uint8_t RequestNo); + + RESULT (*Class_Get_Interface_Setting)(uint8_t Interface, uint8_t AlternateSetting); + + uint8_t* (*GetDeviceDescriptor)(uint16_t Length); + uint8_t* (*GetConfigDescriptor)(uint16_t Length); + uint8_t* (*GetStringDescriptor)(uint16_t Length); + + void* RxEP_buffer; + + uint8_t MaxPacketSize; + +}DEVICE_PROP; + +typedef struct _USER_STANDARD_REQUESTS +{ + void (*User_GetConfiguration)(void); /* Get Configuration */ + void (*User_SetConfiguration)(void); /* Set Configuration */ + void (*User_GetInterface)(void); /* Get Interface */ + void (*User_SetInterface)(void); /* Set Interface */ + void (*User_GetStatus)(void); /* Get Status */ + void (*User_ClearFeature)(void); /* Clear Feature */ + void (*User_SetEndPointFeature)(void); /* Set Endpoint Feature */ + void (*User_SetDeviceFeature)(void); /* Set Device Feature */ + void (*User_SetDeviceAddress)(void); /* Set Device Address */ +} +USER_STANDARD_REQUESTS; + + +#define Type_Recipient (pInformation->USBbmRequestType & (REQUEST_TYPE | RECIPIENT)) + +#define Usb_rLength Usb_wLength +#define Usb_rOffset Usb_wOffset + +#define USBwValue USBwValues.w +#define USBwValue0 USBwValues.bw.bb0 +#define USBwValue1 USBwValues.bw.bb1 +#define USBwIndex USBwIndexs.w +#define USBwIndex0 USBwIndexs.bw.bb0 +#define USBwIndex1 USBwIndexs.bw.bb1 +#define USBwLength USBwLengths.w +#define USBwLength0 USBwLengths.bw.bb0 +#define USBwLength1 USBwLengths.bw.bb1 + + +uint8_t Setup0_Process(void); +uint8_t Post0_Process(void); +uint8_t Out0_Process(void); +uint8_t In0_Process(void); + +RESULT Standard_SetEndPointFeature(void); +RESULT Standard_SetDeviceFeature(void); + +uint8_t *Standard_GetConfiguration(uint16_t Length); +RESULT Standard_SetConfiguration(void); +uint8_t *Standard_GetInterface(uint16_t Length); +RESULT Standard_SetInterface(void); +uint8_t *Standard_GetDescriptorData(uint16_t Length, PONE_DESCRIPTOR pDesc); + +uint8_t *Standard_GetStatus(uint16_t Length); +RESULT Standard_ClearFeature(void); +void SetDeviceAddress(uint8_t); +void NOP_Process(void); + +extern DEVICE_PROP Device_Property; +extern USER_STANDARD_REQUESTS User_Standard_Requests; +extern DEVICE Device_Table; +extern DEVICE_INFO Device_Info; + +/* cells saving status during interrupt servicing */ +extern __IO uint16_t SaveRState; +extern __IO uint16_t SaveTState; + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_CORE_H */ + + + + + diff --git a/V203F6P6/ch32v203/usbd/inc/usb_def.h b/V203F6P6/ch32v203/usbd/inc/usb_def.h new file mode 100644 index 0000000..702ca61 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/inc/usb_def.h @@ -0,0 +1,82 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_def.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : This file contains all the functions prototypes for the + * USB definition 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 __USB_DEF_H +#define __USB_DEF_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v20x.h" + +typedef enum _RECIPIENT_TYPE +{ + DEVICE_RECIPIENT, + INTERFACE_RECIPIENT, + ENDPOINT_RECIPIENT, + OTHER_RECIPIENT +} RECIPIENT_TYPE; + +typedef enum _STANDARD_REQUESTS +{ + GET_STATUS = 0, + CLEAR_FEATURE, + RESERVED1, + SET_FEATURE, + RESERVED2, + SET_ADDRESS, + GET_DESCRIPTOR, + SET_DESCRIPTOR, + GET_CONFIGURATION, + SET_CONFIGURATION, + GET_INTERFACE, + SET_INTERFACE, + TOTAL_sREQUEST, + SYNCH_FRAME = 12 +} STANDARD_REQUESTS; + +/* Definition of "USBwValue" */ +typedef enum _DESCRIPTOR_TYPE +{ + DEVICE_DESCRIPTOR = 1, + CONFIG_DESCRIPTOR, + STRING_DESCRIPTOR, + INTERFACE_DESCRIPTOR, + ENDPOINT_DESCRIPTOR +} DESCRIPTOR_TYPE; + +/* Feature selector of a SET_FEATURE or CLEAR_FEATURE */ +typedef enum _FEATURE_SELECTOR +{ + ENDPOINT_STALL, + DEVICE_REMOTE_WAKEUP +} FEATURE_SELECTOR; + +/* Definition of "USBbmRequestType" */ +#define REQUEST_TYPE 0x60 +#define STANDARD_REQUEST 0x00 +#define CLASS_REQUEST 0x20 +#define VENDOR_REQUEST 0x40 +#define RECIPIENT 0x1F + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_DEF_H */ + + + + + + diff --git a/V203F6P6/ch32v203/usbd/inc/usb_init.h b/V203F6P6/ch32v203/usbd/inc/usb_init.h new file mode 100644 index 0000000..f282407 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/inc/usb_init.h @@ -0,0 +1,42 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_init.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : This file contains all the functions prototypes for the + * USB Initialization 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 __USB_INIT_H +#define __USB_INIT_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v20x.h" + + +void USB_Init(void); +extern uint8_t EPindex; +extern DEVICE_INFO* pInformation; +extern DEVICE_PROP* pProperty; +extern USER_STANDARD_REQUESTS *pUser_Standard_Requests; +extern uint16_t SaveState ; +extern uint16_t wInterrupt_Mask; + +#ifdef __cplusplus +} + +#endif + + +#endif /* __USB_INIT_H */ + + + + + diff --git a/V203F6P6/ch32v203/usbd/inc/usb_int.h b/V203F6P6/ch32v203/usbd/inc/usb_int.h new file mode 100644 index 0000000..7599d61 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/inc/usb_int.h @@ -0,0 +1,25 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_int.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : This file contains all the functions prototypes for the + * USB Endpoint 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 __USB_INT_H +#define __USB_INT_H +#ifdef __cplusplus + extern "C" { +#endif + +void CTR_LP(void); +void CTR_HP(void); +#ifdef __cplusplus +}; +#endif + +#endif /* __USB_INT_H */ diff --git a/V203F6P6/ch32v203/usbd/inc/usb_istr.h b/V203F6P6/ch32v203/usbd/inc/usb_istr.h new file mode 100644 index 0000000..e64a2a8 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/inc/usb_istr.h @@ -0,0 +1,82 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_istr.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : This file includes the peripherals header files in the + * user application. +********************************************************************************* +* 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 __USB_ISTR_H +#define __USB_ISTR_H + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus +#include "usb_conf.h" + +void USB_Istr(void); +void EP1_IN_Callback(void); +void EP2_IN_Callback(void); +void EP3_IN_Callback(void); +void EP4_IN_Callback(void); +void EP5_IN_Callback(void); +void EP6_IN_Callback(void); +void EP7_IN_Callback(void); + +void EP1_OUT_Callback(void); +void EP2_OUT_Callback(void); +void EP3_OUT_Callback(void); +void EP4_OUT_Callback(void); +void EP5_OUT_Callback(void); +void EP6_OUT_Callback(void); +void EP7_OUT_Callback(void); + +#ifdef CTR_CALLBACK +void CTR_Callback(void); +#endif + +#ifdef DOVR_CALLBACK +void DOVR_Callback(void); +#endif + +#ifdef ERR_CALLBACK +void ERR_Callback(void); +#endif + +#ifdef WKUP_CALLBACK +void WKUP_Callback(void); +#endif + +#ifdef SUSP_CALLBACK +void SUSP_Callback(void); +#endif + +#ifdef RESET_CALLBACK +void RESET_Callback(void); +#endif + +#ifdef SOF_CALLBACK +void SOF_Callback(void); +#endif + +#ifdef ESOF_CALLBACK +void ESOF_Callback(void); +#endif + +#ifdef __cplusplus +}; +#endif // __cplusplus + +#endif /*__USB_ISTR_H*/ + + + + + + + + diff --git a/V203F6P6/ch32v203/usbd/inc/usb_lib.h b/V203F6P6/ch32v203/usbd/inc/usb_lib.h new file mode 100644 index 0000000..f633a1f --- /dev/null +++ b/V203F6P6/ch32v203/usbd/inc/usb_lib.h @@ -0,0 +1,30 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_lib.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : Library configuration file for USB. +********************************************************************************* +* 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 __USB_LIB_H +#define __USB_LIB_H + +#include "hw_config.h" +#include "usb_type.h" +#include "usb_regs.h" +#include "usb_def.h" +#include "usb_core.h" +#include "usb_init.h" +#include "usb_sil.h" +#include "usb_mem.h" +#include "usb_int.h" +//#include "ch32f20x_usb.h" + +#endif /* __USB_LIB_H */ + + + + diff --git a/V203F6P6/ch32v203/usbd/inc/usb_mem.h b/V203F6P6/ch32v203/usbd/inc/usb_mem.h new file mode 100644 index 0000000..879fded --- /dev/null +++ b/V203F6P6/ch32v203/usbd/inc/usb_mem.h @@ -0,0 +1,36 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_mem.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : This file contains all the functions prototypes for the + * USB Initialization 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 __USB_MEM_H +#define __USB_MEM_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v20x.h" + +void UserToPMABufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes); +void PMAToUserBufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes); + + +#ifdef __cplusplus +} +#endif + +#endif /*__USB_MEM_H*/ + + + + + + diff --git a/V203F6P6/ch32v203/usbd/inc/usb_prop.h b/V203F6P6/ch32v203/usbd/inc/usb_prop.h new file mode 100644 index 0000000..b0c695c --- /dev/null +++ b/V203F6P6/ch32v203/usbd/inc/usb_prop.h @@ -0,0 +1,66 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_prop.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : All processing related to Virtual COM Port Demo (Endpoint 0) +********************************************************************************* +* 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 __usb_prop_H +#define __usb_prop_H + +#ifdef __cplusplus + extern "C" { +#endif + +//#include "ch32v20x.h" +#include "usb_core.h" + +#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 + + +#define USBD_GetConfiguration NOP_Process +// #define USBD_SetConfiguration NOP_Process +#define USBD_GetInterface NOP_Process +#define USBD_SetInterface NOP_Process +#define USBD_GetStatus NOP_Process +// #define USBD_ClearFeature NOP_Process +#define USBD_SetEndPointFeature NOP_Process +// #define USBD_SetDeviceFeature NOP_Process +// #define USBD_SetDeviceAddress NOP_Process + + + +void USBD_init(void); +void USBD_Reset(void); +void USBD_SetConfiguration(void); +void USBD_SetDeviceAddress (void); +void USBD_SetDeviceFeature (void); +void USBD_ClearFeature (void); +void USBD_Status_In (void); +void USBD_Status_Out (void); +RESULT USBD_Data_Setup(uint8_t); +RESULT USBD_NoData_Setup(uint8_t); +RESULT USBD_Get_Interface_Setting(uint8_t Interface, uint8_t AlternateSetting); +uint8_t *USBD_GetDeviceDescriptor(uint16_t ); +uint8_t *USBD_GetConfigDescriptor(uint16_t); +uint8_t *USBD_GetStringDescriptor(uint16_t); +uint8_t USBD_ENDPx_DataUp( uint8_t endp, uint8_t *pbuf, uint16_t len ); +#ifdef __cplusplus +} +#endif + +#endif /* __usb_prop_H */ + + + + + + + diff --git a/V203F6P6/ch32v203/usbd/inc/usb_pwr.h b/V203F6P6/ch32v203/usbd/inc/usb_pwr.h new file mode 100644 index 0000000..ce80fa2 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/inc/usb_pwr.h @@ -0,0 +1,62 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_pwr.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : Connection/disconnection & power management header +********************************************************************************* +* 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 __USB_PWR_H +#define __USB_PWR_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v20x.h" +typedef enum _RESUME_STATE +{ + RESUME_EXTERNAL, + RESUME_INTERNAL, + RESUME_LATER, + RESUME_WAIT, + RESUME_START, + RESUME_ON, + RESUME_OFF, + RESUME_ESOF +} RESUME_STATE; + +typedef enum _DEVICE_STATE +{ + UNCONNECTED, + ATTACHED, + POWERED, + SUSPENDED, + ADDRESSED, + CONFIGURED +} DEVICE_STATE; + + +void Suspend(void); +void Resume_Init(void); +void Resume(RESUME_STATE eResumeSetVal); +RESULT PowerOn(void); +RESULT PowerOff(void); + +extern __IO uint32_t bDeviceState; /* USB device status */ +extern __IO bool fSuspendEnabled; /* true when suspend is possible */ + +#ifdef __cplusplus +} +#endif + +#endif /*__USB_PWR_H*/ + + + + + + diff --git a/V203F6P6/ch32v203/usbd/inc/usb_regs.h b/V203F6P6/ch32v203/usbd/inc/usb_regs.h new file mode 100644 index 0000000..46a041b --- /dev/null +++ b/V203F6P6/ch32v203/usbd/inc/usb_regs.h @@ -0,0 +1,675 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_regs.h + * Author : WCH + * Version : V1.0.1 + * Date : 2022/12/28 + * Description : This file contains all the functions prototypes for the + * USB cell registers 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 __USB_REGS_H +#define __USB_REGS_H + +#ifdef __cplusplus + extern "C" { +#endif + +//#include "ch32v20x.h" + +typedef enum _EP_DBUF_DIR +{ + EP_DBUF_ERR, + EP_DBUF_OUT, + EP_DBUF_IN +}EP_DBUF_DIR; + +/* endpoint buffer number */ +enum EP_BUF_NUM +{ + EP_NOBUF, + EP_BUF0, + EP_BUF1 +}; + +extern uint16_t Ep0RxBlks; + +#define RegBase (0x40005C00L) +#define PMAAddr (0x40006000L) + +/******************************************************************************/ +/* General registers */ +/******************************************************************************/ + +/* Control register */ +#define CNTLR ((__IO unsigned *)(RegBase + 0x40)) +/* Interrupt status register */ +#define ISTR ((__IO unsigned *)(RegBase + 0x44)) +/* Frame number register */ +#define FNR ((__IO unsigned *)(RegBase + 0x48)) +/* Device address register */ +#define DADDR ((__IO unsigned *)(RegBase + 0x4C)) +/* Buffer Table address register */ +#define BTABLE ((__IO unsigned *)(RegBase + 0x50)) +/******************************************************************************/ +/* Endpoint registers */ +/******************************************************************************/ +#define EP0REG ((__IO unsigned *)(RegBase)) /* endpoint 0 register address */ + +/* Endpoint Addresses (w/direction) */ +#define EP0_OUT ((uint8_t)0x00) +#define EP0_IN ((uint8_t)0x80) +#define EP1_OUT ((uint8_t)0x01) +#define EP1_IN ((uint8_t)0x81) +#define EP2_OUT ((uint8_t)0x02) +#define EP2_IN ((uint8_t)0x82) +#define EP3_OUT ((uint8_t)0x03) +#define EP3_IN ((uint8_t)0x83) +#define EP4_OUT ((uint8_t)0x04) +#define EP4_IN ((uint8_t)0x84) +#define EP5_OUT ((uint8_t)0x05) +#define EP5_IN ((uint8_t)0x85) +#define EP6_OUT ((uint8_t)0x06) +#define EP6_IN ((uint8_t)0x86) +#define EP7_OUT ((uint8_t)0x07) +#define EP7_IN ((uint8_t)0x87) + +/* endpoints enumeration */ +#define ENDP0 ((uint8_t)0) +#define ENDP1 ((uint8_t)1) +#define ENDP2 ((uint8_t)2) +#define ENDP3 ((uint8_t)3) +#define ENDP4 ((uint8_t)4) +#define ENDP5 ((uint8_t)5) +#define ENDP6 ((uint8_t)6) +#define ENDP7 ((uint8_t)7) + +/******************************************************************************/ +/* ISTR interrupt events */ +/******************************************************************************/ +#define ISTR_CTR (0x8000) /* Correct TRansfer (clear-only bit) */ +#define ISTR_DOVR (0x4000) /* DMA OVeR/underrun (clear-only bit) */ +#define ISTR_ERR (0x2000) /* ERRor (clear-only bit) */ +#define ISTR_WKUP (0x1000) /* WaKe UP (clear-only bit) */ +#define ISTR_SUSP (0x0800) /* SUSPend (clear-only bit) */ +#define ISTR_RESET (0x0400) /* RESET (clear-only bit) */ +#define ISTR_SOF (0x0200) /* Start Of Frame (clear-only bit) */ +#define ISTR_ESOF (0x0100) /* Expected Start Of Frame (clear-only bit) */ + + +#define ISTR_DIR (0x0010) /* DIRection of transaction (read-only bit) */ +#define ISTR_EP_ID (0x000F) /* EndPoint IDentifier (read-only bit) */ + +#define CLR_CTR (~ISTR_CTR) /* clear Correct TRansfer bit */ +#define CLR_DOVR (~ISTR_DOVR) /* clear DMA OVeR/underrun bit*/ +#define CLR_ERR (~ISTR_ERR) /* clear ERRor bit */ +#define CLR_WKUP (~ISTR_WKUP) /* clear WaKe UP bit */ +#define CLR_SUSP (~ISTR_SUSP) /* clear SUSPend bit */ +#define CLR_RESET (~ISTR_RESET) /* clear RESET bit */ +#define CLR_SOF (~ISTR_SOF) /* clear Start Of Frame bit */ +#define CLR_ESOF (~ISTR_ESOF) /* clear Expected Start Of Frame bit */ + +/******************************************************************************/ +/* CNTR control register bits definitions */ +/******************************************************************************/ +#define CNTR_CTRM (0x8000) /* Correct TRansfer Mask */ +#define CNTR_DOVRM (0x4000) /* DMA OVeR/underrun Mask */ +#define CNTR_ERRM (0x2000) /* ERRor Mask */ +#define CNTR_WKUPM (0x1000) /* WaKe UP Mask */ +#define CNTR_SUSPM (0x0800) /* SUSPend Mask */ +#define CNTR_RESETM (0x0400) /* RESET Mask */ +#define CNTR_SOFM (0x0200) /* Start Of Frame Mask */ +#define CNTR_ESOFM (0x0100) /* Expected Start Of Frame Mask */ + + +#define CNTR_RESUME (0x0010) /* RESUME request */ +#define CNTR_FSUSP (0x0008) /* Force SUSPend */ +#define CNTR_LPMODE (0x0004) /* Low-power MODE */ +#define CNTR_PDWN (0x0002) /* Power DoWN */ +#define CNTR_FRES (0x0001) /* Force USB RESet */ + +/******************************************************************************/ +/* FNR Frame Number Register bit definitions */ +/******************************************************************************/ +#define FNR_RXDP (0x8000) /* status of D+ data line */ +#define FNR_RXDM (0x4000) /* status of D- data line */ +#define FNR_LCK (0x2000) /* LoCKed */ +#define FNR_LSOF (0x1800) /* Lost SOF */ +#define FNR_FN (0x07FF) /* Frame Number */ +/******************************************************************************/ +/* DADDR Device ADDRess bit definitions */ +/******************************************************************************/ +#define DADDR_EF (0x80) +#define DADDR_ADD (0x7F) +/******************************************************************************/ +/* Endpoint register */ +/******************************************************************************/ +/* bit positions */ +#define EP_CTR_RX (0x8000) /* EndPoint Correct TRansfer RX */ +#define EP_DTOG_RX (0x4000) /* EndPoint Data TOGGLE RX */ +#define EPRX_STAT (0x3000) /* EndPoint RX STATus bit field */ +#define EP_SETUP (0x0800) /* EndPoint SETUP */ +#define EP_T_FIELD (0x0600) /* EndPoint TYPE */ +#define EP_KIND (0x0100) /* EndPoint KIND */ +#define EP_CTR_TX (0x0080) /* EndPoint Correct TRansfer TX */ +#define EP_DTOG_TX (0x0040) /* EndPoint Data TOGGLE TX */ +#define EPTX_STAT (0x0030) /* EndPoint TX STATus bit field */ +#define EPADDR_FIELD (0x000F) /* EndPoint ADDRess FIELD */ + +/* EndPoint REGister MASK (no toggle fields) */ +#define EPREG_MASK (EP_CTR_RX|EP_SETUP|EP_T_FIELD|EP_KIND|EP_CTR_TX|EPADDR_FIELD) + +/* EP_TYPE[1:0] EndPoint TYPE */ +#define EP_TYPE_MASK (0x0600) /* EndPoint TYPE Mask */ +#define EP_BULK (0x0000) /* EndPoint BULK */ +#define EP_CONTROL (0x0200) /* EndPoint CONTROL */ +#define EP_ISOCHRONOUS (0x0400) /* EndPoint ISOCHRONOUS */ +#define EP_INTERRUPT (0x0600) /* EndPoint INTERRUPT */ +#define EP_T_MASK (~EP_T_FIELD & EPREG_MASK) + + +/* EP_KIND EndPoint KIND */ +#define EPKIND_MASK (~EP_KIND & EPREG_MASK) + +/* STAT_TX[1:0] STATus for TX transfer */ +#define EP_TX_DIS (0x0000) /* EndPoint TX DISabled */ +#define EP_TX_STALL (0x0010) /* EndPoint TX STALLed */ +#define EP_TX_NAK (0x0020) /* EndPoint TX NAKed */ +#define EP_TX_VALID (0x0030) /* EndPoint TX VALID */ +#define EPTX_DTOG1 (0x0010) /* EndPoint TX Data TOGgle bit1 */ +#define EPTX_DTOG2 (0x0020) /* EndPoint TX Data TOGgle bit2 */ +#define EPTX_DTOGMASK (EPTX_STAT|EPREG_MASK) + +/* STAT_RX[1:0] STATus for RX transfer */ +#define EP_RX_DIS (0x0000) /* EndPoint RX DISabled */ +#define EP_RX_STALL (0x1000) /* EndPoint RX STALLed */ +#define EP_RX_NAK (0x2000) /* EndPoint RX NAKed */ +#define EP_RX_VALID (0x3000) /* EndPoint RX VALID */ +#define EPRX_DTOG1 (0x1000) /* EndPoint RX Data TOGgle bit1 */ +#define EPRX_DTOG2 (0x2000) /* EndPoint RX Data TOGgle bit1 */ +#define EPRX_DTOGMASK (EPRX_STAT|EPREG_MASK) + +/* SetCNTR */ +#define _SetCNTR(wRegValue) (*CNTLR = (uint16_t)wRegValue) + +/* SetISTR */ +#define _SetISTR(wRegValue) (*ISTR = (uint16_t)wRegValue) + +/* SetDADDR */ +#define _SetDADDR(wRegValue) (*DADDR = (uint16_t)wRegValue) + +/* SetBTABLE */ +#define _SetBTABLE(wRegValue)(*BTABLE = (uint16_t)(wRegValue & 0xFFF8)) + +/* GetCNTR */ +#define _GetCNTR() ((uint16_t) *CNTLR) + +/* GetISTR */ +#define _GetISTR() ((uint16_t) *ISTR) + +/* GetFNR */ +#define _GetFNR() ((uint16_t) *FNR) + +/* GetDADDR */ +#define _GetDADDR() ((uint16_t) *DADDR) + +/* GetBTABLE */ +#define _GetBTABLE() ((uint16_t) *BTABLE) + +/* SetENDPOINT */ +#define _SetENDPOINT(bEpNum,wRegValue) (*(EP0REG + bEpNum)= \ + (uint16_t)wRegValue) + +/* GetENDPOINT */ +#define _GetENDPOINT(bEpNum) ((uint16_t)(*(EP0REG + bEpNum))) + +#define _SetEPType(bEpNum,wType) (_SetENDPOINT(bEpNum,\ + ((_GetENDPOINT(bEpNum) & EP_T_MASK) | wType ))) + +#define _GetEPType(bEpNum) (_GetENDPOINT(bEpNum) & EP_T_FIELD) + +/******************************************************************************* +* Macro Name : SetEPTxStatus +* Description : sets the status for tx transfer (bits STAT_TX[1:0]). +* Input : bEpNum: Endpoint Number. +* wState: new state +* Return : None. +*******************************************************************************/ +#define _SetEPTxStatus(bEpNum,wState) {\ + register uint16_t _wRegVal; \ + _wRegVal = _GetENDPOINT(bEpNum) & EPTX_DTOGMASK;\ + /* toggle first bit ? */ \ + if((EPTX_DTOG1 & wState)!= 0) \ + _wRegVal ^= EPTX_DTOG1; \ + /* toggle second bit ? */ \ + if((EPTX_DTOG2 & wState)!= 0) \ + _wRegVal ^= EPTX_DTOG2; \ + _SetENDPOINT(bEpNum, (_wRegVal | EP_CTR_RX|EP_CTR_TX)); \ + while( ( _GetENDPOINT(bEpNum) & EPTX_STAT ) != wState ) \ + { \ + _SetENDPOINT(bEpNum, (_wRegVal | EP_CTR_RX|EP_CTR_TX)); \ + }; \ + } /* _SetEPTxStatus */ + +/******************************************************************************* +* Macro Name : SetEPRxStatus +* Description : sets the status for rx transfer (bits STAT_TX[1:0]) +* Input : bEpNum: Endpoint Number. +* wState: new state. +* Return : None. +*******************************************************************************/ +#define _SetEPRxStatus(bEpNum,wState) {\ + register uint16_t _wRegVal; \ + \ + _wRegVal = _GetENDPOINT(bEpNum) & EPRX_DTOGMASK;\ + /* toggle first bit ? */ \ + if((EPRX_DTOG1 & wState)!= 0) \ + _wRegVal ^= EPRX_DTOG1; \ + /* toggle second bit ? */ \ + if((EPRX_DTOG2 & wState)!= 0) \ + _wRegVal ^= EPRX_DTOG2; \ + _SetENDPOINT(bEpNum, (_wRegVal | EP_CTR_RX|EP_CTR_TX)); \ + while( ( _GetENDPOINT(bEpNum) & EPRX_STAT ) != wState ) \ + { \ + _SetENDPOINT(bEpNum, (_wRegVal | EP_CTR_RX|EP_CTR_TX)); \ + } \ + } /* _SetEPRxStatus */ + +/******************************************************************************* +* Macro Name : SetEPRxTxStatus +* Description : sets the status for rx & tx (bits STAT_TX[1:0] & STAT_RX[1:0]) +* Input : bEpNum: Endpoint Number. +* wStaterx: new state. +* wStatetx: new state. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPRxTxStatus(bEpNum,wStaterx,wStatetx) {\ + register uint32_t _wRegVal_T, _wRegVal_R; \ + \ + _wRegVal_T = _GetENDPOINT(bEpNum) & EPTX_DTOGMASK; \ + _wRegVal_R = _GetENDPOINT(bEpNum) & EPRX_DTOGMASK; \ + /* toggle first bit ? */ \ + if((EPRX_DTOG1 & wStaterx)!= 0) \ + _wRegVal_R ^= EPRX_DTOG1; \ + /* toggle second bit ? */ \ + if((EPRX_DTOG2 & wStaterx)!= 0) \ + _wRegVal_R ^= EPRX_DTOG2; \ + /* toggle first bit ? */ \ + if((EPTX_DTOG1 & wStatetx)!= 0) \ + _wRegVal_T ^= EPTX_DTOG1; \ + /* toggle second bit ? */ \ + if((EPTX_DTOG2 & wStatetx)!= 0) \ + _wRegVal_T ^= EPTX_DTOG2; \ + _SetENDPOINT(bEpNum, _wRegVal_T |_wRegVal_R | EP_CTR_RX | EP_CTR_TX); \ + while( ( _GetENDPOINT(bEpNum) & EPTX_STAT ) != wStatetx ) \ + { \ + _SetENDPOINT(bEpNum, _wRegVal_T | EP_CTR_RX | EP_CTR_TX); \ + } \ + while( ( _GetENDPOINT(bEpNum) & EPRX_STAT ) != wStaterx ) \ + { \ + _SetENDPOINT(bEpNum, _wRegVal_R | EP_CTR_RX | EP_CTR_TX); \ + } \ + } /* _SetEPRxTxStatus */ + +/******************************************************************************* +* Macro Name : GetEPTxStatus / GetEPRxStatus +* Description : gets the status for tx/rx transfer (bits STAT_TX[1:0] +* /STAT_RX[1:0]) +* Input : bEpNum: Endpoint Number. +* Return : status . +*******************************************************************************/ +#define _GetEPTxStatus(bEpNum) ((uint16_t)_GetENDPOINT(bEpNum) & EPTX_STAT) + +#define _GetEPRxStatus(bEpNum) ((uint16_t)_GetENDPOINT(bEpNum) & EPRX_STAT) + +/******************************************************************************* +* Macro Name : SetEPTxValid / SetEPRxValid +* Description : sets directly the VALID tx/rx-status into the enpoint register +* Input : bEpNum: Endpoint Number. +* Return : None. +*******************************************************************************/ +#define _SetEPTxValid(bEpNum) (_SetEPTxStatus(bEpNum, EP_TX_VALID)) + +#define _SetEPRxValid(bEpNum) (_SetEPRxStatus(bEpNum, EP_RX_VALID)) + +/******************************************************************************* +* Macro Name : GetTxStallStatus / GetRxStallStatus. +* Description : checks stall condition in an endpoint. +* Input : bEpNum: Endpoint Number. +* Return : TRUE = endpoint in stall condition. +*******************************************************************************/ +#define _GetTxStallStatus(bEpNum) (_GetEPTxStatus(bEpNum) \ + == EP_TX_STALL) +#define _GetRxStallStatus(bEpNum) (_GetEPRxStatus(bEpNum) \ + == EP_RX_STALL) + +/******************************************************************************* +* Macro Name : SetEP_KIND / ClearEP_KIND. +* Description : set & clear EP_KIND bit. +* Input : bEpNum: Endpoint Number. +* Return : None. +*******************************************************************************/ +#define _SetEP_KIND(bEpNum) (_SetENDPOINT(bEpNum, \ + (EP_CTR_RX|EP_CTR_TX|((_GetENDPOINT(bEpNum) | EP_KIND) & EPREG_MASK)))) +#define _ClearEP_KIND(bEpNum) (_SetENDPOINT(bEpNum, \ + (EP_CTR_RX|EP_CTR_TX|(_GetENDPOINT(bEpNum) & EPKIND_MASK)))) + +/******************************************************************************* +* Macro Name : Set_Status_Out / Clear_Status_Out. +* Description : Sets/clears directly STATUS_OUT bit in the endpoint register. +* Input : bEpNum: Endpoint Number. +* Return : None. +*******************************************************************************/ +#define _Set_Status_Out(bEpNum) _SetEP_KIND(bEpNum) +#define _Clear_Status_Out(bEpNum) _ClearEP_KIND(bEpNum) + +/******************************************************************************* +* Macro Name : SetEPDoubleBuff / ClearEPDoubleBuff. +* Description : Sets/clears directly EP_KIND bit in the endpoint register. +* Input : bEpNum: Endpoint Number. +* Return : None. +*******************************************************************************/ +#define _SetEPDoubleBuff(bEpNum) _SetEP_KIND(bEpNum) +#define _ClearEPDoubleBuff(bEpNum) _ClearEP_KIND(bEpNum) + +/******************************************************************************* +* Macro Name : ClearEP_CTR_RX / ClearEP_CTR_TX. +* Description : Clears bit CTR_RX / CTR_TX in the endpoint register. +* Input : bEpNum: Endpoint Number. +* Return : None. +*******************************************************************************/ +#define _ClearEP_CTR_RX(bEpNum) (_SetENDPOINT(bEpNum,\ + _GetENDPOINT(bEpNum) & 0x7FFF & EPREG_MASK)) +#define _ClearEP_CTR_TX(bEpNum) (_SetENDPOINT(bEpNum,\ + _GetENDPOINT(bEpNum) & 0xFF7F & EPREG_MASK)) + +/******************************************************************************* +* Macro Name : ToggleDTOG_RX / ToggleDTOG_TX . +* Description : Toggles DTOG_RX / DTOG_TX bit in the endpoint register. +* Input : bEpNum: Endpoint Number. +* Return : None. +*******************************************************************************/ +#define _ToggleDTOG_RX(bEpNum) (_SetENDPOINT(bEpNum, \ + EP_CTR_RX|EP_CTR_TX|EP_DTOG_RX | (_GetENDPOINT(bEpNum) & EPREG_MASK))) +#define _ToggleDTOG_TX(bEpNum) (_SetENDPOINT(bEpNum, \ + EP_CTR_RX|EP_CTR_TX|EP_DTOG_TX | (_GetENDPOINT(bEpNum) & EPREG_MASK))) + +/******************************************************************************* +* Macro Name : ClearDTOG_RX / ClearDTOG_TX. +* Description : Clears DTOG_RX / DTOG_TX bit in the endpoint register. +* Input : bEpNum: Endpoint Number. +* Return : None. +*******************************************************************************/ +#define _ClearDTOG_RX(bEpNum) if((_GetENDPOINT(bEpNum) & EP_DTOG_RX) != 0)\ + _ToggleDTOG_RX(bEpNum) +#define _ClearDTOG_TX(bEpNum) if((_GetENDPOINT(bEpNum) & EP_DTOG_TX) != 0)\ + _ToggleDTOG_TX(bEpNum) +/******************************************************************************* +* Macro Name : SetEPAddress. +* Description : Sets address in an endpoint register. +* Input : bEpNum: Endpoint Number. +* bAddr: Address. +* Return : None. +*******************************************************************************/ +#define _SetEPAddress(bEpNum,bAddr) _SetENDPOINT(bEpNum,\ + EP_CTR_RX|EP_CTR_TX|(_GetENDPOINT(bEpNum) & EPREG_MASK) | bAddr) + +/******************************************************************************* +* Macro Name : GetEPAddress. +* Description : Gets address in an endpoint register. +* Input : bEpNum: Endpoint Number. +* Return : None. +*******************************************************************************/ +#define _GetEPAddress(bEpNum) ((uint8_t)(_GetENDPOINT(bEpNum) & EPADDR_FIELD)) + +#define _pEPTxAddr(bEpNum) ((uint32_t *)((_GetBTABLE()+bEpNum*8 )*2 + PMAAddr)) +#define _pEPTxCount(bEpNum) ((uint32_t *)((_GetBTABLE()+bEpNum*8+2)*2 + PMAAddr)) +#define _pEPRxAddr(bEpNum) ((uint32_t *)((_GetBTABLE()+bEpNum*8+4)*2 + PMAAddr)) +#define _pEPRxCount(bEpNum) ((uint32_t *)((_GetBTABLE()+bEpNum*8+6)*2 + PMAAddr)) + +/******************************************************************************* +* Macro Name : SetEPTxAddr / SetEPRxAddr. +* Description : sets address of the tx/rx buffer. +* Input : bEpNum: Endpoint Number. +* wAddr: address to be set (must be word aligned). +* Return : None. +*******************************************************************************/ +#define _SetEPTxAddr(bEpNum,wAddr) (*_pEPTxAddr(bEpNum) = ((wAddr >> 1) << 1)) +#define _SetEPRxAddr(bEpNum,wAddr) (*_pEPRxAddr(bEpNum) = ((wAddr >> 1) << 1)) + +/******************************************************************************* +* Macro Name : GetEPTxAddr / GetEPRxAddr. +* Description : Gets address of the tx/rx buffer. +* Input : bEpNum: Endpoint Number. +* Return : address of the buffer. +*******************************************************************************/ +#define _GetEPTxAddr(bEpNum) ((uint16_t)*_pEPTxAddr(bEpNum)) +#define _GetEPRxAddr(bEpNum) ((uint16_t)*_pEPRxAddr(bEpNum)) + +/******************************************************************************* +* Macro Name : SetEPCountRxReg. +* Description : Sets counter of rx buffer with no. of blocks. +* Input : pdwReg: pointer to counter. +* wCount: Counter. +* Return : None. +*******************************************************************************/ +#define _BlocksOf32(dwReg,wCount,wNBlocks) {\ + wNBlocks = wCount >> 5;\ + if((wCount & 0x1f) == 0)\ + wNBlocks--;\ + *pdwReg = (uint32_t)((wNBlocks << 10) | 0x8000);\ + }/* _BlocksOf32 */ + +#define _BlocksOf2(dwReg,wCount,wNBlocks) {\ + wNBlocks = wCount >> 1;\ + if((wCount & 0x1) != 0)\ + wNBlocks++;\ + *pdwReg = (uint32_t)(wNBlocks << 10);\ + }/* _BlocksOf2 */ + +#define _SetEPCountRxReg(dwReg,wCount) {\ + uint16_t wNBlocks;\ + if(wCount > 62){_BlocksOf32(dwReg,wCount,wNBlocks);}\ + else {_BlocksOf2(dwReg,wCount,wNBlocks);}\ + }/* _SetEPCountRxReg */ + +#define _GetNumBlock(wCount,wValue) {\ + uint16_t wNBlocks;\ + if(wCount > 62){\ + wNBlocks = wCount >> 5;\ + if((wCount & 0x1f) == 0) wNBlocks--;\ + wValue = (uint32_t)((wNBlocks << 10) | 0x8000);\ + }\ + else {wNBlocks = wCount >> 1;\ + if((wCount & 0x1) != 0) wNBlocks++;\ + wValue = (uint32_t)(wNBlocks << 10);\ + }\ +} + +#define _SetEPRxDblBuf0Count(bEpNum,wCount) {\ + uint32_t *pdwReg = _pEPTxCount(bEpNum); \ + _SetEPCountRxReg(pdwReg, wCount);\ + } + +/******************************************************************************* +* Macro Name : SetEPTxCount / SetEPRxCount. +* Description : sets counter for the tx/rx buffer. +* Input : bEpNum: endpoint number. +* wCount: Counter value. +* Return : None. +*******************************************************************************/ +#define _SetEPTxCount(bEpNum,wCount) (*_pEPTxCount(bEpNum) = wCount) +#define _SetEPRxCount(bEpNum,wCount) {\ + uint32_t *pdwReg = _pEPRxCount(bEpNum); \ + _SetEPCountRxReg(pdwReg, wCount);\ + if (bEpNum == ENDP0) \ + _GetNumBlock(Device_Property.MaxPacketSize,Ep0RxBlks);\ + } + +/******************************************************************************* +* Macro Name : GetEPTxCount / GetEPRxCount. +* Description : gets counter of the tx buffer. +* Input : bEpNum: endpoint number. +* Return : Counter value. +*******************************************************************************/ +#define _GetEPTxCount(bEpNum)((uint16_t)(*_pEPTxCount(bEpNum)) & 0x3ff) +#define _GetEPRxCount(bEpNum)((uint16_t)(*_pEPRxCount(bEpNum)) & 0x3ff) + +/******************************************************************************* +* Macro Name : SetEPDblBuf0Addr / SetEPDblBuf1Addr. +* Description : Sets buffer 0/1 address in a double buffer endpoint. +* Input : bEpNum: endpoint number. +* : wBuf0Addr: buffer 0 address. +* Output : None. +* Return : None. +*******************************************************************************/ +#define _SetEPDblBuf0Addr(bEpNum,wBuf0Addr) {_SetEPTxAddr(bEpNum, wBuf0Addr);} +#define _SetEPDblBuf1Addr(bEpNum,wBuf1Addr) {_SetEPRxAddr(bEpNum, wBuf1Addr);} + +/******************************************************************************* +* Macro Name : SetEPDblBuffAddr. +* Description : Sets addresses in a double buffer endpoint. +* Input : bEpNum: endpoint number. +* : wBuf0Addr: buffer 0 address. +* : wBuf1Addr = buffer 1 address. +* Return : None. +*******************************************************************************/ +#define _SetEPDblBuffAddr(bEpNum,wBuf0Addr,wBuf1Addr) { \ + _SetEPDblBuf0Addr(bEpNum, wBuf0Addr);\ + _SetEPDblBuf1Addr(bEpNum, wBuf1Addr);\ + } /* _SetEPDblBuffAddr */ + +/******************************************************************************* +* Macro Name : GetEPDblBuf0Addr / GetEPDblBuf1Addr. +* Description : Gets buffer 0/1 address of a double buffer endpoint. +* Input : bEpNum: endpoint number. +* Return : None. +*******************************************************************************/ +#define _GetEPDblBuf0Addr(bEpNum) (_GetEPTxAddr(bEpNum)) +#define _GetEPDblBuf1Addr(bEpNum) (_GetEPRxAddr(bEpNum)) + +/******************************************************************************* +* Macro Name : SetEPDblBuffCount / SetEPDblBuf0Count / SetEPDblBuf1Count. +* Description : Gets buffer 0/1 address of a double buffer endpoint. +* Input : bEpNum: endpoint number. +* : bDir: endpoint dir EP_DBUF_OUT = OUT +* EP_DBUF_IN = IN +* : wCount: Counter value +* Return : None. +*******************************************************************************/ +#define _SetEPDblBuf0Count(bEpNum, bDir, wCount) { \ + if(bDir == EP_DBUF_OUT)\ + /* OUT endpoint */ \ + {_SetEPRxDblBuf0Count(bEpNum,wCount);} \ + else if(bDir == EP_DBUF_IN)\ + /* IN endpoint */ \ + *_pEPTxCount(bEpNum) = (uint32_t)wCount; \ + } /* SetEPDblBuf0Count*/ + +#define _SetEPDblBuf1Count(bEpNum, bDir, wCount) { \ + if(bDir == EP_DBUF_OUT)\ + /* OUT endpoint */ \ + {_SetEPRxCount(bEpNum,wCount);}\ + else if(bDir == EP_DBUF_IN)\ + /* IN endpoint */\ + *_pEPRxCount(bEpNum) = (uint32_t)wCount; \ + } /* SetEPDblBuf1Count */ + +#define _SetEPDblBuffCount(bEpNum, bDir, wCount) {\ + _SetEPDblBuf0Count(bEpNum, bDir, wCount); \ + _SetEPDblBuf1Count(bEpNum, bDir, wCount); \ + } /* _SetEPDblBuffCount */ + +/******************************************************************************* +* Macro Name : GetEPDblBuf0Count / GetEPDblBuf1Count. +* Description : Gets buffer 0/1 rx/tx counter for double buffering. +* Input : bEpNum: endpoint number. +* Return : None. +*******************************************************************************/ +#define _GetEPDblBuf0Count(bEpNum) (_GetEPTxCount(bEpNum)) +#define _GetEPDblBuf1Count(bEpNum) (_GetEPRxCount(bEpNum)) + + +extern __IO uint16_t wIstr; /* ISTR register last read value */ + + +void SetCNTR(uint16_t /*wRegValue*/); +void SetISTR(uint16_t /*wRegValue*/); +void SetDADDR(uint16_t /*wRegValue*/); +void SetBTABLE(uint16_t /*wRegValue*/); +void SetBTABLE(uint16_t /*wRegValue*/); +uint16_t GetCNTR(void); +uint16_t GetISTR(void); +uint16_t GetFNR(void); +uint16_t GetDADDR(void); +uint16_t GetBTABLE(void); +void SetENDPOINT(uint8_t /*bEpNum*/, uint16_t /*wRegValue*/); +uint16_t GetENDPOINT(uint8_t /*bEpNum*/); +void SetEPType(uint8_t /*bEpNum*/, uint16_t /*wType*/); +uint16_t GetEPType(uint8_t /*bEpNum*/); +void SetEPTxStatus(uint8_t /*bEpNum*/, uint16_t /*wState*/); +void SetEPRxStatus(uint8_t /*bEpNum*/, uint16_t /*wState*/); +void SetDouBleBuffEPStall(uint8_t /*bEpNum*/, uint8_t bDir); +uint16_t GetEPTxStatus(uint8_t /*bEpNum*/); +uint16_t GetEPRxStatus(uint8_t /*bEpNum*/); +void SetEPTxValid(uint8_t /*bEpNum*/); +void SetEPRxValid(uint8_t /*bEpNum*/); +uint16_t GetTxStallStatus(uint8_t /*bEpNum*/); +uint16_t GetRxStallStatus(uint8_t /*bEpNum*/); +void SetEP_KIND(uint8_t /*bEpNum*/); +void ClearEP_KIND(uint8_t /*bEpNum*/); +void Set_Status_Out(uint8_t /*bEpNum*/); +void Clear_Status_Out(uint8_t /*bEpNum*/); +void SetEPDoubleBuff(uint8_t /*bEpNum*/); +void ClearEPDoubleBuff(uint8_t /*bEpNum*/); +void ClearEP_CTR_RX(uint8_t /*bEpNum*/); +void ClearEP_CTR_TX(uint8_t /*bEpNum*/); +void ToggleDTOG_RX(uint8_t /*bEpNum*/); +void ToggleDTOG_TX(uint8_t /*bEpNum*/); +void ClearDTOG_RX(uint8_t /*bEpNum*/); +void ClearDTOG_TX(uint8_t /*bEpNum*/); +void SetEPAddress(uint8_t /*bEpNum*/, uint8_t /*bAddr*/); +uint8_t GetEPAddress(uint8_t /*bEpNum*/); +void SetEPTxAddr(uint8_t /*bEpNum*/, uint16_t /*wAddr*/); +void SetEPRxAddr(uint8_t /*bEpNum*/, uint16_t /*wAddr*/); +uint16_t GetEPTxAddr(uint8_t /*bEpNum*/); +uint16_t GetEPRxAddr(uint8_t /*bEpNum*/); +void SetEPCountRxReg(uint32_t * /*pdwReg*/, uint16_t /*wCount*/); +void SetEPTxCount(uint8_t /*bEpNum*/, uint16_t /*wCount*/); +void SetEPRxCount(uint8_t /*bEpNum*/, uint16_t /*wCount*/); +uint16_t GetEPTxCount(uint8_t /*bEpNum*/); +uint16_t GetEPRxCount(uint8_t /*bEpNum*/); +void SetEPDblBuf0Addr(uint8_t /*bEpNum*/, uint16_t /*wBuf0Addr*/); +void SetEPDblBuf1Addr(uint8_t /*bEpNum*/, uint16_t /*wBuf1Addr*/); +void SetEPDblBuffAddr(uint8_t /*bEpNum*/, uint16_t /*wBuf0Addr*/, uint16_t /*wBuf1Addr*/); +uint16_t GetEPDblBuf0Addr(uint8_t /*bEpNum*/); +uint16_t GetEPDblBuf1Addr(uint8_t /*bEpNum*/); +void SetEPDblBuffCount(uint8_t /*bEpNum*/, uint8_t /*bDir*/, uint16_t /*wCount*/); +void SetEPDblBuf0Count(uint8_t /*bEpNum*/, uint8_t /*bDir*/, uint16_t /*wCount*/); +void SetEPDblBuf1Count(uint8_t /*bEpNum*/, uint8_t /*bDir*/, uint16_t /*wCount*/); +uint16_t GetEPDblBuf0Count(uint8_t /*bEpNum*/); +uint16_t GetEPDblBuf1Count(uint8_t /*bEpNum*/); +EP_DBUF_DIR GetEPDblBufDir(uint8_t /*bEpNum*/); +void FreeUserBuffer(uint8_t bEpNum/*bEpNum*/, uint8_t bDir); +uint16_t ToWord(uint8_t, uint8_t); +uint16_t ByteSwap(uint16_t); + +#ifdef __cplusplus +} + +#endif + +#endif /* __USB_REGS_H */ + + + + + + + + + + diff --git a/V203F6P6/ch32v203/usbd/inc/usb_sil.h b/V203F6P6/ch32v203/usbd/inc/usb_sil.h new file mode 100644 index 0000000..b3fea6a --- /dev/null +++ b/V203F6P6/ch32v203/usbd/inc/usb_sil.h @@ -0,0 +1,36 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_sil.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : This file contains all the functions prototypes for the + * USB Simplified Interface Layer 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 __USB_SIL_H +#define __USB_SIL_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v20x.h" + +uint32_t USB_SIL_Init(void); +uint32_t USB_SIL_Write(uint8_t bEpAddr, uint8_t* pBufferPointer, uint32_t wBufferSize); +uint32_t USB_SIL_Read(uint8_t bEpAddr, uint8_t* pBufferPointer); + +#ifdef __cplusplus +} + +#endif + +#endif /* __USB_SIL_H */ + + + + + diff --git a/V203F6P6/ch32v203/usbd/inc/usb_type.h b/V203F6P6/ch32v203/usbd/inc/usb_type.h new file mode 100644 index 0000000..c47c476 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/inc/usb_type.h @@ -0,0 +1,33 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_type.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : This file contains all the functions prototypes for the + * USB types 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 __USB_TYPE_H +#define __USB_TYPE_H +//#include "debug.h" +#include "usb_conf.h" + +#ifndef __cplusplus +#ifndef NULL +#define NULL ((void *)0) +#endif +typedef enum +{ + FALSE = 0, TRUE = !FALSE +} +bool; +#endif // __cplusplus +#endif /* __USB_TYPE_H */ + + + + + diff --git a/V203F6P6/ch32v203/usbd/libusbd.a b/V203F6P6/ch32v203/usbd/libusbd.a new file mode 100644 index 0000000..13bf901 Binary files /dev/null and b/V203F6P6/ch32v203/usbd/libusbd.a differ diff --git a/V203F6P6/ch32v203/usbd/src/cdc_class.cpp b/V203F6P6/ch32v203/usbd/src/cdc_class.cpp new file mode 100644 index 0000000..b5f3f31 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/src/cdc_class.cpp @@ -0,0 +1,46 @@ +#include "core_riscv.h" +#include "usb_regs.h" +#include "usb_mem.h" +#include "usb_sil.h" +#include "usb_prop.h" +#include "cdc_class.h" + +cdc_class * cdc_instance = nullptr; + +typedef __SIZE_TYPE__ size_t; +extern "C" { + extern void DeviceInit (); + extern void *memcpy (void *dest, const void *src, size_t n); +}; +cdc_class::cdc_class () : BaseLayer(), ctrli(nullptr), ep3Busy(false), Ready(false) { + cdc_instance = this; +} + +void cdc_class::init() { + DeviceInit (); +} +void cdc_class::ep2outHandler() { + const unsigned len = GetEPRxCount( EP2_OUT & 0x7F ); + PMAToUserBufferCopy( rxbuffer, GetEPRxAddr( EP2_OUT & 0x7F ), len ); + Up((char*)rxbuffer, len); + SetEPRxValid( ENDP2 ); +} +void cdc_class::ep3inHandler() { + ep3Busy = false; +} +uint32_t cdc_class::Down(const char * data, const uint32_t len) { + if ( ep3Busy ) return 0u; + if ( !Ready ) return 0u; + ep3Busy = true; + USB_SIL_Write( EP3_IN, (unsigned char*) data, len ); + SetEPTxStatus( ENDP3, EP_TX_VALID ); + return len; +} +void cdc_class::ctrl(const CTRL_TYPES_DEF type, const void * data, const uint32_t len) { + if (type == USB_USART_SET_DTR_RTS) { + const uint16_t cmd = * reinterpret_cast(data); + Ready = cmd & 1u; + } + if (! ctrli) return; + ctrli->IOCtrl (type, data, len); +} diff --git a/V203F6P6/ch32v203/usbd/src/hw_config.cpp b/V203F6P6/ch32v203/usbd/src/hw_config.cpp new file mode 100644 index 0000000..d12f298 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/src/hw_config.cpp @@ -0,0 +1,132 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : hw_config.c + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : USB configuration file. +********************************************************************************* +* 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_lib.h" +//#include "usb_prop.h" +//#include "usb_desc.h" +#include "system.h" +extern "C" { +#include "usb_istr.h" +#include "hw_config.h" +#include "usb_core.h" +#include "usb_pwr.h" +#include "usb_regs.h" +}; +#define printf(...) + +extern "C" { +[[gnu::interrupt]] extern void USB_LP_CAN1_RX0_IRQHandler(); +}; +void USB_LP_CAN1_RX0_IRQHandler() { + USB_Istr(); +} +/* USB_Device_clock_source */ +enum RCC_USB_CLK_SRC : uint32_t { + RCC_USBCLKSource_PLLCLK_Div1 = 0u, + RCC_USBCLKSource_PLLCLK_Div2, + RCC_USBCLKSource_PLLCLK_Div3, +}; +static void RCC_USBCLKConfig(const RCC_USB_CLK_SRC RCC_USBCLKSource) { + RCC.CFGR0.B.USBPRE = RCC_USBCLKSource; +} +extern "C" uint32_t SystemCoreClock; +/********************************************************************* + * @fn USBFS_RCC_Init + * + * @brief Initializes the usbfs clock configuration. + * + * @return none + */ +static void USBFS_RCC_Init( void ) { + if( SystemCoreClock == 144'000'000 ) { + RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div3 ); + } else if( SystemCoreClock == 96'000'000 ) { + RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div2 ); + } else if( SystemCoreClock == 48'000'000 ) { + RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div1 ); + } + RCC.APB1PCENR.B.USBDEN = SET; +} +extern "C" void USB_Init(); + +void DeviceInit() { + delay_init(); + USBFS_RCC_Init(); + USB_Init (); + NVIC.EnableIRQ(USB_LP_CAN1_RX0_IRQn); +} + +/******************************************************************************* + * @fn Enter_LowPowerMode + * + * @brief Enter low power mode. + * + * @return None + */ +void Enter_LowPowerMode(void) +{ + printf("usb enter low power mode\r\n"); + bDeviceState=SUSPENDED; +} + +/******************************************************************************* + * @fn Leave_LowPowerMode + * + * @brief Leave low power mode. + * + * @return None + */ +void Leave_LowPowerMode(void) +{ + DEVICE_INFO *pInfo=&Device_Info; + printf("usb leave low power mode\r\n"); + if (pInfo->Current_Configuration!=0)bDeviceState=CONFIGURED; + else bDeviceState = ATTACHED; +} +/******************************************************************************* + * @fn USB_Port_Set + * + * @brief Set USB IO port. + * + * @param NewState: DISABLE or ENABLE. + * Pin_In_IPU: Enables or Disables intenal pull-up resistance. + * + * @return None + */ +void USB_Port_Set(FunctionalState NewState, FunctionalState Pin_In_IPU) +{ + RCC.APB2PCENR.B.IOPAEN = SET; + + if(NewState) { + _SetCNTR(_GetCNTR()&(~(1<<1))); + GPIOA.CFGHR.R &= 0XFFF00FFF; + GPIOA.OUTDR.R &= ~(3<<11); //PA11/12=0 + GPIOA.CFGHR.R |= 0X00044000; //float + } + else + { + _SetCNTR(_GetCNTR()|(1<<1)); + GPIOA.CFGHR.R &= 0XFFF00FFF; + GPIOA.OUTDR.R &= ~(3<<11); //PA11/12=0 + GPIOA.CFGHR.R |= 0X00033000; // LOW + } + + if(Pin_In_IPU) EXTEND.EXTEND_CTR.B.USBDPU = SET; + else EXTEND.EXTEND_CTR.B.USBDPU = RESET; +} + + + + + + + + diff --git a/V203F6P6/ch32v203/usbd/src/usb_core.c b/V203F6P6/ch32v203/usbd/src/usb_core.c new file mode 100644 index 0000000..3bc5bcc --- /dev/null +++ b/V203F6P6/ch32v203/usbd/src/usb_core.c @@ -0,0 +1,954 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_core.c + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : Standard protocol processing (USB v2.0) +********************************************************************************* +* 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_lib.h" + +/* Global define */ +#define ValBit(VAR,Place) (VAR & (1 << Place)) +#define SetBit(VAR,Place) (VAR |= (1 << Place)) +#define ClrBit(VAR,Place) (VAR &= ((1 << Place) ^ 255)) +#define Send0LengthData() { _SetEPTxCount(ENDP0, 0); \ + vSetEPTxStatus(EP_TX_VALID); \ + } + +#define vSetEPRxStatus(st) (SaveRState = st) +#define vSetEPTxStatus(st) (SaveTState = st) + +#define USB_StatusIn() Send0LengthData() +#define USB_StatusOut() vSetEPRxStatus(EP_RX_VALID) + +#define StatusInfo0 StatusInfo.bw.bb1 +#define StatusInfo1 StatusInfo.bw.bb0 + +uint16_t_uint8_t StatusInfo; + +bool Data_Mul_MaxPacketSize = FALSE; + +static void DataStageOut(void); +static void DataStageIn(void); +static void NoData_Setup0(void); +static void Data_Setup0(void); + +/********************************************************************* + * @fn Standard_GetConfiguration + * + * @brief Return the current configuration variable address. + * + * @param Length - How many bytes are needed. + * + * @return Return 1 - if the request is invalid when "Length" is 0. + * Return "Buffer" if the "Length" is not 0. + */ +uint8_t *Standard_GetConfiguration(uint16_t Length) +{ + if (Length == 0) + { + pInformation->Ctrl_Info.Usb_wLength = sizeof(pInformation->Current_Configuration); + return 0; + } + pUser_Standard_Requests->User_GetConfiguration(); + + return (uint8_t *)&pInformation->Current_Configuration; +} + +/********************************************************************* + * @fn Standard_SetConfiguration + * + * @brief This routine is called to set the configuration value + * Then each class should configure device itself. + * + * @param None. + * + * @return Return USB_SUCCESS - if the request is performed. + * Return USB_UNSUPPORT - if the request is invalid. + */ +RESULT Standard_SetConfiguration(void) +{ + if ((pInformation->USBwValue0 <= + Device_Table.Total_Configuration) && (pInformation->USBwValue1 == 0) + && (pInformation->USBwIndex == 0)) + { + pInformation->Current_Configuration = pInformation->USBwValue0; + pUser_Standard_Requests->User_SetConfiguration(); + return USB_SUCCESS; + } + else + { + return USB_UNSUPPORT; + } +} + +/********************************************************************* + * @fn Standard_GetInterface + * + * @brief Return the Alternate Setting of the current interface. + * + * @param Length - How many bytes are needed. + * + * @return Return 0 - if the request is invalid when "Length" is 0. + * Return "Buffer" if the "Length" is not 0. + */ +uint8_t *Standard_GetInterface(uint16_t Length) +{ + if (Length == 0) + { + pInformation->Ctrl_Info.Usb_wLength = sizeof(pInformation->Current_AlternateSetting); + return 0; + } + pUser_Standard_Requests->User_GetInterface(); + + return (uint8_t *)&pInformation->Current_AlternateSetting; +} + +/********************************************************************* + * @fn Standard_SetInterface + * + * @brief This routine is called to set the interface. + * Then each class should configure the interface them self. + * + * @param None + * + * @return Return USB_SUCCESS - if the request is performed. + * Return USB_UNSUPPORT - if the request is invalid. + */ +RESULT Standard_SetInterface(void) +{ + RESULT Re; + Re = (*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, pInformation->USBwValue0); + + if (pInformation->Current_Configuration != 0) + { + if ((Re != USB_SUCCESS) || (pInformation->USBwIndex1 != 0) + || (pInformation->USBwValue1 != 0)) + { + return USB_UNSUPPORT; + } + else if (Re == USB_SUCCESS) + { + pUser_Standard_Requests->User_SetInterface(); + pInformation->Current_Interface = pInformation->USBwIndex0; + pInformation->Current_AlternateSetting = pInformation->USBwValue0; + return USB_SUCCESS; + } + } + + return USB_UNSUPPORT; +} + +/********************************************************************* + * @fn Standard_GetStatus + * + * @brief Copy the device request data to "StatusInfo buffer". + * + * @param Length - How many bytes are needed. + * + * @return Return 0 - if the request is at end of data block, + * or is invalid when "Length" is 0. + */ +uint8_t *Standard_GetStatus(uint16_t Length) +{ + if (Length == 0) + { + pInformation->Ctrl_Info.Usb_wLength = 2; + return 0; + } + StatusInfo.w = 0; + + if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { + uint8_t Feature = pInformation->Current_Feature; + + if (ValBit(Feature, 5)) + { + SetBit(StatusInfo0, 1); + } + else + { + ClrBit(StatusInfo0, 1); + } + if (ValBit(Feature, 6)) + { + SetBit(StatusInfo0, 0); + } + else + { + ClrBit(StatusInfo0, 0); + } + } + else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) + { + return (uint8_t *)&StatusInfo; + } + else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) + { + uint8_t Related_Endpoint; + uint8_t wIndex0 = pInformation->USBwIndex0; + + Related_Endpoint = (wIndex0 & 0x0f); + if (ValBit(wIndex0, 7)) + { + if (_GetTxStallStatus(Related_Endpoint)) + { + SetBit(StatusInfo0, 0); + } + } + else + { + if (_GetRxStallStatus(Related_Endpoint)) + { + SetBit(StatusInfo0, 0); + } + } + + } + else + { + return NULL; + } + pUser_Standard_Requests->User_GetStatus(); + + return (uint8_t *)&StatusInfo; +} + +/********************************************************************* + * @fn Standard_ClearFeature + * + * @brief Clear or disable a specific feature. + * + * @return Return USB_SUCCESS - if the request is performed. + * Return USB_UNSUPPORT - if the request is invalid. + */ +RESULT Standard_ClearFeature(void) +{ + uint32_t Type_Rec = Type_Recipient; + uint32_t Status; + + if (Type_Rec == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { + ClrBit(pInformation->Current_Feature, 5); + return USB_SUCCESS; + } + else if (Type_Rec == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) + { + DEVICE* pDev; + uint32_t Related_Endpoint; + uint32_t wIndex0; + uint32_t rEP; + + if ((pInformation->USBwValue != ENDPOINT_STALL) + || (pInformation->USBwIndex1 != 0)) + { + return USB_UNSUPPORT; + } + + pDev = &Device_Table; + wIndex0 = pInformation->USBwIndex0; + rEP = wIndex0 & ~0x80; + Related_Endpoint = ENDP0 + rEP; + + if (ValBit(pInformation->USBwIndex0, 7)) + { + Status = _GetEPTxStatus(Related_Endpoint); + } + else + { + Status = _GetEPRxStatus(Related_Endpoint); + } + + if ((rEP >= pDev->Total_Endpoint) || (Status == 0) + || (pInformation->Current_Configuration == 0)) + { + return USB_UNSUPPORT; + } + + if (wIndex0 & 0x80) + { + if (_GetTxStallStatus(Related_Endpoint )) + { + ClearDTOG_TX(Related_Endpoint); + SetEPTxStatus(Related_Endpoint, EP_TX_VALID); + } + } + else + { + if (_GetRxStallStatus(Related_Endpoint)) + { + if (Related_Endpoint == ENDP0) + { + SetEPRxCount(Related_Endpoint, Device_Property.MaxPacketSize); + _SetEPRxStatus(Related_Endpoint, EP_RX_VALID); + } + else + { + ClearDTOG_RX(Related_Endpoint); + _SetEPRxStatus(Related_Endpoint, EP_RX_VALID); + } + } + } + pUser_Standard_Requests->User_ClearFeature(); + return USB_SUCCESS; + } + + return USB_UNSUPPORT; +} + +/********************************************************************* + * @fn Standard_SetEndPointFeature + * + * @brief Set or enable a specific feature of EndPoint + * + * @return Return USB_SUCCESS - if the request is performed. + * Return USB_UNSUPPORT - if the request is invalid. + */ +RESULT Standard_SetEndPointFeature(void) +{ + uint32_t wIndex0; + uint32_t Related_Endpoint; + uint32_t rEP; + uint32_t Status; + + wIndex0 = pInformation->USBwIndex0; + rEP = wIndex0 & ~0x80; + Related_Endpoint = ENDP0 + rEP; + + if (ValBit(pInformation->USBwIndex0, 7)) + { + Status = _GetEPTxStatus(Related_Endpoint); + } + else + { + Status = _GetEPRxStatus(Related_Endpoint); + } + + if (Related_Endpoint >= Device_Table.Total_Endpoint + || pInformation->USBwValue != 0 || Status == 0 + || pInformation->Current_Configuration == 0) + { + return USB_UNSUPPORT; + } + else + { + if (wIndex0 & 0x80) + { + _SetEPTxStatus(Related_Endpoint, EP_TX_STALL); + } + else + { + _SetEPRxStatus(Related_Endpoint, EP_RX_STALL); + } + } + pUser_Standard_Requests->User_SetEndPointFeature(); + + return USB_SUCCESS; +} + +/********************************************************************* + * @fn Standard_SetDeviceFeature + * + * @brief Set or enable a specific feature of Device. + * + * @return Return USB_SUCCESS - if the request is performed. + * Return USB_UNSUPPORT - if the request is invalid. + */ +RESULT Standard_SetDeviceFeature(void) +{ + SetBit(pInformation->Current_Feature, 5); + pUser_Standard_Requests->User_SetDeviceFeature(); + + return USB_SUCCESS; +} + +/********************************************************************* + * @fn Standard_GetDescriptorData + * + * @brief This routine is used for the descriptors resident in Flash + * or RAM pDesc can be in either Flash or RAM + * The purpose of this routine is to have a versatile way to + * response descriptors request. It allows user to generate + * certain descriptors with software or read descriptors from + * external storage part by part. + * + * @param Length - Length of the data in this transfer. + * pDesc - A pointer points to descriptor struct. + * The structure gives the initial address of the descriptor and + * its original size. + * + * @return Address of a part of the descriptor pointed by the Usb_ + * wOffset The buffer pointed by this address contains at least + * Length bytes. + */ +uint8_t *Standard_GetDescriptorData(uint16_t Length, ONE_DESCRIPTOR *pDesc) +{ + uint32_t wOffset; + + wOffset = pInformation->Ctrl_Info.Usb_wOffset; + + if (Length == 0) + { + pInformation->Ctrl_Info.Usb_wLength = pDesc->Descriptor_Size - wOffset; + return 0; + } + + return pDesc->Descriptor + wOffset; +} + +/********************************************************************* + * @fn DataStageOut + * + * @brief Data stage of a Control Write Transfer. + * + * @return none + */ +void DataStageOut(void) +{ + ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info; + uint32_t save_rLength; + + save_rLength = pEPinfo->Usb_rLength; + + if (pEPinfo->CopyData && save_rLength) + { + uint8_t *Buffer; + uint32_t Length; + + Length = pEPinfo->PacketSize; + + if (Length > save_rLength) + { + Length = save_rLength; + } + + Buffer = (*pEPinfo->CopyData)(Length); + pEPinfo->Usb_rLength -= Length; + pEPinfo->Usb_rOffset += Length; + PMAToUserBufferCopy(Buffer, GetEPRxAddr(ENDP0), Length); + } + + if (pEPinfo->Usb_rLength != 0) + { + vSetEPRxStatus(EP_RX_VALID); + SetEPTxCount(ENDP0, 0); + vSetEPTxStatus(EP_TX_VALID); + } + + if (pEPinfo->Usb_rLength >= pEPinfo->PacketSize) + { + pInformation->ControlState = OUT_DATA; + } + else + { + if (pEPinfo->Usb_rLength > 0) + { + pInformation->ControlState = LAST_OUT_DATA; + } + else if (pEPinfo->Usb_rLength == 0) + { + pInformation->ControlState = WAIT_STATUS_IN; + USB_StatusIn(); + } + } +} + +/********************************************************************* + * @fn DataStageIn + * + * @brief Data stage of a Control Read Transfer. + * + * @return none + */ +void DataStageIn(void) +{ + ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info; + uint32_t save_wLength = pEPinfo->Usb_wLength; + uint32_t ControlState = pInformation->ControlState; + + uint8_t *DataBuffer; + uint32_t Length; + + if ((save_wLength == 0) && (ControlState == LAST_IN_DATA)) + { + if(Data_Mul_MaxPacketSize == TRUE) + { + Send0LengthData(); + ControlState = LAST_IN_DATA; + Data_Mul_MaxPacketSize = FALSE; + } + else + { + ControlState = WAIT_STATUS_OUT; + vSetEPTxStatus(EP_TX_STALL); + + } + + goto Expect_Status_Out; + } + + Length = pEPinfo->PacketSize; + ControlState = (save_wLength <= Length) ? LAST_IN_DATA : IN_DATA; + + if (Length > save_wLength) + { + Length = save_wLength; + } + + DataBuffer = (*pEPinfo->CopyData)(Length); + + UserToPMABufferCopy(DataBuffer, GetEPTxAddr(ENDP0), Length); + + SetEPTxCount(ENDP0, Length); + + pEPinfo->Usb_wLength -= Length; + pEPinfo->Usb_wOffset += Length; + vSetEPTxStatus(EP_TX_VALID); + + USB_StatusOut(); + +Expect_Status_Out: + pInformation->ControlState = ControlState; +} + +/********************************************************************* + * @fn NoData_Setup0 + * + * @brief Proceed the processing of setup request without data stage. + * + * @return none + */ +void NoData_Setup0(void) +{ + RESULT Result = USB_UNSUPPORT; + uint32_t RequestNo = pInformation->USBbRequest; + uint32_t ControlState; + + if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { + if (RequestNo == SET_CONFIGURATION) + { + Result = Standard_SetConfiguration(); + } + else if (RequestNo == SET_ADDRESS) + { + if ((pInformation->USBwValue0 > 127) || (pInformation->USBwValue1 != 0) + || (pInformation->USBwIndex != 0) + || (pInformation->Current_Configuration != 0)) + { + ControlState = STALLED; + goto exit_NoData_Setup0; + } + else + { + Result = USB_SUCCESS; + } + } + else if (RequestNo == SET_FEATURE) + { + if ((pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP) \ + && (pInformation->USBwIndex == 0)) + { + Result = Standard_SetDeviceFeature(); + } + else + { + Result = USB_UNSUPPORT; + } + } + else if (RequestNo == CLEAR_FEATURE) + { + if (pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP + && pInformation->USBwIndex == 0 + && ValBit(pInformation->Current_Feature, 5)) + { + Result = Standard_ClearFeature(); + } + else + { + Result = USB_UNSUPPORT; + } + } + + } + else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) + { + if (RequestNo == SET_INTERFACE) + { + Result = Standard_SetInterface(); + } + } + + else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) + { + if (RequestNo == CLEAR_FEATURE) + { + Result = Standard_ClearFeature(); + } + else if (RequestNo == SET_FEATURE) + { + Result = Standard_SetEndPointFeature(); + } + } + else + { + Result = USB_UNSUPPORT; + } + + if (Result != USB_SUCCESS) + { + Result = (*pProperty->Class_NoData_Setup)(RequestNo); + if (Result == USB_NOT_READY) + { + ControlState = PAUSE; + goto exit_NoData_Setup0; + } + } + + if (Result != USB_SUCCESS) + { + ControlState = STALLED; + goto exit_NoData_Setup0; + } + + ControlState = WAIT_STATUS_IN; + + USB_StatusIn(); + +exit_NoData_Setup0: + pInformation->ControlState = ControlState; + return; +} + +/********************************************************************* + * @fn Data_Setup0 + * + * @brief Proceed the processing of setup request with data stage. + * + * @return none + */ +void Data_Setup0(void) +{ + uint8_t *(*CopyRoutine)(uint16_t); + RESULT Result; + uint32_t Request_No = pInformation->USBbRequest; + uint32_t Related_Endpoint, Reserved; + uint32_t wOffset, Status; + + CopyRoutine = NULL; + wOffset = 0; + + if (Request_No == GET_DESCRIPTOR) + { + if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { + uint8_t wValue1 = pInformation->USBwValue1; + if (wValue1 == DEVICE_DESCRIPTOR) + { + CopyRoutine = pProperty->GetDeviceDescriptor; + } + else if (wValue1 == CONFIG_DESCRIPTOR) + { + CopyRoutine = pProperty->GetConfigDescriptor; + } + else if (wValue1 == STRING_DESCRIPTOR) + { + CopyRoutine = pProperty->GetStringDescriptor; + } + } + } + else if ((Request_No == GET_STATUS) && (pInformation->USBwValue == 0) + && (pInformation->USBwLength == 0x0002) + && (pInformation->USBwIndex1 == 0)) + { + + if ((Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + && (pInformation->USBwIndex == 0)) + { + CopyRoutine = Standard_GetStatus; + } + else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) + { + if (((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == USB_SUCCESS) + && (pInformation->Current_Configuration != 0)) + { + CopyRoutine = Standard_GetStatus; + } + } + else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT)) + { + Related_Endpoint = (pInformation->USBwIndex0 & 0x0f); + Reserved = pInformation->USBwIndex0 & 0x70; + + if (ValBit(pInformation->USBwIndex0, 7)) + { + Status = _GetEPTxStatus(Related_Endpoint); + } + else + { + Status = _GetEPRxStatus(Related_Endpoint); + } + + if ((Related_Endpoint < Device_Table.Total_Endpoint) && (Reserved == 0) + && (Status != 0)) + { + CopyRoutine = Standard_GetStatus; + } + } + + } + else if (Request_No == GET_CONFIGURATION) + { + if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)) + { + CopyRoutine = Standard_GetConfiguration; + } + } + else if (Request_No == GET_INTERFACE) + { + if ((Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) + && (pInformation->Current_Configuration != 0) && (pInformation->USBwValue == 0) + && (pInformation->USBwIndex1 == 0) && (pInformation->USBwLength == 0x0001) + && ((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == USB_SUCCESS)) + { + CopyRoutine = Standard_GetInterface; + } + + } + + if (CopyRoutine) + { + pInformation->Ctrl_Info.Usb_wOffset = wOffset; + pInformation->Ctrl_Info.CopyData = CopyRoutine; + (*CopyRoutine)(0); + Result = USB_SUCCESS; + } + else + { + Result = (*pProperty->Class_Data_Setup)(pInformation->USBbRequest); + + if (Result == USB_NOT_READY) + { + pInformation->ControlState = PAUSE; + return; + } + } + + if (pInformation->Ctrl_Info.Usb_wLength == 0xFFFF) + { + pInformation->ControlState = PAUSE; + return; + } + + if ((Result == USB_UNSUPPORT) || (pInformation->Ctrl_Info.Usb_wLength == 0)) + { + pInformation->ControlState = STALLED; + return; + } + + if (ValBit(pInformation->USBbmRequestType, 7)) + { + __IO uint32_t wLength = pInformation->USBwLength; + if (pInformation->Ctrl_Info.Usb_wLength > wLength) + { + pInformation->Ctrl_Info.Usb_wLength = wLength; + } + else if (pInformation->Ctrl_Info.Usb_wLength < pInformation->USBwLength) + { + if (pInformation->Ctrl_Info.Usb_wLength < pProperty->MaxPacketSize) + { + Data_Mul_MaxPacketSize = FALSE; + } + else if ((pInformation->Ctrl_Info.Usb_wLength % pProperty->MaxPacketSize) == 0) + { + Data_Mul_MaxPacketSize = TRUE; + } + } + + pInformation->Ctrl_Info.PacketSize = pProperty->MaxPacketSize; + DataStageIn(); + } + else + { + pInformation->ControlState = OUT_DATA; + vSetEPRxStatus(EP_RX_VALID); + } + + return; +} + +/********************************************************************* + * @fn Setup0_Process + * + * @brief Get the device request data and dispatch to individual process. + * + * @return Post0_Process. + */ +uint8_t Setup0_Process(void) +{ + union + { + uint8_t* b; + uint16_t* w; + } pBuf; + uint16_t offset = 1; + + pBuf.b = PMAAddr + (uint8_t *)(_GetEPRxAddr(ENDP0) * 2); /* *2 for 32 bits addr */ + + if (pInformation->ControlState != PAUSE) + { + pInformation->USBbmRequestType = *pBuf.b++; /* bmRequestType */ + pInformation->USBbRequest = *pBuf.b++; /* bRequest */ + pBuf.w += offset; /* word not accessed because of 32 bits addressing */ + pInformation->USBwValue = ByteSwap(*pBuf.w++); /* wValue */ + pBuf.w += offset; /* word not accessed because of 32 bits addressing */ + pInformation->USBwIndex = ByteSwap(*pBuf.w++); /* wIndex */ + pBuf.w += offset; /* word not accessed because of 32 bits addressing */ + pInformation->USBwLength = *pBuf.w; /* wLength */ + } + pInformation->ControlState = SETTING_UP; + + if (pInformation->USBwLength == 0) + { + NoData_Setup0(); + } + else + { + Data_Setup0(); + } + return Post0_Process(); +} + +/********************************************************************* + * @fn In0_Process + * + * @brief Process the IN token on all default endpoint. + * + * @return none + */ +uint8_t In0_Process(void) +{ + uint32_t ControlState = pInformation->ControlState; + + if ((ControlState == IN_DATA) || (ControlState == LAST_IN_DATA)) + { + DataStageIn(); + ControlState = pInformation->ControlState; + } + else if (ControlState == WAIT_STATUS_IN) + { + if ((pInformation->USBbRequest == SET_ADDRESS) && + (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))) + { + SetDeviceAddress(pInformation->USBwValue0); + pUser_Standard_Requests->User_SetDeviceAddress(); + } + (*pProperty->Process_Status_IN)(); + ControlState = STALLED; + } + else + { + ControlState = STALLED; + } + + pInformation->ControlState = ControlState; + + return Post0_Process(); +} + +/********************************************************************* + * @fn Out0_Process + * + * @brief Process the OUT token on all default endpoint. + * + * @return none + */ +uint8_t Out0_Process(void) +{ + uint32_t ControlState = pInformation->ControlState; + + if ((ControlState == IN_DATA) || (ControlState == LAST_IN_DATA)) + { + ControlState = STALLED; + } + else if ((ControlState == OUT_DATA) || (ControlState == LAST_OUT_DATA)) + { + DataStageOut(); + ControlState = pInformation->ControlState; + } + else if (ControlState == WAIT_STATUS_OUT) + { + (*pProperty->Process_Status_OUT)(); + ControlState = STALLED; + } + else + { + ControlState = STALLED; + } + + pInformation->ControlState = ControlState; + + return Post0_Process(); +} + +/********************************************************************* + * @fn Post0_Process + * + * @brief Stall the Endpoint 0 in case of error. + * + * @return 0 - if the control State is in PAUSE + * 1 - if not. + */ +uint8_t Post0_Process(void) +{ + SetEPRxCount(ENDP0, Device_Property.MaxPacketSize); + + if (pInformation->ControlState == STALLED) + { + vSetEPRxStatus(EP_RX_STALL); + vSetEPTxStatus(EP_TX_STALL); + } + + return (pInformation->ControlState == PAUSE); +} + +/********************************************************************* + * @fn SetDeviceAddress + * + * @brief Set the device and all the used Endpoints addresses. + * + * @param Val - device address. + * + * @return none + */ +void SetDeviceAddress(uint8_t Val) +{ + uint32_t i; + uint32_t nEP = Device_Table.Total_Endpoint; + + for (i = 0; i < nEP; i++) + { + _SetEPAddress((uint8_t)i, (uint8_t)i); + } + + _SetDADDR(Val | DADDR_EF); +} + +/********************************************************************* + * @fn NOP_Process + * + * @brief No operation function. + * + * @return none + */ +void NOP_Process(void) +{ +} + + + + diff --git a/V203F6P6/ch32v203/usbd/src/usb_endp.cpp b/V203F6P6/ch32v203/usbd/src/usb_endp.cpp new file mode 100644 index 0000000..975d3c8 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/src/usb_endp.cpp @@ -0,0 +1,52 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_endp.c + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : Endpoint routines +********************************************************************************* +* 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_lib.h" +#include "usb_desc.h" +#include "usb_mem.h" +#include "hw_config.h" +#include "usb_istr.h" +#include "usb_pwr.h" +#include "usb_prop.h" +#include "cdc_class.h" + +/********************************************************************* + * @fn EP2_IN_Callback + * + * @brief Endpoint 1 IN. + * + * @return none + */ +void EP1_IN_Callback (void) +{ + +} + +/********************************************************************* + * @fn EP2_OUT_Callback + * + * @brief Endpoint 2 OUT. + * + * @return none + */ +void EP2_OUT_Callback (void) { + if (cdc_instance) cdc_instance->ep2outHandler(); +} +/********************************************************************* + * @fn EP3_IN_Callback + * + * @brief Endpoint 3 IN. + * + * @return none + */ +void EP3_IN_Callback (void) { + if (cdc_instance) cdc_instance->ep3inHandler(); +} diff --git a/V203F6P6/ch32v203/usbd/src/usb_init.c b/V203F6P6/ch32v203/usbd/src/usb_init.c new file mode 100644 index 0000000..2c421f5 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/src/usb_init.c @@ -0,0 +1,42 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_init.c + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : Initialization routines & global variables +********************************************************************************* +* 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_lib.h" + +uint8_t EPindex; +DEVICE_INFO *pInformation; +DEVICE_PROP *pProperty; +uint16_t SaveState ; +uint16_t wInterrupt_Mask; +DEVICE_INFO Device_Info; +USER_STANDARD_REQUESTS *pUser_Standard_Requests; + +/******************************************************************************* + * @fn USB_Init + * + * @brief USB system initialization + * + * @return None. + * + */ +void USB_Init(void) +{ + pInformation = &Device_Info; + pInformation->ControlState = 2; + pProperty = &Device_Property; + pUser_Standard_Requests = &User_Standard_Requests; + pProperty->Init(); +} + + + + + diff --git a/V203F6P6/ch32v203/usbd/src/usb_int.c b/V203F6P6/ch32v203/usbd/src/usb_int.c new file mode 100644 index 0000000..57ffd01 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/src/usb_int.c @@ -0,0 +1,130 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_int.c + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : Endpoint CTR (Low and High) interrupt's service routines +********************************************************************************* +* 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_lib.h" + +/* Private variables */ +__IO uint16_t SaveRState; +__IO uint16_t SaveTState; + +/* Extern variables */ +extern void (*pEpInt_IN[7])(void); /* Handles IN interrupts */ +extern void (*pEpInt_OUT[7])(void); /* Handles OUT interrupts */ + +/******************************************************************************* + * @fn CTR_LP. + * + * @brief Low priority Endpoint Correct Transfer interrupt's service + * routine. + * + * @return None. + */ +void CTR_LP(void) +{ + __IO uint16_t wEPVal = 0; + + while (((wIstr = _GetISTR()) & ISTR_CTR) != 0) + { + EPindex = (uint8_t)(wIstr & ISTR_EP_ID); + + if (EPindex == 0) + { + SaveRState = _GetENDPOINT(ENDP0); + SaveTState = SaveRState & EPTX_STAT; + SaveRState &= EPRX_STAT; + + _SetEPRxTxStatus(ENDP0,EP_RX_NAK,EP_TX_NAK); + + if ((wIstr & ISTR_DIR) == 0) + { + _ClearEP_CTR_TX(ENDP0); + In0_Process(); + + _SetEPRxTxStatus(ENDP0,SaveRState,SaveTState); + return; + } + else + { + wEPVal = _GetENDPOINT(ENDP0); + + if ((wEPVal &EP_SETUP) != 0) + { + _ClearEP_CTR_RX(ENDP0); + Setup0_Process(); + _SetEPRxTxStatus(ENDP0,SaveRState,SaveTState); + return; + } + else if ((wEPVal & EP_CTR_RX) != 0) + { + _ClearEP_CTR_RX(ENDP0); + Out0_Process(); + _SetEPRxTxStatus(ENDP0,SaveRState,SaveTState); + return; + } + } + } + else + { + wEPVal = _GetENDPOINT(EPindex); + if ((wEPVal & EP_CTR_RX) != 0) + { + _ClearEP_CTR_RX(EPindex); + (*pEpInt_OUT[EPindex-1])(); + } + + if ((wEPVal & EP_CTR_TX) != 0) + { + _ClearEP_CTR_TX(EPindex); + (*pEpInt_IN[EPindex-1])(); + } + } + } +} +#if 0 +/******************************************************************************* + * @fn CTR_HP. + * + * @brief High Priority Endpoint Correct Transfer interrupt's service + * routine. + * + * @return None. + */ +void CTR_HP(void) +{ + uint32_t wEPVal = 0; + + while (((wIstr = _GetISTR()) & ISTR_CTR) != 0) + { + _SetISTR((uint16_t)CLR_CTR); + EPindex = (uint8_t)(wIstr & ISTR_EP_ID); + wEPVal = _GetENDPOINT(EPindex); + + if ((wEPVal & EP_CTR_RX) != 0) + { + _ClearEP_CTR_RX(EPindex); + (*pEpInt_OUT[EPindex-1])(); + } + else if ((wEPVal & EP_CTR_TX) != 0) + { + _ClearEP_CTR_TX(EPindex); + (*pEpInt_IN[EPindex-1])(); + } + } +} +#endif + + + + + + + + diff --git a/V203F6P6/ch32v203/usbd/src/usb_istr.c b/V203F6P6/ch32v203/usbd/src/usb_istr.c new file mode 100644 index 0000000..c69fce2 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/src/usb_istr.c @@ -0,0 +1,196 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_istr.c + * Author : WCH + * Version : V1.0.1 + * Date : 2022/12/28 + * Description : ISTR events interrupt service routines +********************************************************************************* +* 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_lib.h" +#include "usb_prop.h" +#include "usb_pwr.h" +#include "usb_istr.h" + +uint16_t Ep0RxBlks; + +/* Private variables */ +__IO uint16_t wIstr; +static __IO uint8_t bIntPackSOF = 0; +static __IO uint32_t esof_counter =0; +static __IO uint32_t wCNTR=0; + +/* function pointers to non-control endpoints service routines */ +void (*pEpInt_IN[7])(void) ={ + EP1_IN_Callback, + EP2_IN_Callback, + EP3_IN_Callback, + EP4_IN_Callback, + EP5_IN_Callback, + EP6_IN_Callback, + EP7_IN_Callback, +}; + +void (*pEpInt_OUT[7])(void) ={ + EP1_OUT_Callback, + EP2_OUT_Callback, + EP3_OUT_Callback, + EP4_OUT_Callback, + EP5_OUT_Callback, + EP6_OUT_Callback, + EP7_OUT_Callback, +}; + +/******************************************************************************* + * @fn USB_Istr + * + * @brief ISTR events interrupt service routine + * + * @return None. + */ +void USB_Istr(void) +{ + uint32_t i=0; + __IO uint32_t EP[8]; + if ((*_pEPRxCount(0) & 0xFC00 )!= Ep0RxBlks) + { + *_pEPRxCount(0) |= (Ep0RxBlks & 0xFC00); + } + wIstr = _GetISTR(); +#if (IMR_MSK & ISTR_SOF) + if (wIstr & ISTR_SOF & wInterrupt_Mask) + { + _SetISTR((uint16_t)CLR_SOF); + bIntPackSOF++; +/* +#ifdef SOF_CALLBACK + SOF_Callback(); + +#endif*/ + } +#endif + + +#if (IMR_MSK & ISTR_CTR) + if (wIstr & ISTR_CTR & wInterrupt_Mask) + { + CTR_LP(); +/*#ifdef CTR_CALLBACK + CTR_Callback(); +#endif*/ + } +#endif + +#if (IMR_MSK & ISTR_RESET) + if (wIstr & ISTR_RESET & wInterrupt_Mask) + { + _SetISTR((uint16_t)CLR_RESET); + Device_Property.Reset(); + +/*#ifdef RESET_CALLBACK + RESET_Callback(); +#endif*/ + } +#endif + +#if (IMR_MSK & ISTR_DOVR) + if (wIstr & ISTR_DOVR & wInterrupt_Mask) + { + _SetISTR((uint16_t)CLR_DOVR); +/*#ifdef DOVR_CALLBACK + DOVR_Callback(); +#endif*/ + } +#endif + +#if (IMR_MSK & ISTR_ERR) + if (wIstr & ISTR_ERR & wInterrupt_Mask) + { + _SetISTR((uint16_t)CLR_ERR); +/*#ifdef ERR_CALLBACK + ERR_Callback(); +#endif*/ + } +#endif + +#if (IMR_MSK & ISTR_WKUP) + if (wIstr & ISTR_WKUP & wInterrupt_Mask) + { + _SetISTR((uint16_t)CLR_WKUP); + Resume(RESUME_EXTERNAL); +/*#ifdef WKUP_CALLBACK + WKUP_Callback(); +#endif*/ + } +#endif +#if (IMR_MSK & ISTR_SUSP) + if (wIstr & ISTR_SUSP & wInterrupt_Mask) + { + if (fSuspendEnabled) + { + Suspend(); + } + else + { + Resume(RESUME_LATER); + } + _SetISTR((uint16_t)CLR_SUSP); +/*#ifdef SUSP_CALLBACK + SUSP_Callback(); +#endif*/ + } +#endif + +#if (IMR_MSK & ISTR_ESOF) + if (wIstr & ISTR_ESOF & wInterrupt_Mask) + { + _SetISTR((uint16_t)CLR_ESOF); + + if ((_GetFNR()&FNR_RXDP)!=0) + { + esof_counter ++; + + if ((esof_counter >3)&&((_GetCNTR()&CNTR_FSUSP)==0)) + { + + wCNTR = _GetCNTR(); + + for (i=0;i<8;i++) EP[i] = _GetENDPOINT(i); + + wCNTR|=CNTR_FRES; + _SetCNTR(wCNTR); + + wCNTR&=~CNTR_FRES; + _SetCNTR(wCNTR); + + while((_GetISTR()&ISTR_RESET) == 0); + + _SetISTR((uint16_t)CLR_RESET); + + for (i=0;i<8;i++) + _SetENDPOINT(i, EP[i]); + + esof_counter = 0; + } + } + else + { + esof_counter = 0; + } + + Resume(RESUME_ESOF); + +/*#ifdef ESOF_CALLBACK + ESOF_Callback(); +#endif*/ + } +#endif +} /* USB_Istr */ + + + + + + diff --git a/V203F6P6/ch32v203/usbd/src/usb_mem.c b/V203F6P6/ch32v203/usbd/src/usb_mem.c new file mode 100644 index 0000000..7d65f82 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/src/usb_mem.c @@ -0,0 +1,74 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_mem.c + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : Utility functions for memory transfers to/from PMA +********************************************************************************* +* 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_lib.h" + + +/******************************************************************************* + * @fn UserToPMABufferCopy + * + * @brief Copy a buffer from user memory area to packet memory area (PMA) + * + * @param pbUsrBuf: pointer to user memory area. + * wPMABufAddr: address into PMA. + * wNBytes: no. of bytes to be copied. + * + * @param None . + */ +void UserToPMABufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes) +{ + uint32_t n = (wNBytes + 1) >> 1; + uint32_t i, temp1, temp2; + uint16_t *pdwVal; + pdwVal = (uint16_t *)(wPMABufAddr * 2 + PMAAddr); + + for (i = n; i != 0; i--) + { + temp1 = (uint16_t) * pbUsrBuf; + pbUsrBuf++; + temp2 = temp1 | (uint16_t) * pbUsrBuf << 8; + *pdwVal++ = temp2; + pdwVal++; + pbUsrBuf++; + } +} + +/******************************************************************************* + * @fn PMAToUserBufferCopy + * + * @brief Copy a buffer from user memory area to packet memory area (PMA) + * + * @param pbUsrBuf: pointer to user memory area. + * wPMABufAddr: address into PMA. + * wNBytes: no. of bytes to be copied. + * + * @param None. + */ +void PMAToUserBufferCopy(uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes) +{ + uint32_t n = (wNBytes + 1) >> 1; + uint32_t i; + uint32_t *pdwVal; + + pdwVal = (uint32_t *)(wPMABufAddr * 2 + PMAAddr); + + for (i = n; i != 0; i--) + { + *(uint16_t*)pbUsrBuf++ = *pdwVal++; + pbUsrBuf++; + } +} + + + + + + diff --git a/V203F6P6/ch32v203/usbd/src/usb_prop.cpp b/V203F6P6/ch32v203/usbd/src/usb_prop.cpp new file mode 100644 index 0000000..730140c --- /dev/null +++ b/V203F6P6/ch32v203/usbd/src/usb_prop.cpp @@ -0,0 +1,423 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_prop.c + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : All processing related to Virtual Com Port Demo +********************************************************************************* +* 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_lib.h" +#include "usb_conf.h" +#include "usb_prop.h" +#include "usb_desc.h" +#include "usb_pwr.h" +#include "hw_config.h" +#include "cdc_class.h" + +uint8_t Request = 0; + +//extern uint8_t USBD_Endp3_Busy; +static USB_CDC_LineCoding line_coding; + + +DEVICE Device_Table = +{ + EP_NUM, + 1 +}; + +DEVICE_PROP Device_Property = +{ + USBD_init, + USBD_Reset, + USBD_Status_In, + USBD_Status_Out, + USBD_Data_Setup, + USBD_NoData_Setup, + USBD_Get_Interface_Setting, + USBD_GetDeviceDescriptor, + USBD_GetConfigDescriptor, + USBD_GetStringDescriptor, + 0, + DEF_USBD_UEP0_SIZE +}; + +USER_STANDARD_REQUESTS User_Standard_Requests = +{ + USBD_GetConfiguration, + USBD_SetConfiguration, + USBD_GetInterface, + USBD_SetInterface, + USBD_GetStatus, + USBD_ClearFeature, + USBD_SetEndPointFeature, + USBD_SetDeviceFeature, + USBD_SetDeviceAddress +}; + +ONE_DESCRIPTOR Device_Descriptor = +{ + (uint8_t*)USBD_DeviceDescriptor, + USBD_SIZE_DEVICE_DESC +}; + +ONE_DESCRIPTOR Config_Descriptor = +{ + (uint8_t*)USBD_ConfigDescriptor, + USBD_SIZE_CONFIG_DESC +}; + +ONE_DESCRIPTOR String_Descriptor[4] = +{ + {(uint8_t*)USBD_StringLangID, USBD_SIZE_STRING_LANGID}, + {(uint8_t*)USBD_StringVendor, USBD_SIZE_STRING_VENDOR}, + {(uint8_t*)USBD_StringProduct,USBD_SIZE_STRING_PRODUCT}, + {(uint8_t*)USBD_StringSerial, USBD_SIZE_STRING_SERIAL} +}; + +/********************************************************************* + * @fn USBD_SetConfiguration. + * + * @brief Update the device state to configured. + * + * @return None. + */ +void USBD_SetConfiguration(void) +{ + DEVICE_INFO *pInfo = &Device_Info; + + if (pInfo->Current_Configuration != 0) + { + bDeviceState = CONFIGURED; + } +} + +/******************************************************************************* + * @fn USBD_SetDeviceAddress. + * + * @brief Update the device state to addressed. + * + * @return None. + */ +void USBD_SetDeviceAddress (void) +{ + bDeviceState = ADDRESSED; +} + + +/********************************************************************* + * @fn USBD_SetDeviceFeature. + * + * @brief SetDeviceFeature Routine. + * + * @return none + */ +void USBD_SetDeviceFeature (void) +{ + +} + + + +/********************************************************************* + * @fn USBD_ClearFeature. + * + * @brief ClearFeature Routine. + * + * @return none + */ +void USBD_ClearFeature(void) +{ + +} + + + + + +/********************************************************************* + * @fn USBD_Status_In. + * + * @brief USBD Status In Routine. + * + * @return None. + */ +void USBD_Status_In(void) +{ + uint32_t Request_No = pInformation->USBbRequest; + if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) + { + if (Request_No == CDC_SET_LINE_CODING) + { + //UART2_USB_Init(); // TODO + if (cdc_instance) cdc_instance->ctrl (USB_USART_SET_PARAM, & line_coding, sizeof (line_coding)); + } + } +} + +/******************************************************************************* + * @fn USBD_Status_Out + * + * @brief USBD Status OUT Routine. + * + * @return None. + */ +void USBD_Status_Out(void) +{ + +} + +/******************************************************************************* + * @fn USBD_init. + * + * @brief init routine. + * + * @return None. + */ +extern "C" void Delay_Ms (const unsigned); + +void USBD_init(void) +{ + uint8_t i; + + pInformation->Current_Configuration = 0; + PowerOn(); + for (i=0;i<8;i++) _SetENDPOINT(i,_GetENDPOINT(i) & 0x7F7F & EPREG_MASK);//all clear + _SetISTR((uint16_t)0x00FF);//all clear + USB_SIL_Init(); + bDeviceState = UNCONNECTED; + + USB_Port_Set(DISABLE, DISABLE); + Delay_Ms(20); + USB_Port_Set(ENABLE, ENABLE); +} + +/******************************************************************************* + * @fn USBD_Reset + * + * @brief USBD reset routine + * + * @return None. + */ +void USBD_Reset(void) +{ + pInformation->Current_Configuration = 0; + pInformation->Current_Feature = USBD_ConfigDescriptor[7]; + pInformation->Current_Interface = 0; + + SetBTABLE(BTABLE_ADDRESS); + + SetEPType(ENDP0, EP_CONTROL); + SetEPTxStatus(ENDP0, EP_TX_STALL); + SetEPRxAddr(ENDP0, ENDP0_RXADDR); + SetEPTxAddr(ENDP0, ENDP0_TXADDR); + Clear_Status_Out(ENDP0); + SetEPRxCount(ENDP0, Device_Property.MaxPacketSize); + SetEPRxValid(ENDP0); + _ClearDTOG_RX(ENDP0); + _ClearDTOG_TX(ENDP0); + + SetEPType(ENDP1, EP_INTERRUPT); + SetEPTxStatus(ENDP1, EP_TX_NAK); + SetEPTxAddr(ENDP1, ENDP1_TXADDR); + SetEPRxStatus(ENDP1, EP_RX_DIS); + _ClearDTOG_TX(ENDP1); + _ClearDTOG_RX(ENDP1); + + SetEPType(ENDP2, EP_BULK); + SetEPTxStatus(ENDP2, EP_TX_DIS); + SetEPRxAddr(ENDP2, ENDP2_RXADDR); + SetEPRxCount(ENDP2, DEF_USBD_MAX_PACK_SIZE); + SetEPRxStatus(ENDP2,EP_RX_VALID); + _ClearDTOG_RX(ENDP2); + _ClearDTOG_TX(ENDP2); + + SetEPType(ENDP3, EP_BULK); + SetEPTxStatus(ENDP3, EP_TX_NAK); + SetEPTxAddr(ENDP3, ENDP3_TXADDR); + SetEPRxStatus(ENDP3, EP_RX_DIS); + _ClearDTOG_TX(ENDP3); + _ClearDTOG_RX(ENDP3); + + SetDeviceAddress(0); + + bDeviceState = ATTACHED; +} + +/******************************************************************************* + * @fn USBD_GetDeviceDescriptor. + * + * @brief Gets the device descriptor. + * + * @param Length. + * + * @return The address of the device descriptor. + */ +uint8_t *USBD_GetDeviceDescriptor(uint16_t Length) +{ + return Standard_GetDescriptorData(Length, &Device_Descriptor); +} + +/******************************************************************************* + * @fn USBD_GetConfigDescriptor. + * + * @brief get the configuration descriptor. + * + * @param Length. + * + * @return The address of the configuration descriptor. + */ +uint8_t *USBD_GetConfigDescriptor(uint16_t Length) +{ + return Standard_GetDescriptorData(Length, &Config_Descriptor); +} + +/******************************************************************************* + * @fn USBD_GetStringDescriptor + * + * @brief Gets the string descriptors according to the needed index + * + * @param Length. + * + * @return The address of the string descriptors. + */ +uint8_t *USBD_GetStringDescriptor(uint16_t Length) +{ + uint8_t wValue0 = pInformation->USBwValue0; + + if (wValue0 > 4) + { + return nullptr; + } + else + { + return Standard_GetDescriptorData(Length, &String_Descriptor[wValue0]); + } +} + +/********************************************************************* + * @fn USBD_Get_Interface_Setting. + * + * @brief test the interface and the alternate setting according to the + * supported one. + * + * @param Interface: interface number. + * AlternateSetting: Alternate Setting number. + * + * @return USB_UNSUPPORT or USB_SUCCESS. + */ +RESULT USBD_Get_Interface_Setting(uint8_t Interface, uint8_t AlternateSetting) +{ + if (AlternateSetting > 0) + { + return USB_UNSUPPORT; + } + else if (Interface > 1) + { + return USB_UNSUPPORT; + } + + return USB_SUCCESS; +} + +/********************************************************************* + * @fn USB_CDC_GetLineCoding. + * + * @brief send the linecoding structure to the PC host. + * + * @param Length + * + * @return Inecoding structure base address. + */ +uint8_t *USB_CDC_GetLineCoding( uint16_t Length ) +{ + if( Length == 0 ) + { + pInformation->Ctrl_Info.Usb_wLength = 7; + return nullptr; + } + return (uint8_t*) & line_coding; +} +/********************************************************************* + * @fn USB_CDC_SetLineCoding. + * + * @brief Set the linecoding structure fields. + * + * @param Length + * + * @return Inecoding structure base address. + */ +uint8_t *USB_CDC_SetLineCoding( uint16_t Length ) +{ + if( Length == 0 ) + { + pInformation->Ctrl_Info.Usb_wLength = 7; + return nullptr; + } + return (uint8_t*) & line_coding; +} + + +/********************************************************************* + * @fn USBD_Data_Setup + * + * @brief handle the data class specific requests + * + * @param Request Nb. + * + * @return USB_UNSUPPORT or USB_SUCCESS. + */ +RESULT USBD_Data_Setup(uint8_t RequestNo) +{ + uint32_t Request_No = pInformation->USBbRequest; + uint8_t *(*CopyRoutine)(uint16_t); + CopyRoutine = nullptr; + if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) { + return USB_UNSUPPORT; + } else if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { + if (Request_No == CDC_GET_LINE_CODING) { + CopyRoutine = &USB_CDC_GetLineCoding; + } else if (Request_No == CDC_SET_LINE_CODING) { + CopyRoutine = &USB_CDC_SetLineCoding; + } else { + return USB_UNSUPPORT; + } + } + if (CopyRoutine) { + pInformation->Ctrl_Info.CopyData = CopyRoutine; + pInformation->Ctrl_Info.Usb_wOffset = 0; + (*CopyRoutine)( 0 ); + } else { + return( USB_UNSUPPORT ); + } + return USB_SUCCESS; +} + +/******************************************************************************* + * @fn USBD_NoData_Setup. + * + * @brief handle the no data class specific requests. + * + * @param Request Nb. + * + * @return USB_UNSUPPORT or USB_SUCCESS. + */ +RESULT USBD_NoData_Setup(uint8_t RequestNo) +{ + uint32_t Request_No = pInformation->USBbRequest; + + if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) { + if (Request_No == CDC_SET_LINE_CTLSTE) { + uint16_t ww = pInformation->USBwValues.w >> 8; + if (cdc_instance) cdc_instance->ctrl (USB_USART_SET_DTR_RTS, & ww, 2); + } else if (Request_No == CDC_SEND_BREAK) { + + } else { + return USB_UNSUPPORT; + } + } + return USB_SUCCESS; +} diff --git a/V203F6P6/ch32v203/usbd/src/usb_pwr.c b/V203F6P6/ch32v203/usbd/src/usb_pwr.c new file mode 100644 index 0000000..4632069 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/src/usb_pwr.c @@ -0,0 +1,215 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_pwr.c + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : Connection/disconnection & power management +********************************************************************************* +* 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_lib.h" +#include "usb_conf.h" +#include "usb_pwr.h" +#include "hw_config.h" + +__IO uint32_t bDeviceState = UNCONNECTED; +__IO bool fSuspendEnabled = TRUE; +__IO uint32_t EP[8]; + +struct +{ + __IO RESUME_STATE eState; + __IO uint8_t bESOFcnt; +} +ResumeS; + +__IO uint32_t remotewakeupon=0; + +/******************************************************************************* + * @fn PowerOn + * + * @brief Enable power on. + * + * @return USB_SUCCESS. + */ +RESULT PowerOn(void) +{ + uint16_t wRegVal; + + wRegVal = CNTR_FRES; + _SetCNTR(wRegVal); + wInterrupt_Mask = 0; + _SetCNTR(wInterrupt_Mask); + _SetISTR(0); + wInterrupt_Mask = CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM; + _SetCNTR(wInterrupt_Mask); + + return USB_SUCCESS; +} + +/******************************************************************************* + * @fn PowerOff + * + * @brief handles switch-off conditions + * + * @return USB_SUCCESS. + */ +RESULT PowerOff() +{ + _SetCNTR(CNTR_FRES); + _SetISTR(0); + _SetCNTR(CNTR_FRES + CNTR_PDWN); + + return USB_SUCCESS; +} + +/******************************************************************************* + * @fn Suspend + * + * @brief sets suspend mode operating conditions + * + * @return USB_SUCCESS. + */ +void Suspend(void) +{ + uint32_t i =0; + uint16_t wCNTR; + + wCNTR = _GetCNTR(); + for (i=0;i<8;i++) EP[i] = _GetENDPOINT(i); + + wCNTR|=CNTR_RESETM; + _SetCNTR(wCNTR); + + wCNTR|=CNTR_FRES; + _SetCNTR(wCNTR); + + wCNTR&=~CNTR_FRES; + _SetCNTR(wCNTR); + + while((_GetISTR()&ISTR_RESET) == 0); + + _SetISTR((uint16_t)CLR_RESET); + + for (i=0;i<8;i++) + _SetENDPOINT(i, EP[i]); + + wCNTR |= CNTR_FSUSP; + _SetCNTR(wCNTR); + + wCNTR = _GetCNTR(); + wCNTR |= CNTR_LPMODE; + _SetCNTR(wCNTR); + + Enter_LowPowerMode(); +} + +/******************************************************************************* + * @fn Resume_Init + * + * @brief Handles wake-up restoring normal operations + * + * @return USB_SUCCESS. + */ +void Resume_Init(void) +{ + uint16_t wCNTR; + + wCNTR = _GetCNTR(); + wCNTR &= (~CNTR_LPMODE); + _SetCNTR(wCNTR); + Leave_LowPowerMode(); + _SetCNTR(IMR_MSK); +} + +/******************************************************************************* + * @fn Resume + * + * @brief This is the state machine handling resume operations and + * timing sequence. The control is based on the Resume structure + * variables and on the ESOF interrupt calling this subroutine + * without changing machine state. + * + * @param a state machine value (RESUME_STATE) + * RESUME_ESOF doesn't change ResumeS.eState allowing + * decrementing of the ESOF counter in different states. + * + * @return None. + */ +void Resume(RESUME_STATE eResumeSetVal) +{ + uint16_t wCNTR; + + if (eResumeSetVal != RESUME_ESOF) + { + ResumeS.eState = eResumeSetVal; + } + + switch (ResumeS.eState) + { + case RESUME_EXTERNAL: + if (remotewakeupon ==0) + { + Resume_Init(); + ResumeS.eState = RESUME_OFF; + } + else + { + ResumeS.eState = RESUME_ON; + } + break; + + case RESUME_INTERNAL: + Resume_Init(); + ResumeS.eState = RESUME_START; + remotewakeupon = 1; + break; + + case RESUME_LATER: + ResumeS.bESOFcnt = 2; + ResumeS.eState = RESUME_WAIT; + break; + + case RESUME_WAIT: + ResumeS.bESOFcnt--; + if (ResumeS.bESOFcnt == 0) + ResumeS.eState = RESUME_START; + break; + + case RESUME_START: + wCNTR = _GetCNTR(); + wCNTR |= CNTR_RESUME; + _SetCNTR(wCNTR); + ResumeS.eState = RESUME_ON; + ResumeS.bESOFcnt = 10; + break; + + case RESUME_ON: + ResumeS.bESOFcnt--; + if (ResumeS.bESOFcnt == 0) + { + wCNTR = _GetCNTR(); + wCNTR &= (~CNTR_RESUME); + _SetCNTR(wCNTR); + ResumeS.eState = RESUME_OFF; + remotewakeupon = 0; + } + break; + + case RESUME_OFF: + + case RESUME_ESOF: + + default: + ResumeS.eState = RESUME_OFF; + break; + } +} + + + + + + diff --git a/V203F6P6/ch32v203/usbd/src/usb_regs.c b/V203F6P6/ch32v203/usbd/src/usb_regs.c new file mode 100644 index 0000000..57a2094 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/src/usb_regs.c @@ -0,0 +1,852 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_regs.c + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : Interface functions to USB cell registers +********************************************************************************* +* 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_lib.h" + +/******************************************************************************* + * @fn SetCNTR. + * + * @brief Set the CNTR register value. + * + * @param wRegValue: new register value. + * + * @return None. + */ +void SetCNTR(uint16_t wRegValue) +{ + _SetCNTR(wRegValue); +} + +/******************************************************************************* + * @fn GetCNTR. + * + * @brief returns the CNTR register value. + * + * @param None. + * + * @return CNTR register Value. + */ +uint16_t GetCNTR(void) +{ + return(_GetCNTR()); +} + +/******************************************************************************* + * @fn SetISTR. + * + * @brief Set the ISTR register value. + * + * @param wRegValue: new register value. + * + * @return None. + */ +void SetISTR(uint16_t wRegValue) +{ + _SetISTR(wRegValue); +} + +/******************************************************************************* + * @fn GetISTR + * + * @brief Returns the ISTR register value. + * + * @param None. + * + * @return ISTR register Value + */ +uint16_t GetISTR(void) +{ + return(_GetISTR()); +} + +/******************************************************************************* + * @fn GetFNR + * + * @brief Returns the FNR register value. + * + * @param None. + * + * @return FNR register Value + */ +uint16_t GetFNR(void) +{ + return(_GetFNR()); +} + +/******************************************************************************* + * @fn SetDADDR + * + * @brief Set the DADDR register value. + * + * @param wRegValue: new register value. + * + * @return None. + */ +void SetDADDR(uint16_t wRegValue) +{ + _SetDADDR(wRegValue); +} + +/******************************************************************************* + * @fn GetDADDR + * + * @brief Returns the DADDR register value. + * + * @return DADDR register Value + * + */ +uint16_t GetDADDR(void) +{ + return(_GetDADDR()); +} + +/******************************************************************************* + * @fn SetBTABLE + * + * @brief Set the BTABLE. + * + * @param wRegValue: New register value. + * + * @return None. + */ +void SetBTABLE(uint16_t wRegValue) +{ + _SetBTABLE(wRegValue); +} + +/******************************************************************************* + * @fn GetBTABLE. + * + * @param Returns the BTABLE register value. + * + * @return BTABLE address. + */ +uint16_t GetBTABLE(void) +{ + return(_GetBTABLE()); +} + +/******************************************************************************* + * @fn SetENDPOINT + * + * @brief Set the Endpoint register value. + * + * @param bEpNum: Endpoint Number. + * wRegValue. + * + * @return None. + */ +void SetENDPOINT(uint8_t bEpNum, uint16_t wRegValue) +{ + _SetENDPOINT(bEpNum, wRegValue); +} + +/******************************************************************************* + * @fn GetENDPOINT + * + * @brief Return the Endpoint register value. + * + * @param bEpNum: Endpoint Number. + * + * @return Endpoint register value. + */ +uint16_t GetENDPOINT(uint8_t bEpNum) +{ + return(_GetENDPOINT(bEpNum)); +} + +/******************************************************************************* + * @fn SetEPType + * + * @brief sets the type in the endpoint register. + * + * @param bEpNum: Endpoint Number. + * wType: type definition. + * + * @return None. + */ +void SetEPType(uint8_t bEpNum, uint16_t wType) +{ + _SetEPType(bEpNum, wType); +} + +/******************************************************************************* + * @fn GetEPType + * + * @brief Returns the endpoint type. + * + * @param bEpNum: Endpoint Number. + * + * @return Endpoint Type + */ +uint16_t GetEPType(uint8_t bEpNum) +{ + return(_GetEPType(bEpNum)); +} + +/******************************************************************************* + * @fn SetEPTxStatus + * + * @brief Set the status of Tx endpoint. + * + * @param bEpNum: Endpoint Number. + * wState: new state. + * + * @return None. + */ +void SetEPTxStatus(uint8_t bEpNum, uint16_t wState) +{ + _SetEPTxStatus(bEpNum, wState); +} + +/******************************************************************************* + * @fn SetEPRxStatus + * + * @brief Set the status of Rx endpoint. + * + * @param bEpNum: Endpoint Number. + * wState: new state. + * + * @return None. + */ +void SetEPRxStatus(uint8_t bEpNum, uint16_t wState) +{ + _SetEPRxStatus(bEpNum, wState); +} + +/******************************************************************************* + * @fn SetDouBleBuffEPStall + * + * @brief sets the status for Double Buffer Endpoint to STALL + * + * @param bEpNum: Endpoint Number. + * bDir: Endpoint direction. + * + * @return None. + */ +void SetDouBleBuffEPStall(uint8_t bEpNum, uint8_t bDir) +{ + uint16_t Endpoint_DTOG_Status; + + Endpoint_DTOG_Status = GetENDPOINT(bEpNum); + + if (bDir == EP_DBUF_OUT) + { + _SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPRX_DTOG1); + } + else if (bDir == EP_DBUF_IN) + { + _SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPTX_DTOG1); + } +} + +/******************************************************************************* + * @fn GetEPTxStatus + * + * @brief Returns the endpoint Tx status. + * + * @param bEpNum: Endpoint Number. + * + * @return Endpoint TX Status + */ +uint16_t GetEPTxStatus(uint8_t bEpNum) +{ + return(_GetEPTxStatus(bEpNum)); +} + +/******************************************************************************* + * @fn GetEPRxStatus + * + * @brief Returns the endpoint Rx status. + * + * @param bEpNum: Endpoint Number. + * + * @return Endpoint RX Status + */ +uint16_t GetEPRxStatus(uint8_t bEpNum) +{ + return(_GetEPRxStatus(bEpNum)); +} + +/******************************************************************************* + * @fn SetEPTxValid + * + * @brief Valid the endpoint Tx Status. + * + * @param bEpNum: Endpoint Number. + * + * @return None. + */ +void SetEPTxValid(uint8_t bEpNum) +{ + _SetEPTxStatus(bEpNum, EP_TX_VALID); +} + +/******************************************************************************* + * @fn SetEPRxValid + * + * @brief Valid the endpoint Rx Status. + * + * @param bEpNum: Endpoint Number. + * + * @return None. + */ +void SetEPRxValid(uint8_t bEpNum) +{ + _SetEPRxStatus(bEpNum, EP_RX_VALID); +} + +/******************************************************************************* + * @fn SetEP_KIND + * + * @brief Clear the EP_KIND bit. + * + * @param bEpNum: Endpoint Number. + * + * @return None. + */ +void SetEP_KIND(uint8_t bEpNum) +{ + _SetEP_KIND(bEpNum); +} + +/******************************************************************************* + * @fn ClearEP_KIND + * + * @brief set the EP_KIND bit. + * + * @param bEpNum: Endpoint Number. + * + * @return None. + */ +void ClearEP_KIND(uint8_t bEpNum) +{ + _ClearEP_KIND(bEpNum); +} +/******************************************************************************* + * @fn Clear_Status_Out + * + * @brief Clear the Status Out of the related Endpoint + * + * @param bEpNum: Endpoint Number. + * + * @return None. + */ +void Clear_Status_Out(uint8_t bEpNum) +{ + _ClearEP_KIND(bEpNum); +} +/******************************************************************************* + * @fn Set_Status_Out + * + * @brief Set the Status Out of the related Endpoint + * + * @param bEpNum: Endpoint Number. + * + * @return None. + */ +void Set_Status_Out(uint8_t bEpNum) +{ + _SetEP_KIND(bEpNum); +} +/******************************************************************************* + * @fn SetEPDoubleBuff + * + * @brief Enable the double buffer feature for the endpoint. + * + * @param bEpNum: Endpoint Number. + * + * @return None. + */ +void SetEPDoubleBuff(uint8_t bEpNum) +{ + _SetEP_KIND(bEpNum); +} +/******************************************************************************* + * @fn ClearEPDoubleBuff + * + * @brief Disable the double buffer feature for the endpoint. + * + * @param bEpNum: Endpoint Number. + * + * @return None. + */ +void ClearEPDoubleBuff(uint8_t bEpNum) +{ + _ClearEP_KIND(bEpNum); +} +/******************************************************************************* + * @fn GetTxStallStatus + * + * @brief Returns the Stall status of the Tx endpoint. + * + * @param bEpNum: Endpoint Number. + * + * @return Tx Stall status. + */ +uint16_t GetTxStallStatus(uint8_t bEpNum) +{ + return(_GetTxStallStatus(bEpNum)); +} +/******************************************************************************* + * @fn GetRxStallStatus + * + * @brief Returns the Stall status of the Rx endpoint. + * + * @param bEpNum: Endpoint Number. + * + * @return Rx Stall status. + */ +uint16_t GetRxStallStatus(uint8_t bEpNum) +{ + return(_GetRxStallStatus(bEpNum)); +} +/******************************************************************************* + * @fn ClearEP_CTR_RX + * + * @brief Clear the CTR_RX bit. + * + * @param bEpNum: Endpoint Number. + * + * @return None. + */ +void ClearEP_CTR_RX(uint8_t bEpNum) +{ + _ClearEP_CTR_RX(bEpNum); +} +/******************************************************************************* + * @fn ClearEP_CTR_TX + * + * @brief Clear the CTR_TX bit. + * + * @param bEpNum: Endpoint Number. + * + * @return None. + */ +void ClearEP_CTR_TX(uint8_t bEpNum) +{ + _ClearEP_CTR_TX(bEpNum); +} +/******************************************************************************* + * @fn ToggleDTOG_RX + * + * @brief Toggle the DTOG_RX bit. + * + * @param bEpNum: Endpoint Number. + * + * @return None. + */ +void ToggleDTOG_RX(uint8_t bEpNum) +{ + _ToggleDTOG_RX(bEpNum); +} +/******************************************************************************* + * @fn ToggleDTOG_TX + * + * @brief Toggle the DTOG_TX bit. + * + * @param bEpNum: Endpoint Number. + * + * @return None. + */ +void ToggleDTOG_TX(uint8_t bEpNum) +{ + _ToggleDTOG_TX(bEpNum); +} +/******************************************************************************* + * @fn ClearDTOG_RX. + * + * @brief Clear the DTOG_RX bit. + * + * @param bEpNum: Endpoint Number. + * + * @return None. + */ +void ClearDTOG_RX(uint8_t bEpNum) +{ + _ClearDTOG_RX(bEpNum); +} +/******************************************************************************* + * @fn ClearDTOG_TX. + * + * @brief Clear the DTOG_TX bit. + * + * @param bEpNum: Endpoint Number. + * + * @return None. + */ +void ClearDTOG_TX(uint8_t bEpNum) +{ + _ClearDTOG_TX(bEpNum); +} +/******************************************************************************* + * @fn SetEPAddress + * + * @brief Set the endpoint address. + * + * @param bEpNum: Endpoint Number. + * bAddr: New endpoint address. + * + * @return None. + */ +void SetEPAddress(uint8_t bEpNum, uint8_t bAddr) +{ + _SetEPAddress(bEpNum, bAddr); +} +/******************************************************************************* + * @fn GetEPAddress + * + * @brief Get the endpoint address. + * + * @param bEpNum: Endpoint Number. + * + * @return Endpoint address. + */ +uint8_t GetEPAddress(uint8_t bEpNum) +{ + return(_GetEPAddress(bEpNum)); +} +/******************************************************************************* + * @fn SetEPTxAddr + * + * @brief Set the endpoint Tx buffer address. + * + * @param bEpNum: Endpoint Number. + * wAddr: new address. + * + * @return None. + */ +void SetEPTxAddr(uint8_t bEpNum, uint16_t wAddr) +{ + _SetEPTxAddr(bEpNum, wAddr); +} +/******************************************************************************* + * @fn SetEPRxAddr + * + * @brief Set the endpoint Rx buffer address. + * + * @param bEpNum: Endpoint Number. + * wAddr: new address. + * + * @return None. + */ +void SetEPRxAddr(uint8_t bEpNum, uint16_t wAddr) +{ + _SetEPRxAddr(bEpNum, wAddr); +} +/******************************************************************************* + * @fn GetEPTxAddr + * + * @brief Returns the endpoint Tx buffer address. + * + * @param bEpNum: Endpoint Number. + * + * @return Rx buffer address. + */ +uint16_t GetEPTxAddr(uint8_t bEpNum) +{ + return(_GetEPTxAddr(bEpNum)); +} +/******************************************************************************* + * @fn GetEPRxAddr. + * + * @brief Returns the endpoint Rx buffer address. + * + * @param bEpNum: Endpoint Number. + * + * @returnRx buffer address. + */ +uint16_t GetEPRxAddr(uint8_t bEpNum) +{ + return(_GetEPRxAddr(bEpNum)); +} +/******************************************************************************* + * @fn SetEPTxCount. + * + * @brief Set the Tx count. + * + * @param bEpNum: Endpoint Number. + * wCount: new count value. + * + * @return None. + */ +void SetEPTxCount(uint8_t bEpNum, uint16_t wCount) +{ + _SetEPTxCount(bEpNum, wCount); +} +/******************************************************************************* + * @fn SetEPCountRxReg. + * + * @brief Set the Count Rx Register value. + * + * @param *pdwReg: point to the register. + * wCount: the new register value. + * + * @return None. + */ +void SetEPCountRxReg(uint32_t *pdwReg, uint16_t wCount) +{ + _SetEPCountRxReg(dwReg, wCount); +} +/******************************************************************************* + * @fn SetEPRxCount + * + * @brief Set the Rx count. + * + * @param bEpNum: Endpoint Number. + * wCount: the new count value. + * + * @return None. + */ +void SetEPRxCount(uint8_t bEpNum, uint16_t wCount) +{ + _SetEPRxCount(bEpNum, wCount); +} +/******************************************************************************* + * @fn GetEPTxCount + * + * @brief Get the Tx count. + * + * @param bEpNum: Endpoint Number. + * + * @return Tx count value. + */ +uint16_t GetEPTxCount(uint8_t bEpNum) +{ + return(_GetEPTxCount(bEpNum)); +} +/******************************************************************************* + * @fn GetEPRxCount + * + * @brief Get the Rx count. + * + * @param bEpNum: Endpoint Number. + * + * @return Rx count value. + */ +uint16_t GetEPRxCount(uint8_t bEpNum) +{ + return(_GetEPRxCount(bEpNum)); +} +/******************************************************************************* + * @fn SetEPDblBuffAddr + * + * @brief Set the addresses of the buffer 0 and 1. + * + * @param bEpNum: Endpoint Number. + * wBuf0Addr: new address of buffer 0. + * wBuf1Addr: new address of buffer 1. + * + * @return None. + */ +void SetEPDblBuffAddr(uint8_t bEpNum, uint16_t wBuf0Addr, uint16_t wBuf1Addr) +{ + _SetEPDblBuffAddr(bEpNum, wBuf0Addr, wBuf1Addr); +} +/******************************************************************************* + * @fn SetEPDblBuf0Addr + * + * @brief Set the Buffer 1 address. + * + * @param bEpNum: Endpoint Number + * wBuf0Addr: new address. + * + * @return None. + */ +void SetEPDblBuf0Addr(uint8_t bEpNum, uint16_t wBuf0Addr) +{ + _SetEPDblBuf0Addr(bEpNum, wBuf0Addr); +} +/******************************************************************************* + * @fn SetEPDblBuf1Addr + * + * @brief Set the Buffer 1 address. + * + * @param bEpNum: Endpoint Number + * wBuf1Addr: new address. + * + * @return None. + */ +void SetEPDblBuf1Addr(uint8_t bEpNum, uint16_t wBuf1Addr) +{ + _SetEPDblBuf1Addr(bEpNum, wBuf1Addr); +} +/******************************************************************************* + * @fn GetEPDblBuf0Addr + * + * @brief Returns the address of the Buffer 0. + * + * @param bEpNum: Endpoint Number. + * + * @return None. + */ +uint16_t GetEPDblBuf0Addr(uint8_t bEpNum) +{ + return(_GetEPDblBuf0Addr(bEpNum)); +} +/******************************************************************************* + * @fn GetEPDblBuf1Addr + * + * @brief Returns the address of the Buffer 1. + * + * @param bEpNum: Endpoint Number. + * + * @return Address of the Buffer 1. + */ +uint16_t GetEPDblBuf1Addr(uint8_t bEpNum) +{ + return(_GetEPDblBuf1Addr(bEpNum)); +} +/******************************************************************************* + * @fn SetEPDblBuffCount + * + * @brief Set the number of bytes for a double Buffer + * endpoint. + * + * @param bEpNum,bDir, wCount + * + * @return None. + */ +void SetEPDblBuffCount(uint8_t bEpNum, uint8_t bDir, uint16_t wCount) +{ + _SetEPDblBuffCount(bEpNum, bDir, wCount); +} +/******************************************************************************* + * @fn SetEPDblBuf0Count + * + * @brief Set the number of bytes in the buffer 0 of a double Buffer + * endpoint. + * + * @param bEpNum, bDir, wCount + * + * @return None. + */ +void SetEPDblBuf0Count(uint8_t bEpNum, uint8_t bDir, uint16_t wCount) +{ + _SetEPDblBuf0Count(bEpNum, bDir, wCount); +} +/******************************************************************************* + * @fn SetEPDblBuf1Count + * + * @brief Set the number of bytes in the buffer 0 of a double Buffer +* endpoint. + * + * @param bEpNum, bDir, wCount + * + * @return None. + */ +void SetEPDblBuf1Count(uint8_t bEpNum, uint8_t bDir, uint16_t wCount) +{ + _SetEPDblBuf1Count(bEpNum, bDir, wCount); +} +/******************************************************************************* + * @fn GetEPDblBuf0Count + * + * @brief Returns the number of byte received in the buffer 0 of a double + * Buffer endpoint. + * + * @param bEpNum: Endpoint Number. + * + * @return Endpoint Buffer 0 count + */ +uint16_t GetEPDblBuf0Count(uint8_t bEpNum) +{ + return(_GetEPDblBuf0Count(bEpNum)); +} +/******************************************************************************* + * @fn GetEPDblBuf1Count + * + * @brief Returns the number of data received in the buffer 1 of a double + * Buffer endpoint. + * + * @param bEpNum: Endpoint Number. + * + * @return Endpoint Buffer 1 count. + */ +uint16_t GetEPDblBuf1Count(uint8_t bEpNum) +{ + return(_GetEPDblBuf1Count(bEpNum)); +} +/******************************************************************************* + * @fn GetEPDblBufDir + * + * @brief gets direction of the double buffered endpoint + * + * @param bEpNum: Endpoint Number. + * + * @return EP_DBUF_OUT, EP_DBUF_IN, + * EP_DBUF_ERR if the endpoint counter not yet programmed. + */ +EP_DBUF_DIR GetEPDblBufDir(uint8_t bEpNum) +{ + if ((uint16_t)(*_pEPRxCount(bEpNum) & 0xFC00) != 0) + return(EP_DBUF_OUT); + else if (((uint16_t)(*_pEPTxCount(bEpNum)) & 0x03FF) != 0) + return(EP_DBUF_IN); + else + return(EP_DBUF_ERR); +} +/******************************************************************************* + * @fn FreeUserBuffer + * + * @brief free buffer used from the application realizing it to the line + toggles bit SW_BUF in the double buffered endpoint register + * + * @param bEpNum, bDir + * + * @return None. + */ +void FreeUserBuffer(uint8_t bEpNum, uint8_t bDir) +{ + if (bDir == EP_DBUF_OUT) + { + _ToggleDTOG_TX(bEpNum); + } + else if (bDir == EP_DBUF_IN) + { + _ToggleDTOG_RX(bEpNum); + } +} + +/******************************************************************************* + * @fn ToWord + * + * @brief merge two byte in a word. + * + * @param bh: byte high, bl: bytes low. + * + * @return resulted word. + */ +uint16_t ToWord(uint8_t bh, uint8_t bl) +{ + uint16_t wRet; + wRet = (uint16_t)bl | ((uint16_t)bh << 8); + + return(wRet); +} +/******************************************************************************* + * @fn ByteSwap + * + * @brief Swap two byte in a word. + * + * @param wSwW: word to Swap. + * + * @return resulted word. + */ +uint16_t ByteSwap(uint16_t wSwW) +{ + uint8_t bTemp; + uint16_t wRet; + bTemp = (uint8_t)(wSwW & 0xff); + wRet = (wSwW >> 8) | ((uint16_t)bTemp << 8); + + return(wRet); +} diff --git a/V203F6P6/ch32v203/usbd/src/usb_sil.c b/V203F6P6/ch32v203/usbd/src/usb_sil.c new file mode 100644 index 0000000..8d7adcf --- /dev/null +++ b/V203F6P6/ch32v203/usbd/src/usb_sil.c @@ -0,0 +1,77 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_sil.c + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : Simplified Interface Layer for Global Initialization and + * Endpoint Rea/Write operations. +********************************************************************************* +* 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_lib.h" + + +/******************************************************************************* + * @fn USB_SIL_Init + * + * @brief Initialize the USB Device IP and the Endpoint 0. + * + * @return Status. + */ +uint32_t USB_SIL_Init(void) +{ + _SetISTR(0); + wInterrupt_Mask = IMR_MSK; + _SetCNTR(wInterrupt_Mask); + + return 0; +} + +/******************************************************************************* + * @fn USB_SIL_Write + * + * @brief Write a buffer of data to a selected endpoint. + * + * @param bEpAddr: The address of the non control endpoint. + * pBufferPointer: The pointer to the buffer of data to be written + * to the endpoint. + * wBufferSize: Number of data to be written (in bytes). + * + * @return Status. + */ +uint32_t USB_SIL_Write(uint8_t bEpAddr, uint8_t* pBufferPointer, uint32_t wBufferSize) +{ + UserToPMABufferCopy(pBufferPointer, GetEPTxAddr(bEpAddr & 0x7F), wBufferSize); + SetEPTxCount((bEpAddr & 0x7F), wBufferSize); + + return 0; +} + +/******************************************************************************* + * @fn USB_SIL_Read + * + * @brief Write a buffer of data to a selected endpoint. + * + * @param bEpAddr: The address of the non control endpoint. + * pBufferPointer: The pointer to which will be saved the + * received data buffer. + * + * @return Number of received data (in Bytes). + */ +uint32_t USB_SIL_Read(uint8_t bEpAddr, uint8_t* pBufferPointer) +{ + uint32_t DataLength = 0; + + DataLength = GetEPRxCount(bEpAddr & 0x7F); + PMAToUserBufferCopy(pBufferPointer, GetEPRxAddr(bEpAddr & 0x7F), DataLength); + + return DataLength; +} + + + + + + diff --git a/V203F6P6/ch32v203/usbd/usb_desc.h b/V203F6P6/ch32v203/usbd/usb_desc.h new file mode 100644 index 0000000..2fc5976 --- /dev/null +++ b/V203F6P6/ch32v203/usbd/usb_desc.h @@ -0,0 +1,80 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_desc.h + * Author : WCH + * Version : V1.0.0 + * Date : 2021/08/08 + * Description : This file contains all the functions prototypes for the + * USB description 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 __USB_DESC_H +#define __USB_DESC_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include +/* 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 + +#define DEF_USBD_REPORT_DESC_LEN 0 + +#define DEF_MAX_STRINGS (4) + +#define USB_DEVICE_DESCRIPTOR_TYPE 0x01 +#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02 +#define USB_STRING_DESCRIPTOR_TYPE 0x03 +#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04 +#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05 + +#define DEF_USBD_UEP0_SIZE 64 +#define DEF_USBD_MAX_PACK_SIZE 64 + +#define USBD_SIZE_DEVICE_DESC ((uint16_t) USBD_DeviceDescriptor[0]) +#define USBD_SIZE_CONFIG_DESC ((uint16_t)(USBD_ConfigDescriptor[2] + ((uint16_t)(USBD_ConfigDescriptor[3]) << 8))) +#define USBD_SIZE_STRING_LANGID ((uint16_t) USBD_StringLangID [0]) +#define USBD_SIZE_STRING_VENDOR ((uint16_t) USBD_StringVendor [0]) +#define USBD_SIZE_STRING_PRODUCT ((uint16_t) USBD_StringProduct[0]) +#define USBD_SIZE_STRING_SERIAL ((uint16_t) USBD_StringSerial [0]) + +extern const uint8_t USBD_DeviceDescriptor[]; +extern const uint8_t USBD_ConfigDescriptor[]; + +extern const uint8_t * USBD_StringLangID; +extern const uint8_t * USBD_StringVendor; +extern const uint8_t * USBD_StringProduct; +extern const uint8_t * USBD_StringSerial; + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_DESC_H */ diff --git a/V203F6P6/common/ctrlinterface.h b/V203F6P6/common/ctrlinterface.h new file mode 100644 index 0000000..ca6bc9d --- /dev/null +++ b/V203F6P6/common/ctrlinterface.h @@ -0,0 +1,30 @@ +#ifndef CTRLINTERFACE_DEF_H +#define CTRLINTERFACE_DEF_H +#include +enum CTRL_TYPES_DEF { + UNKNOWN_TYPE = 0, + USB_USART_SET_PARAM, + USB_USART_SET_DTR_RTS, + USB_USART_INIT, +}; +static_assert (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__, "Bad ENDIAN"); +struct USB_CDC_LineCoding { + uint32_t baud; + uint8_t stop, parity, data; + explicit USB_CDC_LineCoding () noexcept : baud (57600u), stop (0u), parity (0u), data (8u) {} +}__attribute__((packed)); +static_assert (sizeof(USB_CDC_LineCoding) == 7, "USB_CDC_LineCoding size error"); +/** @class CtrlInterface + * Abstraktní interface, které je možné podědit třeba ve třídě USART a pomocí + * jediné virtuální metody zadefinovat chování při událostech měnících parametry + * přenosu, přicházejících po USB. Fakticky místo callback funkce, nutí to + * IOCtrl() opravdu přetížit. + * Je to mimo třídu BaseLayer, protože Up třída nemusí být totožná s kontrolní. + * V cdc_class se proto musí nastavit na toto ukazatel pomocí metody attach(). + * */ +class CDC_CtrlInterface { + public: + virtual bool IOCtrl (const CTRL_TYPES_DEF type, const void * data, const uint32_t len) = 0; +}; + +#endif // CTRLINTERFACE_DEF_H diff --git a/V203F6P6/common/mirror.h b/V203F6P6/common/mirror.h new file mode 100644 index 0000000..26f48ce --- /dev/null +++ b/V203F6P6/common/mirror.h @@ -0,0 +1,60 @@ +#ifndef MIRROR_H +#define MIRROR_H + +#include +#include "baselayer.h" + +/** + * @file + * @brief Obraceč datového toku. + * @class Mirror + * @brief Obraceč datového toku má 2 třídy. + * + * TwoTop je vlastní obraceč, dědí vlastnosti BaseLayer, pouze metoda Up je přetížena - + * to je to vlastní převrácení. Hlavní třída Mirror, jejíž instance je pak v kódu použita + * obsahuje 2 rovnocenné instance třídy TwoTop, které musí být ve stacku vždy navrchu. + * První část stacku volá Up jedné instance, druhá Up té druhé. Proto tam musí být dvě. + * Podobně by šel udělat něco jako Fork, odbočení datového toku. + + * A zase - všechny metody jsou tak jednoduché, že jsou celé v hlavičce, tedy inline. + * + * @class TwoTop + * @brief Vlastní obraceč. + * Ono to vypadá hodně zmateně, ale používá se to snadno - dokonce to funguje. + * +*/ + +class TwoTop : public BaseLayer { + public: + /// Konstruktor + explicit TwoTop () noexcept : BaseLayer (), x (nullptr) {}; + /// Setter pro x + void setX (BaseLayer & bl) { x = & bl; }; + /// Přetížení metody Up, nic jiného není potřeba + uint32_t Up (const char* data, uint32_t len) { + if (!x) return 0; // pro jistotu + // To, co přišlo zespoda, pošlu druhou instancí zase dolů + return x->Down (data, len); + }; + private: + /// Fakticky ukazatel na druhou instanci TwoTop + BaseLayer * x; +}; + +class Mirror { + public: + /// Konstruktor + explicit Mirror () noexcept : L(), R() { + L.setX (R); R.setX (L); + }; + /** + Zřetězení voláme 2x. Poprvé pro jednu +=, podruhé -= pro druhou instanci TwoTop. + Protože je tato třída navrchu (vlevo), operátor nic nevrací. + */ + void operator += (BaseLayer& bl) { L += bl; return; }; + void operator -= (BaseLayer& bl) { R += bl; return; }; + private: + TwoTop L, R; //!< 2 instance Top +}; + +#endif // MIRROR_H diff --git a/V203F6P6/common/usart.h b/V203F6P6/common/usart.h index 9c761e5..8d9c9e6 100644 --- a/V203F6P6/common/usart.h +++ b/V203F6P6/common/usart.h @@ -2,6 +2,7 @@ #define USART_H #include "fifo.h" #include "baselayer.h" +#include "ctrlinterface.h" /** @class Usart * @brief Sériový port. * @@ -10,11 +11,13 @@ * Tady u toho typu je pin řízení směru přenosu dělán čistě softwarově, * překrytí je minimální, zdá se že to nevadí. */ -class Usart : public BaseLayer { +class Usart : public BaseLayer, public CDC_CtrlInterface { FIFO tx_ring; public: - explicit Usart (const uint32_t baud = 9600) noexcept; - uint32_t Down (const char * data, const uint32_t len) override; + explicit Usart (const uint32_t baud = 9600) noexcept; + void setBaud (const uint32_t baud); + uint32_t Down (const char * data, const uint32_t len) override; + bool IOCtrl (const CTRL_TYPES_DEF type, const void * data, const uint32_t len) override; void irq (void); }; diff --git a/V203F6P6/usart/Makefile b/V203F6P6/usart/Makefile index 20bee8e..fd93a44 100644 --- a/V203F6P6/usart/Makefile +++ b/V203F6P6/usart/Makefile @@ -9,15 +9,15 @@ VPATH = . ./$(TARGET) ./common BLD = ./build/ DFLAGS = -d LFLAGS = -g -LDLIBS = +LDLIBS = -L./$(TARGET)/usbd -lusbd BFLAGS = --strip-unneeded CFLAGS = -MMD -Wall -Wno-parentheses -ggdb -fno-exceptions -ffunction-sections -fdata-sections -CFLAGS+= -I. -I./$(TARGET) -I./common +CFLAGS+= -I. -I./$(TARGET) -I./$(TARGET)/usbd -I./common DEL = rm -f # zdrojaky -OBJS = main.o usart.o print.o +OBJS = main.o usart.o usb_desc.o #OBJS += include $(TARGET)/$(TOOL).mk diff --git a/V203F6P6/usart/main.cpp b/V203F6P6/usart/main.cpp index 191eb7a..3a6f979 100644 --- a/V203F6P6/usart/main.cpp +++ b/V203F6P6/usart/main.cpp @@ -1,59 +1,35 @@ #include "system.h" #include "gpio.h" #include "usart.h" -#include "print.h" +#include "cdc_class.h" +#include "mirror.h" /********************************************************************************* Sériový port na CH32V203F6P6 je příklad jak by z dokumentace člověka klepla pepka. Podle DS to má jen jeden sériový port, ale vývody USART1 nejsou nijak vyvedeny -z pouzdra. Tak zkusíte USART2, a ejhle, ono to funguje. +z pouzdra. Tak zkusíte USART2, a ejhle, ono to funguje. + +Pro testování USB v režimu device to bylo předěláno na převodník USB na RS485. +Funguje nastavení baudové rychlosti, ostatní parametry jsou ignorovány a pevně +na 8 bitů 1 stop, bez parity. USB má jen jedinou třídu CDC, původní zdroj je +šíleně komplikovaný, takže je to zabaleno do knihovny libusbd.a, vnitřkem tedy +celkem není nutné se zabývat. **********************************************************************************/ -#if 0 -class TEST : public BaseLayer { // Testovací třída pro test příjmu - OK. - static constexpr unsigned buflen = 64u; - char buffer [buflen]; - unsigned rx_index; - GpioClass & led; -public: - explicit TEST (GpioClass & io) noexcept : BaseLayer(), rx_index(0u), led(io) {} - uint32_t Up(const char * data, const uint32_t len) override { - for (unsigned n=0u; n> 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 USBD_ConfigDescriptor[] = +{ + /* 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, +}; +#define DEF_STRDESC(p,n) w_text<(sizeof(p)>>1)>n={sizeof(n)-2u,3u,{p}} +template struct w_text { + uint8_t len, typ; + const char16_t str [N]; +}; +static const DEF_STRDESC((u"Kizarm Labs."), str_1); +static const DEF_STRDESC((u"USB <=> RS485"),str_2); +static const DEF_STRDESC((u"0001"), str_3); +/* Language Descriptor */ +static const uint8_t LangDescr[] = { + 0x04, 0x03, 0x09, 0x04 +}; +const uint8_t * USBD_StringLangID = reinterpret_cast(LangDescr); +const uint8_t * USBD_StringVendor = reinterpret_cast(&str_1); +const uint8_t * USBD_StringProduct = reinterpret_cast(&str_2); +const uint8_t * USBD_StringSerial = reinterpret_cast(&str_3); +