From 243ae309cf6a0f7bdf0f474708bd0c953dddaf6d Mon Sep 17 00:00:00 2001 From: true Date: Wed, 6 Nov 2024 19:58:23 -0800 Subject: [PATCH] initial USB CDC+HID vendor code merge merged in example USB CDC + HID code, but removed any comms with actual USART peripheral. this code is not yet tested. once tested and USB enumerates, work can proceed. --- gat_stand_fw/.cproject | 49 +- gat_stand_fw/.settings/language.settings.xml | 2 +- gat_stand_fw/usblib/config/hw_config.c | 162 ++++ gat_stand_fw/usblib/config/hw_config.h | 41 + gat_stand_fw/usblib/config/usb_conf.h | 78 ++ gat_stand_fw/usblib/config/usb_desc.c | 190 ++++ gat_stand_fw/usblib/config/usb_desc.h | 52 + gat_stand_fw/usblib/config/usb_endp.c | 148 +++ gat_stand_fw/usblib/config/usb_istr.c | 201 ++++ gat_stand_fw/usblib/config/usb_istr.h | 77 ++ gat_stand_fw/usblib/config/usb_prop.c | 503 ++++++++++ gat_stand_fw/usblib/config/usb_prop.h | 85 ++ gat_stand_fw/usblib/config/usb_pwr.c | 221 +++++ gat_stand_fw/usblib/config/usb_pwr.h | 75 ++ gat_stand_fw/usblib/driver/inc/usb_core.h | 191 ++++ gat_stand_fw/usblib/driver/inc/usb_def.h | 82 ++ gat_stand_fw/usblib/driver/inc/usb_init.h | 42 + gat_stand_fw/usblib/driver/inc/usb_int.h | 25 + gat_stand_fw/usblib/driver/inc/usb_lib.h | 31 + gat_stand_fw/usblib/driver/inc/usb_mem.h | 36 + gat_stand_fw/usblib/driver/inc/usb_regs.h | 675 +++++++++++++ gat_stand_fw/usblib/driver/inc/usb_sil.h | 36 + gat_stand_fw/usblib/driver/inc/usb_type.h | 34 + gat_stand_fw/usblib/driver/src/usb_core.c | 954 +++++++++++++++++++ gat_stand_fw/usblib/driver/src/usb_init.c | 42 + gat_stand_fw/usblib/driver/src/usb_int.c | 133 +++ gat_stand_fw/usblib/driver/src/usb_mem.c | 74 ++ gat_stand_fw/usblib/driver/src/usb_regs.c | 852 +++++++++++++++++ gat_stand_fw/usblib/driver/src/usb_sil.c | 77 ++ gat_stand_fw/user/main.c | 8 + gat_stand_fw/user/usb/cdc.c | 347 +++++++ gat_stand_fw/user/usb/cdc.h | 91 ++ 32 files changed, 5566 insertions(+), 48 deletions(-) create mode 100644 gat_stand_fw/usblib/config/hw_config.c create mode 100644 gat_stand_fw/usblib/config/hw_config.h create mode 100644 gat_stand_fw/usblib/config/usb_conf.h create mode 100644 gat_stand_fw/usblib/config/usb_desc.c create mode 100644 gat_stand_fw/usblib/config/usb_desc.h create mode 100644 gat_stand_fw/usblib/config/usb_endp.c create mode 100644 gat_stand_fw/usblib/config/usb_istr.c create mode 100644 gat_stand_fw/usblib/config/usb_istr.h create mode 100644 gat_stand_fw/usblib/config/usb_prop.c create mode 100644 gat_stand_fw/usblib/config/usb_prop.h create mode 100644 gat_stand_fw/usblib/config/usb_pwr.c create mode 100644 gat_stand_fw/usblib/config/usb_pwr.h create mode 100644 gat_stand_fw/usblib/driver/inc/usb_core.h create mode 100644 gat_stand_fw/usblib/driver/inc/usb_def.h create mode 100644 gat_stand_fw/usblib/driver/inc/usb_init.h create mode 100644 gat_stand_fw/usblib/driver/inc/usb_int.h create mode 100644 gat_stand_fw/usblib/driver/inc/usb_lib.h create mode 100644 gat_stand_fw/usblib/driver/inc/usb_mem.h create mode 100644 gat_stand_fw/usblib/driver/inc/usb_regs.h create mode 100644 gat_stand_fw/usblib/driver/inc/usb_sil.h create mode 100644 gat_stand_fw/usblib/driver/inc/usb_type.h create mode 100644 gat_stand_fw/usblib/driver/src/usb_core.c create mode 100644 gat_stand_fw/usblib/driver/src/usb_init.c create mode 100644 gat_stand_fw/usblib/driver/src/usb_int.c create mode 100644 gat_stand_fw/usblib/driver/src/usb_mem.c create mode 100644 gat_stand_fw/usblib/driver/src/usb_regs.c create mode 100644 gat_stand_fw/usblib/driver/src/usb_sil.c create mode 100644 gat_stand_fw/user/usb/cdc.c create mode 100644 gat_stand_fw/user/usb/cdc.h diff --git a/gat_stand_fw/.cproject b/gat_stand_fw/.cproject index ae0dcd8..1ebc6a9 100644 --- a/gat_stand_fw/.cproject +++ b/gat_stand_fw/.cproject @@ -60,10 +60,10 @@ - - - - - + diff --git a/gat_stand_fw/.settings/language.settings.xml b/gat_stand_fw/.settings/language.settings.xml index a2c60cd..9270c16 100644 --- a/gat_stand_fw/.settings/language.settings.xml +++ b/gat_stand_fw/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/gat_stand_fw/usblib/config/hw_config.c b/gat_stand_fw/usblib/config/hw_config.c new file mode 100644 index 0000000..cdd2242 --- /dev/null +++ b/gat_stand_fw/usblib/config/hw_config.c @@ -0,0 +1,162 @@ +/********************************** (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 "hw_config.h" + +#include +#include +#include + +#include "../driver/inc/usb_lib.h" + +#include "usb_desc.h" +#include "usb_istr.h" +#include "usb_prop.h" +#include "usb_pwr.h" + + + +void USBWakeUp_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); +void USB_LP_CAN1_RX0_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); + + + +/******************************************************************************* + * @fn USBWakeUp_IRQHandler + * + * @brief This function handles USB wake up exception. + * + * @return None + */ +void USBWakeUp_IRQHandler(void) +{ + EXTI_ClearITPendingBit(EXTI_Line18); +} + +/******************************************************************************* + * @fn USB_LP_CAN1_RX0_IRQHandler + * + * @brief This function handles USB exception. + * + * @return None + */ +void USB_LP_CAN1_RX0_IRQHandler(void) +{ + USB_Istr(); +} + +/******************************************************************************* + * @fn Set_USBConfig + * + * @brief Set_USBConfig . + * + * @return None + */ +void usb_conf_clksource(void) +{ + switch (SystemCoreClock) { + case 144000000: RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div3 ); break; + case 96000000: RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div2 ); break; + case 48000000: RCC_USBCLKConfig( RCC_USBCLKSource_PLLCLK_Div1 ); break; + } + + RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE); +} + +/******************************************************************************* + * @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_Interrupts_Config + * + * @brief Configrate USB interrupt. + * + * @return None + */ +void usb_intr_init(void) +{ + NVIC_InitTypeDef NVIC_InitStructure; + EXTI_InitTypeDef EXTI_InitStructure; + + EXTI_ClearITPendingBit(EXTI_Line18); + EXTI_InitStructure.EXTI_Line = EXTI_Line18; + EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; + EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; + EXTI_InitStructure.EXTI_LineCmd = ENABLE; + EXTI_Init(&EXTI_InitStructure); + + NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + + NVIC_InitStructure.NVIC_IRQChannel = USBWakeUp_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; + NVIC_Init(&NVIC_InitStructure); +} + +/******************************************************************************* + * @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_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); + + if (NewState) { + _SetCNTR(_GetCNTR()&(~(1<<1))); + GPIOA->CFGHR&=0XFFF00FFF; + GPIOA->OUTDR&=~(3<<11); //PA11/12=0 + GPIOA->CFGHR|=0X00044000; //float + } else { + _SetCNTR(_GetCNTR()|(1<<1)); + GPIOA->CFGHR&=0XFFF00FFF; + GPIOA->OUTDR&=~(3<<11); //PA11/12=0 + GPIOA->CFGHR|=0X00033000; // LOW + } + + if(Pin_In_IPU) (EXTEN->EXTEN_CTR) |= EXTEN_USBD_PU_EN; + else (EXTEN->EXTEN_CTR) &= ~EXTEN_USBD_PU_EN; +} diff --git a/gat_stand_fw/usblib/config/hw_config.h b/gat_stand_fw/usblib/config/hw_config.h new file mode 100644 index 0000000..8e3d3ef --- /dev/null +++ b/gat_stand_fw/usblib/config/hw_config.h @@ -0,0 +1,41 @@ +/********************************** (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 + + + +#include + +#include "usb_type.h" + + + +#ifdef USE_PRINTF +#define printf_usb(X...) printf(X) +#else +#define printf_usb(X...) +#endif + + + +void usb_conf_clksource(void); +void usb_intr_init(void); + +void Enter_LowPowerMode(void); +void Leave_LowPowerMode(void); + +void USB_Port_Set(FunctionalState NewState, FunctionalState Pin_In_IPU); + + + +#endif /* __HW_CONFIG_H */ diff --git a/gat_stand_fw/usblib/config/usb_conf.h b/gat_stand_fw/usblib/config/usb_conf.h new file mode 100644 index 0000000..d97dce4 --- /dev/null +++ b/gat_stand_fw/usblib/config/usb_conf.h @@ -0,0 +1,78 @@ +/********************************** (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 + + +#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) +#define ENDP4_TXADDR (ENDP3_TXADDR + 0x40) +#define ENDP4_RXADDR (ENDP4_TXADDR + 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 + +#endif /* __USB_CONF_H */ + + + + + + diff --git a/gat_stand_fw/usblib/config/usb_desc.c b/gat_stand_fw/usblib/config/usb_desc.c new file mode 100644 index 0000000..ccf53c2 --- /dev/null +++ b/gat_stand_fw/usblib/config/usb_desc.c @@ -0,0 +1,190 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usb_desc.c + * Author : WCH + * Version : V1.0.0 + * Date : 2019/10/15 + * Description : USB Descriptors. +********************************************************************************* +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* Attention: This software (modified or not) and binary are used for +* microcontroller manufactured by Nanjing Qinheng Microelectronics. +*******************************************************************************/ +#include "usb_desc.h" + +#include "../driver/inc/usb_lib.h" + +/* USB Device Descriptors */ +const uint8_t USBD_DeviceDescriptor[] = { + USBD_SIZE_DEVICE_DESC, // bLength + 0x01, // bDescriptorType + 0x10, 0x01, // bcdUSB + 0x00, // bDeviceClass + 0x00, // bDeviceSubClass + 0x00, // bDeviceProtocol + DEF_USBD_UEP0_SIZE, // bMaxPacketSize0 + 0x86, 0x1A, // idVendor + 0x0C, 0xFE, // idProduct + 0x00, 0x01, // bcdDevice + 0x01, // iManufacturer + 0x02, // iProduct + 0x00, // iSerialNumber + 0x01, // bNumConfigurations +}; + +/* USB Configration Descriptors */ +const uint8_t USBD_ConfigDescriptor[] = { + /* Configuration Descriptor */ + 0x09, // bLength + 0x02, // bDescriptorType + USBD_SIZE_CONFIG_DESC & 0xFF, USBD_SIZE_CONFIG_DESC >> 8, // wTotalLength + 0x03, // bNumInterfaces + 0x01, // bConfigurationValue + 0x00, // iConfiguration + 0x80, // bmAttributes: Bus Powered; Remote Wakeup + 0x32, // MaxPower: 100mA + + /* IAD Descriptor(interface 0/1)*/ + 0x08, 0x0B, 0x00, 0x02, 0x02, 0x02, 0x01, 0x00, + + /* Interface 0 (CDC) descriptor */ + 0x09, // bLength + 0x04, // bDescriptorType (Interface) + 0x00, // bInterfaceNumber 0 + 0x00, // bAlternateSetting + 0x01, // bNumEndpoints 1 + 0x02, // bInterfaceClass + 0x02, // bInterfaceSubClass + 0x01, // bInterfaceProtocol + 0x00, // iInterface (String Index) + + /* 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, // bLength + 0x05, // bDescriptorType (Endpoint) + 0x81, // bEndpointAddress (IN/D2H) + 0x03, // bmAttributes (Interrupt) + 0x40, 0x00, // wMaxPacketSize 64 + 0x01, // bInterval 1 (unit depends on device speed) + + /* Interface 1 (data interface) descriptor */ + 0x09, // bLength + 0x04, // bDescriptorType (Interface) + 0x01, // bInterfaceNumber 1 + 0x00, // bAlternateSetting + 0x02, // bNumEndpoints 2 + 0x0A, // bInterfaceClass + 0x00, // bInterfaceSubClass + 0x00, // bInterfaceProtocol + 0x00, // iInterface (String Index) + + /* Endpoint descriptor */ + 0x07, // bLength + 0x05, // bDescriptorType (Endpoint) + 0x02, // bEndpointAddress (OUT/H2D) + 0x02, // bmAttributes (Bulk) + 0x40, 0x00, // wMaxPacketSize 64 + 0x00, // bInterval 0 (unit depends on device speed) + + /* Endpoint descriptor */ + 0x07, // bLength + 0x05, // bDescriptorType (Endpoint) + 0x83, // bEndpointAddress (IN/D2H) + 0x02, // bmAttributes (Bulk) + 0x40, 0x00, // wMaxPacketSize 64 + 0x00, // bInterval 0 (unit depends on device speed) + + /* interface 2 (HID interface) descriptor */ + 0x09, // bLength + 0x04, // bDescriptorType (Interface) + 0x02, // bInterfaceNumber 2 + 0x00, // bAlternateSetting + 0x02, // bNumEndpoints 2 + 0x03, // bInterfaceClass + 0x00, // bInterfaceSubClass + 0x00, // bInterfaceProtocol + 0x00, // iInterface (String Index) + + /* interface 2 HID descriptor */ + 0x09, // bLength + 0x21, // bDescriptorType + 0x11, 0x01, // bcdHID + 0x00, // bCountryCode + 0x01, // bNumDescriptors + 0x22, // bDescriptorType + USBD_SIZE_REPORT_DESC & 0xFF, USBD_SIZE_REPORT_DESC >> 8, // wDescriptorLength + + + /* interface 2 endpoint descriptor*/ + 0x07, // bLength + 0x05, // bDescriptorType (Endpoint) + 0x84, // bEndpointAddress (IN/D2H) + 0x03, // bmAttributes (Interrupt) + 0x40, 0x00, // wMaxPacketSize 64 + 0x01, // bInterval 1 (unit depends on device speed) + + /* interface 2 endpoint descriptor */ + 0x07, // bLength + 0x05, // bDescriptorType (Endpoint) + 0x04, // bEndpointAddress (OUT/H2D) + 0x03, // bmAttributes (Interrupt) + 0x40, 0x00, // wMaxPacketSize 64 + 0x01, // bInterval 1 (unit depends on device speed) + +}; + +/* USB String Descriptors */ +const uint8_t USBD_StringLangID[USBD_SIZE_STRING_LANGID] = { + USBD_SIZE_STRING_LANGID, + USB_STRING_DESCRIPTOR_TYPE, + 0x09, + 0x04 +}; + +/* USB Device String Vendor */ +const uint8_t USBD_StringVendor[USBD_SIZE_STRING_VENDOR] = { + USBD_SIZE_STRING_VENDOR, + USB_STRING_DESCRIPTOR_TYPE, + 'w',0,'c',0,'h',0,'.',0,'c',0,'n',0 +}; + +/* USB Device String Product */ +const uint8_t USBD_StringProduct[USBD_SIZE_STRING_PRODUCT] = { + USBD_SIZE_STRING_PRODUCT, + USB_STRING_DESCRIPTOR_TYPE, + 'U', 0, 'S', 0, 'B', 0, ' ', 0, 'S', 0, 'e', 0, 'r', 0, 'i', 0, 'a', 0, 'l', 0}; + +/* USB Device String Serial */ +uint8_t USBD_StringSerial[USBD_SIZE_STRING_SERIAL] = { + USBD_SIZE_STRING_SERIAL, + USB_STRING_DESCRIPTOR_TYPE, + '0', 0, '1', 0, '2', 0, '3', 0, '4', 0, '5', 0 , '6', 0, '7', 0, '8', 0, '9', 0 +}; + +/* HID Report Descriptor */ +const uint8_t USBD_HidRepDesc[USBD_SIZE_REPORT_DESC] = +{ + 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) + 0x09, 0x01, // Usage (0x01) + 0xA1, 0x01, // Collection (Application) + 0x09, 0x02, // Usage (0x02) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x15, 0x00, // Logical Minimum (0) + 0x95, 0x40, // Report Count (64) + 0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) + 0x09, 0x02, // Usage (0x02) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x40, // Report Count (64) + 0x91, 0x06, // Output (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + 0xC0, // End Collection +}; + diff --git a/gat_stand_fw/usblib/config/usb_desc.h b/gat_stand_fw/usblib/config/usb_desc.h new file mode 100644 index 0000000..85976e5 --- /dev/null +++ b/gat_stand_fw/usblib/config/usb_desc.h @@ -0,0 +1,52 @@ +/********************************** (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 + + +#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 18 +#define USBD_SIZE_CONFIG_DESC 107 +#define USBD_SIZE_REPORT_DESC 34 +#define USBD_SIZE_STRING_LANGID 4 +#define USBD_SIZE_STRING_VENDOR 14 +#define USBD_SIZE_STRING_PRODUCT 22 +#define USBD_SIZE_STRING_SERIAL 22 + +extern const uint8_t USBD_DeviceDescriptor[USBD_SIZE_DEVICE_DESC]; +extern const uint8_t USBD_ConfigDescriptor[USBD_SIZE_CONFIG_DESC]; +extern const uint8_t USBD_StringLangID [USBD_SIZE_STRING_LANGID]; +extern const uint8_t USBD_StringVendor [USBD_SIZE_STRING_VENDOR]; +extern const uint8_t USBD_StringProduct[USBD_SIZE_STRING_PRODUCT]; +extern const uint8_t USBD_HidRepDesc[USBD_SIZE_REPORT_DESC]; +extern uint8_t USBD_StringSerial [USBD_SIZE_STRING_SERIAL]; + +#ifdef __cplusplus +} +#endif + +#endif /* __USB_DESC_H */ diff --git a/gat_stand_fw/usblib/config/usb_endp.c b/gat_stand_fw/usblib/config/usb_endp.c new file mode 100644 index 0000000..de0bebe --- /dev/null +++ b/gat_stand_fw/usblib/config/usb_endp.c @@ -0,0 +1,148 @@ +/********************************** (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_mem.h" + +#include "hw_config.h" +#include "usb_desc.h" +#include "usb_istr.h" +#include "usb_prop.h" +#include "usb_pwr.h" + +#include "../../user/usb/cdc.h" + + + +uint8_t USBD_Endp3_Busy; +uint16_t USB_Rx_Cnt = 0; +uint8_t HID_Buffer[DEF_USBD_MAX_PACK_SIZE]; + + + +/********************************************************************* + * @fn EP1_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) +{ + uint32_t len; + len = GetEPRxCount( EP2_OUT & 0x7F ); + PMAToUserBufferCopy( &CDC_Tx_Buf[ ( Cdc.Tx_LoadNum * DEF_USB_FS_PACK_LEN ) ], GetEPRxAddr( EP2_OUT & 0x7F ), len ); + Cdc.Tx_PackLen[ Cdc.Tx_LoadNum ] = len; + Cdc.Tx_LoadNum++; + if( Cdc.Tx_LoadNum >= DEF_CDC_TX_BUF_NUM_MAX ) + { + Cdc.Tx_LoadNum = 0x00; + } + Cdc.Tx_RemainNum++; + + if( Cdc.Tx_RemainNum >= ( DEF_CDC_TX_BUF_NUM_MAX - 2 ) ) + { + Cdc.USB_Down_StopFlag = 0x01; + } + else + { + SetEPRxValid( ENDP2 ); + } +} + + +/********************************************************************* + * @fn EP3_IN_Callback + * + * @brief Endpoint 3 IN. + * + * @return none + */ +void EP3_IN_Callback (void) +{ + USBD_Endp3_Busy = 0; + Cdc.USB_Up_IngFlag = 0x00; + +} + +/********************************************************************* + * @fn EP4_IN_Callback + * + * @brief Endpoint 4 IN. + * + * @return none + */ +void EP4_IN_Callback (void) +{ + +} + +/********************************************************************* + * @fn EP4_OUT_Callback + * + * @brief Endpoint 4 OUT. + * + * @return none + */ +void EP4_OUT_Callback (void) +{ + uint16_t i; + USB_Rx_Cnt = USB_SIL_Read(EP4_IN,HID_Buffer); + for ( i = 0; i < USB_Rx_Cnt; i++) + { + HID_Buffer[i] = ~HID_Buffer[i]; + } + USB_SIL_Write( EP4_OUT, HID_Buffer, USB_Rx_Cnt ); + SetEPTxValid( ENDP4 ); + SetEPRxValid( ENDP4 ); +} + +/********************************************************************* + * @fn USBD_ENDPx_DataUp + * + * @brief USBD ENDPx DataUp Function + * + * @param endp - endpoint num. + * *pbuf - A pointer points to data. + * len - data length to transmit. + * + * @return data up status. + */ +uint8_t USBD_ENDPx_DataUp( uint8_t endp, uint8_t *pbuf, uint16_t len ) +{ + if( endp == ENDP3 ) + { + if (USBD_Endp3_Busy) + { + return USB_ERROR; + } + USB_SIL_Write( EP3_IN, pbuf, len ); + USBD_Endp3_Busy = 1; + SetEPTxStatus( ENDP3, EP_TX_VALID ); + } + else + { + return USB_ERROR; + } + return USB_SUCCESS; +} diff --git a/gat_stand_fw/usblib/config/usb_istr.c b/gat_stand_fw/usblib/config/usb_istr.c new file mode 100644 index 0000000..2e6bc57 --- /dev/null +++ b/gat_stand_fw/usblib/config/usb_istr.c @@ -0,0 +1,201 @@ +/********************************** (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_istr.h" + +#include "../driver/inc/usb_lib.h" +#include "usb_prop.h" +#include "usb_pwr.h" + + + +uint16_t Ep0RxBlks; + +/* Private variables */ +__IO uint16_t wIstr; +__IO uint8_t bIntPackSOF = 0; +__IO uint32_t esof_counter =0; +__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/gat_stand_fw/usblib/config/usb_istr.h b/gat_stand_fw/usblib/config/usb_istr.h new file mode 100644 index 0000000..1a7738a --- /dev/null +++ b/gat_stand_fw/usblib/config/usb_istr.h @@ -0,0 +1,77 @@ +/********************************** (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 + +#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 + + +#endif /*__USB_ISTR_H*/ + + + + + + + + diff --git a/gat_stand_fw/usblib/config/usb_prop.c b/gat_stand_fw/usblib/config/usb_prop.c new file mode 100644 index 0000000..39e7daf --- /dev/null +++ b/gat_stand_fw/usblib/config/usb_prop.c @@ -0,0 +1,503 @@ +/********************************** (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_prop.h" + +#include "hw_config.h" +#include "usb_conf.h" +#include "usb_desc.h" +#include "usb_pwr.h" + +#include "../../user/usb/cdc.h" + + + +uint8_t Request = 0; + +extern uint8_t USBD_Endp3_Busy; +volatile uint8_t HID_Idle_Value[2] = {0}; +volatile uint8_t HID_Protocol_Value[2] = {0}; + +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} +}; + +ONE_DESCRIPTOR Report_Descriptor[1] = +{ + {(uint8_t*)USBD_HidRepDesc, USBD_SIZE_REPORT_DESC}, +}; + +ONE_DESCRIPTOR Hid_Descriptor[1] = +{ + {(uint8_t*)&USBD_ConfigDescriptor[84], 0x09}, +}; + + + +/********************************************************************* + * @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) + { + CDC_USB_Init(); + } + } +} + +/******************************************************************************* + * @fn USBD_Status_Out + * + * @brief USBD Status OUT Routine. + * + * @return None. + */ +void USBD_Status_Out(void) +{ + +} + +/******************************************************************************* + * @fn USBD_init. + * + * @brief init routine. + * + * @return None. + */ +void USBD_init(void) +{ + uint8_t i; + uint32_t timeout; + + 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); + for (timeout = SystemCoreClock >> 5; timeout; timeout--); + 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); + USBD_Endp3_Busy = 0; + + SetEPType(ENDP4, EP_INTERRUPT); + SetEPTxStatus(ENDP4, EP_TX_NAK); + SetEPTxAddr(ENDP4, ENDP4_TXADDR); + SetEPRxAddr(ENDP4, ENDP4_RXADDR); + SetEPRxCount(ENDP4, DEF_USBD_MAX_PACK_SIZE); + SetEPRxStatus(ENDP4, EP_RX_VALID ); + _ClearDTOG_TX(ENDP4); + _ClearDTOG_RX(ENDP4); + + SetDeviceAddress(0); + + USBD_Endp3_Busy = 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 NULL; + } + else + { + return Standard_GetDescriptorData(Length, &String_Descriptor[wValue0]); + } +} + +/********************************************************************* + * @fn USBD_GetReportDescriptor + * + * @brief Gets the report descriptors according to the needed index + * + * @param Length. + * + * @return The address of the device descriptor. + */ +uint8_t *USBD_GetReportDescriptor(uint16_t Length) +{ + return Standard_GetDescriptorData(Length, &Report_Descriptor[0]); +} + +/********************************************************************* + * @fn USBD_GetHidDescriptor + * + * @brief Gets the report descriptors according to the needed index + * + * @param Length. + * + * @return The address of the device descriptor. + */ +uint8_t *USBD_GetHidDescriptor(uint16_t Length) +{ + return Standard_GetDescriptorData(Length, &Hid_Descriptor[0]); +} + +/********************************************************************* + * @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( NULL ); + } + + return (uint8_t *)&Cdc.Com_Cfg[ 0 ]; +} + +/********************************************************************* + * @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( NULL ); + } + return(uint8_t *)&Cdc.Com_Cfg[ 0 ]; +} + + +/********************************************************************* + * @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; + uint8_t *(*CopyRoutine)(uint16_t); + uint8_t wValue1; + + Request_No = pInformation->USBbRequest; + CopyRoutine = NULL; + wValue1 = pInformation->USBwValue1; + + if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) { + if (wValue1 == HID_REPORT_DESCRIPTOR) { + CopyRoutine = USBD_GetReportDescriptor; + } + else if (wValue1 == HID_DESCRIPTOR) { + CopyRoutine = USBD_GetHidDescriptor; + } + + if (CopyRoutine) { + pInformation->Ctrl_Info.CopyData = CopyRoutine; + (*CopyRoutine)(0); + } + else { + 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) { + + } + else if (Request_No == CDC_SEND_BREAK) { + + } + else { + return USB_UNSUPPORT; + } + } + + return USB_SUCCESS; +} diff --git a/gat_stand_fw/usblib/config/usb_prop.h b/gat_stand_fw/usblib/config/usb_prop.h new file mode 100644 index 0000000..c14fcf6 --- /dev/null +++ b/gat_stand_fw/usblib/config/usb_prop.h @@ -0,0 +1,85 @@ +/********************************** (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 + +#include "usb_lib.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 HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0A +#define HID_SET_PROTOCOL 0x0B + +#define HID_DESCRIPTOR 0x21 +#define HID_REPORT_DESCRIPTOR 0x22 + + +#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/gat_stand_fw/usblib/config/usb_pwr.c b/gat_stand_fw/usblib/config/usb_pwr.c new file mode 100644 index 0000000..2da7f0e --- /dev/null +++ b/gat_stand_fw/usblib/config/usb_pwr.c @@ -0,0 +1,221 @@ +/********************************** (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_pwr.h" + +#include "usb_lib.h" + +#include "hw_config.h" +#include "usb_conf.h" + + + +__IO uint32_t bDeviceState = UNCONNECTED; +__IO uint8_t 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(void) +{ + _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; + } + } +} diff --git a/gat_stand_fw/usblib/config/usb_pwr.h b/gat_stand_fw/usblib/config/usb_pwr.h new file mode 100644 index 0000000..9c0735c --- /dev/null +++ b/gat_stand_fw/usblib/config/usb_pwr.h @@ -0,0 +1,75 @@ +/********************************** (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" + +#include "usb_lib.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; + + + +extern __IO uint32_t bDeviceState; /* USB device status */ +extern __IO uint8_t fSuspendEnabled; /* true when suspend is possible */ + + + +void Suspend(void); +void Resume_Init(void); +void Resume(RESUME_STATE eResumeSetVal); +RESULT PowerOn(void); +RESULT PowerOff(void); + + + + +#ifdef __cplusplus +} +#endif + +#endif /*__USB_PWR_H*/ + + + + + + diff --git a/gat_stand_fw/usblib/driver/inc/usb_core.h b/gat_stand_fw/usblib/driver/inc/usb_core.h new file mode 100644 index 0000000..685f60a --- /dev/null +++ b/gat_stand_fw/usblib/driver/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/gat_stand_fw/usblib/driver/inc/usb_def.h b/gat_stand_fw/usblib/driver/inc/usb_def.h new file mode 100644 index 0000000..281cd24 --- /dev/null +++ b/gat_stand_fw/usblib/driver/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/gat_stand_fw/usblib/driver/inc/usb_init.h b/gat_stand_fw/usblib/driver/inc/usb_init.h new file mode 100644 index 0000000..edcec85 --- /dev/null +++ b/gat_stand_fw/usblib/driver/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/gat_stand_fw/usblib/driver/inc/usb_int.h b/gat_stand_fw/usblib/driver/inc/usb_int.h new file mode 100644 index 0000000..b3e557f --- /dev/null +++ b/gat_stand_fw/usblib/driver/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 + +void CTR_LP(void); +void CTR_HP(void); + +#endif /* __USB_INT_H */ + + + + + + diff --git a/gat_stand_fw/usblib/driver/inc/usb_lib.h b/gat_stand_fw/usblib/driver/inc/usb_lib.h new file mode 100644 index 0000000..4860f32 --- /dev/null +++ b/gat_stand_fw/usblib/driver/inc/usb_lib.h @@ -0,0 +1,31 @@ +/********************************** (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 "../../usblib/config/hw_config.h" + +#include "usb_core.h" +#include "usb_def.h" +#include "usb_init.h" +#include "usb_int.h" +#include "usb_mem.h" +#include "usb_regs.h" +#include "usb_sil.h" +#include "usb_type.h" + + + +#endif /* __USB_LIB_H */ diff --git a/gat_stand_fw/usblib/driver/inc/usb_mem.h b/gat_stand_fw/usblib/driver/inc/usb_mem.h new file mode 100644 index 0000000..80014cc --- /dev/null +++ b/gat_stand_fw/usblib/driver/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/gat_stand_fw/usblib/driver/inc/usb_regs.h b/gat_stand_fw/usblib/driver/inc/usb_regs.h new file mode 100644 index 0000000..2a7a03b --- /dev/null +++ b/gat_stand_fw/usblib/driver/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/gat_stand_fw/usblib/driver/inc/usb_sil.h b/gat_stand_fw/usblib/driver/inc/usb_sil.h new file mode 100644 index 0000000..5909a99 --- /dev/null +++ b/gat_stand_fw/usblib/driver/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/gat_stand_fw/usblib/driver/inc/usb_type.h b/gat_stand_fw/usblib/driver/inc/usb_type.h new file mode 100644 index 0000000..558a053 --- /dev/null +++ b/gat_stand_fw/usblib/driver/inc/usb_type.h @@ -0,0 +1,34 @@ +/********************************** (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 "../../config/usb_conf.h" + + + +#ifndef NULL +#define NULL ((void *)0) +#endif + +typedef enum +{ + FALSE = 0, TRUE = !FALSE +} +bool; + + + +#endif /* __USB_TYPE_H */ diff --git a/gat_stand_fw/usblib/driver/src/usb_core.c b/gat_stand_fw/usblib/driver/src/usb_core.c new file mode 100644 index 0000000..5be9180 --- /dev/null +++ b/gat_stand_fw/usblib/driver/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 "../../driver/inc/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/gat_stand_fw/usblib/driver/src/usb_init.c b/gat_stand_fw/usblib/driver/src/usb_init.c new file mode 100644 index 0000000..3e6ab66 --- /dev/null +++ b/gat_stand_fw/usblib/driver/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/gat_stand_fw/usblib/driver/src/usb_int.c b/gat_stand_fw/usblib/driver/src/usb_int.c new file mode 100644 index 0000000..a3ffe25 --- /dev/null +++ b/gat_stand_fw/usblib/driver/src/usb_int.c @@ -0,0 +1,133 @@ +/********************************** (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 "../../driver/inc/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])(); + } + } + } +} + +/******************************************************************************* + * @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])(); + } + } +} + + + + + + + + + diff --git a/gat_stand_fw/usblib/driver/src/usb_mem.c b/gat_stand_fw/usblib/driver/src/usb_mem.c new file mode 100644 index 0000000..13ae92d --- /dev/null +++ b/gat_stand_fw/usblib/driver/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 "../../driver/inc/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/gat_stand_fw/usblib/driver/src/usb_regs.c b/gat_stand_fw/usblib/driver/src/usb_regs.c new file mode 100644 index 0000000..14587ae --- /dev/null +++ b/gat_stand_fw/usblib/driver/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 "../../driver/inc/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/gat_stand_fw/usblib/driver/src/usb_sil.c b/gat_stand_fw/usblib/driver/src/usb_sil.c new file mode 100644 index 0000000..d3c8616 --- /dev/null +++ b/gat_stand_fw/usblib/driver/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 "../../driver/inc/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/gat_stand_fw/user/main.c b/gat_stand_fw/user/main.c index d949c29..12acd2e 100644 --- a/gat_stand_fw/user/main.c +++ b/gat_stand_fw/user/main.c @@ -19,6 +19,9 @@ #include "periph/rgbled.h" #include "periph/rtc.h" +#include "usb/cdc.h" +#include "usb_lib.h" + void btn_top_push_cb(uint8_t idx) @@ -142,6 +145,8 @@ int main(void) RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD | RCC_APB2Periph_ADC1, ENABLE); + RCC_AHBPeriphClockCmd( RCC_AHBPeriph_USBHS, ENABLE); + // configure gpio pins gpio_init(); @@ -173,6 +178,9 @@ int main(void) systick_init(); // initialize USB device for console shell + usb_conf_clksource(); + USB_Init(); + usb_intr_init(); // let's do this while (1) { diff --git a/gat_stand_fw/user/usb/cdc.c b/gat_stand_fw/user/usb/cdc.c new file mode 100644 index 0000000..4e07a40 --- /dev/null +++ b/gat_stand_fw/user/usb/cdc.c @@ -0,0 +1,347 @@ +/* + * cdc.c + * + * Created on: Nov 6, 2024 + * Author: true + */ + +#include "cdc.h" + +#include "usb_lib.h" + +#include "../../usblib/config/usb_desc.h" +#include "../../usblib/config/usb_prop.h" + + + +#define USB_TIM TIM4 +#define USB_TIM_IRQn TIM4_IRQn + + + +/*******************************************************************************/ +/* Variable Definition */ +/* Global */ + +/* The following are serial port transmit and receive related variables and buffers */ +volatile CDC_CTL Cdc; + +__attribute__ ((aligned(4))) uint8_t CDC_Tx_Buf[DEF_CDC_TX_BUF_LEN]; /* Serial port 2 transmit data buffer */ +__attribute__ ((aligned(4))) uint8_t CDC_Rx_Buf[DEF_CDC_RX_BUF_LEN]; /* Serial port 2 receive data buffer */ + +extern uint8_t USBD_Endp3_Busy; + + +/********************************************************************* + * @fn USB_TIM_Init + * + * @brief 100us Timer + * 144 * 100 * 13.8888 -----> 100uS + * todo: document why we need this counter. + * + * @return none + */ +void USB_TIM_Init( void ) +{ + TIM_TimeBaseInitTypeDef tim = {0}; + + TIM_DeInit(USB_TIM); + + /* Time base configuration */ + tim.TIM_Period = 100 - 1; + tim.TIM_Prescaler = SystemCoreClock / 1000000 - 1; + tim.TIM_ClockDivision = 0; + tim.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseInit(USB_TIM, &tim); + + /* Clear USB_TIM update pending flag */ + TIM_ClearFlag(USB_TIM, TIM_FLAG_Update); + + /* TIM IT enable */ + TIM_ITConfig(USB_TIM, TIM_IT_Update, ENABLE); + + /* Enable Interrupt */ + NVIC_EnableIRQ(USB_TIM_IRQn); + + /* USB_TIM enable counter */ + TIM_Cmd(USB_TIM, ENABLE); +} + +/********************************************************************* + * @fn UART2_ParaInit + * + * @brief Cdc2 parameters initialization + * mode = 0 : Used in usb modify initialization + * mode = 1 : Used in default initializations + * @return none + */ +void CDC_ParaInit(uint8_t mode) +{ + uint8_t i; + + Cdc.Rx_LoadPtr = 0x00; + Cdc.Rx_DealPtr = 0x00; + Cdc.Rx_RemainLen = 0x00; + Cdc.Rx_TimeOut = 0x00; + Cdc.Rx_TimeOutMax = 30; + + Cdc.Tx_LoadNum = 0x00; + Cdc.Tx_DealNum = 0x00; + Cdc.Tx_RemainNum = 0x00; + + for(i = 0; i < DEF_CDC_TX_BUF_NUM_MAX; i++) { + Cdc.Tx_PackLen[ i ] = 0x00; + } + + Cdc.Tx_Flag = 0x00; + Cdc.Tx_CurPackLen = 0x00; + Cdc.Tx_CurPackPtr = 0x00; + + Cdc.USB_Up_IngFlag = 0x00; + Cdc.USB_Up_TimeOut = 0x00; + Cdc.USB_Up_Pack0_Flag = 0x00; + Cdc.USB_Down_StopFlag = 0x00; + + if(mode) { + Cdc.Com_Cfg[ 0 ] = (uint8_t)( DEF_CDC_BAUDRATE ); + Cdc.Com_Cfg[ 1 ] = (uint8_t)( DEF_CDC_BAUDRATE >> 8 ); + Cdc.Com_Cfg[ 2 ] = (uint8_t)( DEF_CDC_BAUDRATE >> 16 ); + Cdc.Com_Cfg[ 3 ] = (uint8_t)( DEF_CDC_BAUDRATE >> 24 ); + Cdc.Com_Cfg[ 4 ] = DEF_CDC_STOPBIT; + Cdc.Com_Cfg[ 5 ] = DEF_CDC_PARITY; + Cdc.Com_Cfg[ 6 ] = DEF_CDC_DATABIT; + Cdc.Com_Cfg[ 7 ] = DEF_CDC_RX_TIMEOUT; + } +} + +/********************************************************************* + * @fn CDC_USB_Init + * + * @brief CDC initialization in usb interrupt + * + * @return none + */ +void CDC_USB_Init(void) +{ + uint32_t baudrate; + uint8_t stopbits __attribute__((unused)); + uint8_t parity __attribute__((unused)); + + baudrate = ( uint32_t )( Cdc.Com_Cfg[ 3 ] << 24 ) + ( uint32_t )( Cdc.Com_Cfg[ 2 ] << 16 ); + baudrate += ( uint32_t )( Cdc.Com_Cfg[ 1 ] << 8 ) + ( uint32_t )( Cdc.Com_Cfg[ 0 ] ); + stopbits = Cdc.Com_Cfg[ 4 ]; + parity = Cdc.Com_Cfg[ 5 ]; + + // this is the point where you would apply these settings. + // since we are virtual only with no real UART, there is nothing to do here. + // UART2_Init( 0, baudrate, stopbits, parity ); +} + +/********************************************************************* + * @fn UART2_DataTx_Process + * + * @brief Cdc2 data transmission processing + * + * @return none + */ +void CDC_DataTx_Process( void ) +{ + // uint16_t count; + + /* uart1 transmission processing */ + if( Cdc.Tx_Flag ) { + // process incoming data from the host. + + /* + // Query whether the DMA transmission of the serial port is completed + if( USART2->STATR & USART_FLAG_TC ) + { + USART2->STATR = (uint16_t)( ~USART_FLAG_TC ); + USART2->CTLR3 &= ( ~USART_DMAReq_Tx ); + + Cdc.Tx_Flag = 0x00; + + NVIC_DisableIRQ( USB_LP_CAN1_RX0_IRQn ); + NVIC_DisableIRQ( USB_HP_CAN1_TX_IRQn ); + + // Calculate the variables of last data + count = Cdc.Tx_CurPackLen - DEF_UART2_TX_DMA_CH->CNTR; + Cdc.Tx_CurPackLen -= count; + Cdc.Tx_CurPackPtr += count; + if( Cdc.Tx_CurPackLen == 0x00 ) + { + Cdc.Tx_PackLen[ Cdc.Tx_DealNum ] = 0x0000; + Cdc.Tx_DealNum++; + if( Cdc.Tx_DealNum >= DEF_CDC_TX_BUF_NUM_MAX ) + { + Cdc.Tx_DealNum = 0x00; + } + Cdc.Tx_RemainNum--; + } + + // If the current serial port has suspended the downlink, restart the driver downlink + if( ( Cdc.USB_Down_StopFlag == 0x01 ) && ( Cdc.Tx_RemainNum < 2 ) ) + { + SetEPRxValid( ENDP2 ); + Cdc.USB_Down_StopFlag = 0x00; + } + */ + + NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); + NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn); + //} + } + else + { + // Load data from the serial port send buffer to send + if(Cdc.Tx_RemainNum) { + // Determine whether to load from the last unsent buffer or from a new buffer + if( Cdc.Tx_CurPackLen == 0x00 ) { + Cdc.Tx_CurPackLen = Cdc.Tx_PackLen[ Cdc.Tx_DealNum ]; + Cdc.Tx_CurPackPtr = ( Cdc.Tx_DealNum * DEF_USB_FS_PACK_LEN ); + } + + // todo: figure out wtf all this does. + /* + // Configure DMA and send + USART_ClearFlag( USART2, USART_FLAG_TC ); + DMA_Cmd( DEF_UART2_TX_DMA_CH, DISABLE ); + DEF_UART2_TX_DMA_CH->MADDR = (uint32_t)&UART2_Tx_Buf[ Cdc.Tx_CurPackPtr ]; + DEF_UART2_TX_DMA_CH->CNTR = Cdc.Tx_CurPackLen; + DMA_Cmd( DEF_UART2_TX_DMA_CH, ENABLE ); + USART2->CTLR3 |= USART_DMAReq_Tx; + Cdc.Tx_Flag = 0x01; + */ + } + } +} + +/********************************************************************* + * @fn UART2_DataRx_Deal + * + * @brief Cdc2 data receiving processing + * + * @return none + */ +void CDC_DataRx_Process( void ) +{ + // uint16_t temp16; + // uint32_t remain_len; + // uint16_t packlen; + + /* Serial port 1 data DMA receive processing */ + NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn); + NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn); + + // process sending data over USB to the host. + /* + CDC_Rx_DMACurCount = DEF_UART2_RX_DMA_CH->CNTR; + if( CDC_Rx_DMALastCount != CDC_Rx_DMACurCount ) + + { + if( CDC_Rx_DMALastCount > CDC_Rx_DMACurCount ) + { + temp16 = CDC_Rx_DMALastCount - CDC_Rx_DMACurCount; + } + else + { + temp16 = DEF_CDC_RX_BUF_LEN - CDC_Rx_DMACurCount; + temp16 += CDC_Rx_DMALastCount; + } + CDC_Rx_DMALastCount = CDC_Rx_DMACurCount; + if( ( Cdc.Rx_RemainLen + temp16 ) > DEF_CDC_RX_BUF_LEN ) + { + // Overflow handling + // Save frame error status + printf("U0_O:%08lx\n",(uint32_t)Cdc.Rx_RemainLen); + } + else + { + Cdc.Rx_RemainLen += temp16; + } + + // Setting reception status + Cdc.Rx_TimeOut = 0x00; + } + */ + + NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); + NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn); + + /*****************************************************************/ + /* Serial port 1 data processing via USB upload and reception */ + if( Cdc.Rx_RemainLen ) { + if( Cdc.USB_Up_IngFlag == 0 ) { + // todo: figure out wtf this does. + /* + // Calculate the length of this upload + remain_len = Cdc.Rx_RemainLen; + packlen = 0x00; + if( remain_len >= DEF_USBD_MAX_PACK_SIZE ) { + packlen = DEF_USBD_MAX_PACK_SIZE; + } + else { + if( Cdc.Rx_TimeOut >= Cdc.Rx_TimeOutMax ) { + packlen = remain_len; + } + } + + if( packlen > ( DEF_CDC_RX_BUF_LEN - Cdc.Rx_DealPtr ) ) { + packlen = ( DEF_CDC_RX_BUF_LEN - Cdc.Rx_DealPtr ); + } + + // Upload serial data via usb + if( packlen ) { + NVIC_DisableIRQ( USB_LP_CAN1_RX0_IRQn ); + NVIC_DisableIRQ( USB_HP_CAN1_TX_IRQn ); + Cdc.USB_Up_IngFlag = 0x01; + Cdc.USB_Up_TimeOut = 0x00; + USBD_ENDPx_DataUp( ENDP3, &UART2_Rx_Buf[ Cdc.Rx_DealPtr], packlen); + // Calculate the variables of interest + Cdc.Rx_RemainLen -= packlen; + Cdc.Rx_DealPtr += packlen; + if( Cdc.Rx_DealPtr >= DEF_CDC_RX_BUF_LEN ) + { + Cdc.Rx_DealPtr = 0x00; + } + + // Start 0-length packet timeout timer + if( packlen == DEF_CDC_RX_BUF_LEN ) + { + Cdc.USB_Up_Pack0_Flag = 0x01; + } + + NVIC_EnableIRQ( USB_LP_CAN1_RX0_IRQn ); + NVIC_EnableIRQ( USB_HP_CAN1_TX_IRQn ); + } + */ + } + else { + /* Set the upload success flag directly if the upload is not successful after the timeout */ + if(Cdc.USB_Up_TimeOut >= DEF_CDC_USB_UP_TIMEOUT) { + Cdc.USB_Up_IngFlag = 0x00; + USBD_Endp3_Busy = 0; + } + } + } + + /*****************************************************************/ + /* Determine if a 0-length packet needs to be uploaded (required for CDC mode) */ + if( Cdc.USB_Up_Pack0_Flag ) { + if( Cdc.USB_Up_IngFlag == 0 ) { + if( Cdc.USB_Up_TimeOut >= ( DEF_CDC_RX_TIMEOUT * 20 ) ) { + NVIC_DisableIRQ( USB_LP_CAN1_RX0_IRQn ); + NVIC_DisableIRQ( USB_HP_CAN1_TX_IRQn ); + Cdc.USB_Up_IngFlag = 0x01; + Cdc.USB_Up_TimeOut = 0x00; + + USBD_ENDPx_DataUp( ENDP3, &CDC_Rx_Buf[ Cdc.Rx_DealPtr], 0); + + Cdc.USB_Up_IngFlag = 0; + Cdc.USB_Up_Pack0_Flag = 0x00; + NVIC_EnableIRQ( USB_LP_CAN1_RX0_IRQn ); + NVIC_EnableIRQ( USB_HP_CAN1_TX_IRQn ); + } + } + } +} diff --git a/gat_stand_fw/user/usb/cdc.h b/gat_stand_fw/user/usb/cdc.h new file mode 100644 index 0000000..eb8a9a2 --- /dev/null +++ b/gat_stand_fw/user/usb/cdc.h @@ -0,0 +1,91 @@ +/* + * cdc.h + * + * Created on: Nov 6, 2024 + * Author: true + */ + +#ifndef USER_USB_CDC_H_ +#define USER_USB_CDC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + +#include +#include + + + +/******************************************************************************/ +/* Related macro definitions */ +/* Serial buffer related definitions */ +#define DEF_CDC_RX_BUF_LEN ( 4 * 512 ) /* Serial x receive buffer size */ +#define DEF_CDC_TX_BUF_LEN ( 2 * 512 ) /* Serial x transmit buffer size */ +#define DEF_USB_FS_PACK_LEN 64 /* USB full speed mode packet size for serial x data */ +#define DEF_CDC_TX_BUF_NUM_MAX (DEF_CDC_TX_BUF_LEN / DEF_USB_FS_PACK_LEN) /* Serial x transmit buffer size */ + +/* Serial port receive timeout related macro definition */ +#define DEF_CDC_BAUDRATE 115200 /* Default baud rate for serial port */ +#define DEF_CDC_STOPBIT 0 /* Default stop bit for serial port */ +#define DEF_CDC_PARITY 0 /* Default parity bit for serial port */ +#define DEF_CDC_DATABIT 8 /* Default data bit for serial port */ +#define DEF_CDC_RX_TIMEOUT 30 /* Serial port receive timeout, in 100uS */ +#define DEF_CDC_USB_UP_TIMEOUT 60000 /* Serial port receive upload timeout, in 100uS */ + + +/************************************************************/ +/* Serial port X related structure definition */ +typedef struct __attribute__((packed)) _UART_CTL +{ + uint16_t Rx_LoadPtr; /* Serial x data receive buffer load pointer */ + uint16_t Rx_DealPtr; /* Pointer to serial x data receive buffer processing */ + volatile uint16_t Rx_RemainLen; /* Remaining unprocessed length of the serial x data receive buffer */ + uint8_t Rx_TimeOut; /* Serial x data receive timeout */ + uint8_t Rx_TimeOutMax; /* Serial x data receive timeout maximum */ + + volatile uint16_t Tx_LoadNum; /* Serial x data send buffer load number */ + volatile uint16_t Tx_DealNum; /* Serial x data send buffer processing number */ + volatile uint16_t Tx_RemainNum; /* Serial x data send buffer remaining unprocessed number */ + volatile uint16_t Tx_PackLen[DEF_CDC_TX_BUF_NUM_MAX]; /* The current packet length of the serial x data send buffer */ + uint8_t Tx_Flag; /* Serial x data send status */ + uint8_t Recv1; + uint16_t Tx_CurPackLen; /* The current packet length sent by serial port x */ + uint16_t Tx_CurPackPtr; /* Pointer to the packet currently being sent by serial port x */ + + uint8_t USB_Up_IngFlag; /* Serial xUSB packet being uploaded flag */ + uint8_t Recv2; + uint16_t USB_Up_TimeOut; /* Serial xUSB packet upload timeout timer */ + uint8_t USB_Up_Pack0_Flag; /* Serial xUSB data needs to upload 0-length packet flag */ + uint8_t USB_Down_StopFlag; /* Serial xUSB packet stop down flag */ + + uint8_t Com_Cfg[ 8 ]; /* Serial x parameter configuration (default baud rate is 115200, 1 stop bit, no parity, 8 data bits) */ + uint8_t Recv3; + uint8_t USB_Int_UpFlag; /* Serial x interrupt upload status */ + uint16_t USB_Int_UpTimeCount; /* Serial x interrupt upload timing */ +} CDC_CTL, *PCDC_CTL; + +/***********************************************************************************************************************/ +/* Constant, variable extents */ +/* The following are serial port transmit and receive related variables and buffers */ +extern volatile CDC_CTL Cdc; /* Serial x control related structure */ +extern __attribute__ ((aligned(4))) uint8_t CDC_Tx_Buf[DEF_CDC_TX_BUF_LEN]; /* Serial x transmit buffer */ +extern __attribute__ ((aligned(4))) uint8_t CDC_Rx_Buf[DEF_CDC_RX_BUF_LEN]; /* Serial x transmit buffer */ + +/***********************************************************************************************************************/ + + + +void CDC_USB_Init(void); +void CDC_DataTx_Process( void ); /* Serial port 1 data sending processing */ +void CDC_DataRx_Process( void ); /* Serial port 1 data reception processing */ + + + +#ifdef __cplusplus +} +#endif + +#endif /* USER_USB_CDC_H_ */