Jonas Thörnblad 9828e1d51b
Raise UART IRQ priority and tune USB polling period
Set UART1 IRQ to high priority to not miss any incoming bytes
and tune USB polling period (bInterval).
2025-01-23 13:47:53 +01:00

1525 lines
79 KiB
C

/********************************** (C) COPYRIGHT *******************************
* File Name : CDC.C
* Author : WCH
* Version : V1.0
* Date : 2017/03/01
* Description : CH554 as CDC device to serial port, select serial port 1
*******************************************************************************/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <ch554.h>
#include <ch554_usb.h>
#include "debug.h"
#include "mem.h"
#include "print.h"
#include "usb_strings.h"
XDATA AT0000 uint8_t Ep0Buffer[3*MAX_PACKET_SIZE] = { 0 }; // Endpoint 0, Default endpoint, OUT & IN buffer[64], must be an even address +
// Endpoint 4, TKEYCTRL, buffer OUT[64]+IN[64], must be an even address
XDATA AT00C0 uint8_t Ep1Buffer[DEFAULT_EP1_SIZE] = { 0 }; // Endpoint 1, CDC Ctrl, IN[8] buffer
XDATA AT00C8 uint8_t Ep2Buffer[2*MAX_PACKET_SIZE] = { 0 }; // Endpoint 2, CDC Data, buffer OUT[64]+IN[64], must be an even address
XDATA AT0148 uint8_t Ep3Buffer[2*MAX_PACKET_SIZE] = { 0 }; // Endpoint 3, HID, buffer OUT[64]+IN[64], must be an even address
uint16_t SetupLen = 0;
uint8_t SetupReq = 0;
uint8_t UsbConfig = 0;
const uint8_t *pDescr = NULL; // USB configuration flag
USB_SETUP_REQ SetupReqBuf = { 0 }; // Temporary Setup package
#define UsbSetupBuf ((PUSB_SETUP_REQ)Ep0Buffer)
#define CDC_CTRL_EPOUT_ADDR 0x01 // CDC Ctrl Endpoint OUT Address
#define CDC_CTRL_EPOUT_SIZE DEFAULT_EP1_SIZE // CDC Ctrl Endpoint OUT Size
#define CDC_CTRL_EPIN_ADDR 0x81 // CDC Ctrl Endpoint IN Address
#define CDC_CTRL_EPIN_SIZE DEFAULT_EP1_SIZE // CDC Ctrl Endpoint IN Size
#define CDC_DATA_EPOUT_ADDR 0x02 // CDC Data Endpoint OUT Address
#define CDC_DATA_EPOUT_SIZE MAX_PACKET_SIZE // CDC Data Endpoint OUT Size
#define CDC_DATA_EPIN_ADDR 0x82 // CDC Data Endpoint IN Address
#define CDC_DATA_EPIN_SIZE MAX_PACKET_SIZE // CDC Data Endpoint IN Size
#define HID_EPOUT_ADDR 0x03 // HID Endpoint OUT Address
#define HID_EPOUT_SIZE MAX_PACKET_SIZE // HID Endpoint OUT Size
#define HID_EPIN_ADDR 0x83 // HID Endpoint IN Address
#define HID_EPIN_SIZE MAX_PACKET_SIZE // HID Endpoint IN Size
#define TKEYCTRL_EPOUT_ADDR 0x04 // TKEYCTRL Endpoint OUT Address
#define TKEYCTRL_EPOUT_SIZE MAX_PACKET_SIZE // TKEYCTRL Endpoint OUT Size
#define TKEYCTRL_EPIN_ADDR 0x84 // TKEYCTRL Endpoint IN Address
#define TKEYCTRL_EPIN_SIZE MAX_PACKET_SIZE // TKEYCTRL Endpoint IN Size
#define CDC_CTRL_FS_BINTERVAL 32 // Gives 32 ms polling interval at Full Speed for interrupt transfers
#define CDC_DATA_FS_BINTERVAL 0 // bInterval is ignored for BULK transfers
#define HID_FS_BINTERVAL 2 // Gives 2 ms polling interval at Full Speed for interrupt transfers
#define TKEYCTRL_FS_BINTERVAL 2 // Gives 2 ms polling interval at Full Speed for interrupt transfers
#define CFGDESC_SIZE 139U // Size of CfgDesc
#define NUM_INTERFACES 4 // Number of interfaces
#define HID_REPORT_DESC_SIZE 47 // Size of HID_ReportDesc
#define TKEYCTRL_REPORT_DESC_SIZE 34 // Size of TKEYCTRL_ReportDesc
#define LOBYTE(x) ((uint8_t)( (x) & 0x00FFU))
#define HIBYTE(x) ((uint8_t)(((x) & 0xFF00U) >> 8U))
// Device Descriptor
FLASH uint8_t DevDesc[] = {
0x12, /* bLength */
USB_DESC_TYPE_DEVICE, /* bDescriptorType: Device */
0x00, /* bcdUSB (low byte), USB Specification Release Number in Binary-Coded Decimal (2.0 is 200h) */
0x02, /* bcdUSB (high byte) USB Specification Release Number in Binary-Coded Decimal (2.0 is 200h) */
USB_DEV_CLASS_MISCELLANEOUS, /* bDeviceClass: Miscellaneous Device Class (Composite) */
0x02, /* bDeviceSubClass: Common Class */
0x01, /* bDeviceProtocol: IAD (Interface Association Descriptor) */
DEFAULT_EP0_SIZE, /* bMaxPacketSize */
0x07, /* idVendor */ // VID LOBYTE
0x12, /* idVendor */ // VID HIBYTE
0x87, /* idProduct */ // PID LOBYTE
0x88, /* idProduct */ // PID HIBYTE
0x00, /* bcdDevice (device release number in binary-coded decimal (BCD) format, low byte, i.e. YY) rel. XX.YY */
0x01, /* bcdDevice (device release number in binary-coded decimal (BCD) format, high byte, i.e. XX) rel. XX.YY */
0x01, /* Index of manufacturer string */
0x02, /* Index of product string */
0x03, /* Index of serial number string */
0x01, /* bNumConfigurations */
};
// Configuration Descriptor
FLASH uint8_t CfgDesc[] = {
/******************** Configuration Descriptor ********************/
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
CFGDESC_SIZE, /* wTotalLength (low byte): Bytes returned */
0x00, /* wTotalLength (high byte): Bytes returned */
NUM_INTERFACES, /* bNumInterfaces: 4 interfaces (1 CDC Ctrl, 1 CDC Data, 1 HID, 1 HID (TKEYCTRL) ) */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
0xA0, /* bmAttributes: Bus powered and Support Remote Wake-up */
0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */
/******************** IAD (Interface Association Descriptor), should be positioned just before the CDC interfaces ********************/
/******************** This is to associate the two CDC interfaces with the CDC class ********************/
/* 9 */
0x08, /* bLength: IAD Descriptor size */
USB_DESC_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType: Interface Association */
0x00, /* bFirstInterface: 0 */
0x02, /* bInterfaceCount: 2 */
0x02, /* bFunctionClass: Communications & CDC Control */
0x02, /* bFunctionSubClass: Abstract Control Model */
0x01, /* bFunctionProtocol: Common AT commands */
0x00, /* iFunction: Index of string descriptor */
/******************** Interface 0, CDC Ctrl Descriptor (one endpoint) ********************/
/* 17 */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
0x00, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x01, /* bNumEndpoints */
USB_DEV_CLASS_CDC_CONTROL, /* bInterfaceClass: Communications and CDC Control */
0x02, /* bInterfaceSubClass : Abstract Control Model */
0x01, /* bInterfaceProtocol : AT Commands: V.250 etc */
0x04, /* iInterface: Index of string descriptor */
/******************** Header Functional Descriptor ********************/
/* 26 */
0x05, /* bFunctionLength: Size of this descriptor in bytes */
USB_DESC_TYPE_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE (24h) */
0x00, /* bDescriptorSubtype: Header Functional Descriptor */
0x10, /* bcdCDC (low byte): CDC version 1.10 */
0x01, /* bcdCDC (high byte): CDC version 1.10 */
/******************** Call Management Functional Descriptor (no data interface, bmCapabilities=03, bDataInterface=01) ********************/
/* 31 */
0x05, /* bFunctionLength: Size of this descriptor */
USB_DESC_TYPE_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE (24h) */
0x01, /* bDescriptorSubtype: Call Management Functional Descriptor */
0x00, /* bmCapabilities:
D7..2: 0x00 (RESERVED,
D1 : 0x00 (0 - Device sends/receives call management information only over the Communications Class interface
1 - Device can send/receive call management information over a Data Class interface)
D0 : 0x00 (0 - Device does not handle call management itself
1 - Device handles call management itself) */
0x00, /* bDataInterface: Interface number of Data Class interface optionally used for call management */
/******************** Abstract Control Management Functional Descriptor ********************/
/* 36 */
0x04, /* bLength */
0x24, /* bDescriptorType: CS_INTERFACE (24h) */
0x02, /* bDescriptorSubtype: Abstract Control Management Functional Descriptor */
0x02, /* bmCapabilities:
D7..4: 0x00 (RESERVED, Reset to zero)
D3 : 0x00 (1 - Device supports the notification Network_Connection)
D2 : 0x00 (1 - Device supports the request Send_Break)
D1 : 0x01 (1 - Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State)
D0 : 0x00 (1 - Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature) */
/******************** Union Functional Descriptor. CDC Ctrl interface numbered 0; CDC Data interface numbered 1 ********************/
/* 40 */
0x05, /* bLength */
0x24, /* bDescriptorType: CS_INTERFACE (24h) */
0x06, /* bDescriptorSubtype: Union Functional Descriptor */
0x00, /* bControlInterface: Interface number 0 (Control interface) */
0x01, /* bSubordinateInterface0: Interface number 1 (Data interface) */
/******************** CDC Ctrl Endpoint descriptor (IN) ********************/
/* 45 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_CTRL_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */
USB_EP_TYPE_INTERRUPT, /* bmAttributes: Interrupt Endpoint */
LOBYTE(CDC_CTRL_EPIN_SIZE), /* wMaxPacketSize (low byte): 8 Byte max */
HIBYTE(CDC_CTRL_EPIN_SIZE), /* wMaxPacketSize (high byte): 8 Byte max */
CDC_CTRL_FS_BINTERVAL, /* bInterval: Polling Interval */
/******************** Interface 1, CDC Data Descriptor (two endpoints) ********************/
/* 52 */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
0x01, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints */
USB_DEV_CLASS_CDC_DATA, /* bInterfaceClass: CDC Data */
0x00, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x00, /* bInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0x05, /* iInterface: Index of string descriptor */
/******************** CDC Data Endpoint descriptor (OUT) ********************/
/* 61 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_DATA_EPOUT_ADDR, /* bEndpointAddress: Endpoint Address (OUT) */
USB_EP_TYPE_BULK, /* bmAttributes: Bulk Endpoint */
LOBYTE(CDC_DATA_EPOUT_SIZE), /* wMaxPacketSize (low byte): 64 Byte max */
HIBYTE(CDC_DATA_EPOUT_SIZE), /* wMaxPacketSize (high byte): 64 Byte max */
CDC_DATA_FS_BINTERVAL, /* bInterval: Polling Interval */
/******************** CDC Data Endpoint descriptor (IN) ********************/
/* 68 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
CDC_DATA_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */
USB_EP_TYPE_BULK, /* bmAttributes: Bulk Endpoint */
LOBYTE(CDC_DATA_EPIN_SIZE), /* wMaxPacketSize (low byte): 64 Byte max */
HIBYTE(CDC_DATA_EPIN_SIZE), /* wMaxPacketSize (high byte): 64 Byte max */
CDC_DATA_FS_BINTERVAL, /* bInterval: Polling Interval */
/******************** Interface 2, HID Descriptor (two endpoints) ********************/
/* 75 */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
0x02, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: 2 */
USB_DEV_CLASS_HID, /* bInterfaceClass: Human Interface Device */
0x00, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x00, /* bInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0x06, /* iInterface: Index of string descriptor */
/******************** HID Device Descriptor ********************/
/* 84 */
0x09, /* bLength: HID Descriptor size */
USB_DESC_TYPE_HID, /* bDescriptorType: HID */
0x11, /* bcdHID (low byte): HID Class Spec release number */
0x01, /* bcdHID (high byte): HID Class Spec release number */
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
USB_DESC_TYPE_REPORT, /* bDescriptorType: Report */
LOBYTE(HID_REPORT_DESC_SIZE), /* wDescriptorLength (low byte): Total length of Report descriptor */
HIBYTE(HID_REPORT_DESC_SIZE), /* wDescriptorLength (high byte): Total length of Report descriptor */
/******************** HID Endpoint Descriptor (OUT) ********************/
/* 93 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
HID_EPOUT_ADDR, /* bEndpointAddress: Endpoint Address (OUT) */
USB_EP_TYPE_INTERRUPT, /* bmAttributes: Interrupt endpoint */
LOBYTE(HID_EPOUT_SIZE), /* wMaxPacketSize (low byte): 64 Byte max */
HIBYTE(HID_EPOUT_SIZE), /* wMaxPacketSize (high byte): 64 Byte max */
HID_FS_BINTERVAL, /* bInterval: Polling Interval */
/******************** HID Endpoint Descriptor (IN) ********************/
/* 100 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
HID_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */
USB_EP_TYPE_INTERRUPT, /* bmAttributes: Interrupt endpoint */
LOBYTE(HID_EPIN_SIZE), /* wMaxPacketSize (low byte): 64 Byte max */
HIBYTE(HID_EPIN_SIZE), /* wMaxPacketSize (high byte): 64 Byte max */
HID_FS_BINTERVAL, /* bInterval: Polling Interval */
/******************** Interface 3, HID (TKEYCTRL) Descriptor (two endpoints) ********************/
/* 107 */
0x09, /* bLength: Interface Descriptor size */
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
0x03, /* bInterfaceNumber: Number of Interface */
0x00, /* bAlternateSetting: Alternate setting */
0x02, /* bNumEndpoints: 2 */
USB_DEV_CLASS_HID, /* bInterfaceClass: Human Interface Device */
0x00, /* bInterfaceSubClass : 1=BOOT, 0=no boot */
0x00, /* bInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */
0x07, /* iInterface: Index of string descriptor */
/******************** HID (TKEYCTRL) Device Descriptor ********************/
/* 116 */
0x09, /* bLength: HID Descriptor size */
USB_DESC_TYPE_HID, /* bDescriptorType: HID */
0x11, /* bcdHID (low byte): HID Class Spec release number */
0x01, /* bcdHID (high byte): HID Class Spec release number */
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
USB_DESC_TYPE_REPORT, /* bDescriptorType: Report */
LOBYTE(TKEYCTRL_REPORT_DESC_SIZE),/* wDescriptorLength (low byte): Total length of Report descriptor */
HIBYTE(TKEYCTRL_REPORT_DESC_SIZE),/* wDescriptorLength (high byte): Total length of Report descriptor */
/******************** HID (TKEYCTRL) Endpoint Descriptor (OUT) ********************/
/* 125 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
TKEYCTRL_EPOUT_ADDR, /* bEndpointAddress: Endpoint Address (OUT) */
USB_EP_TYPE_INTERRUPT, /* bmAttributes: Interrupt endpoint */
LOBYTE(TKEYCTRL_EPOUT_SIZE), /* wMaxPacketSize (low byte): 64 Byte max */
HIBYTE(TKEYCTRL_EPOUT_SIZE), /* wMaxPacketSize (high byte): 64 Byte max */
TKEYCTRL_FS_BINTERVAL, /* bInterval: Polling Interval */
/******************** HID (TKEYCTRL) Endpoint Descriptor (IN) ********************/
/* 132 */
0x07, /* bLength: Endpoint Descriptor size */
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
TKEYCTRL_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */
USB_EP_TYPE_INTERRUPT, /* bmAttributes: Interrupt endpoint */
LOBYTE(TKEYCTRL_EPIN_SIZE), /* wMaxPacketSize (low byte): 64 Byte max */
HIBYTE(TKEYCTRL_EPIN_SIZE), /* wMaxPacketSize (high byte): 64 Byte max */
TKEYCTRL_FS_BINTERVAL, /* bInterval: Polling Interval */
/* 139 */
};
// HID Device Descriptor (copy from CfgDesc)
FLASH uint8_t HID_CfgDesc[] = {
0x09, /* bLength: HID Descriptor size */
USB_DESC_TYPE_HID, /* bDescriptorType: HID */
0x11, /* bcdHID (low byte): HID Class Spec release number */
0x01, /* bcdHID (high byte): HID Class Spec release number */
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
USB_DESC_TYPE_REPORT, /* bDescriptorType: Report */
LOBYTE(HID_REPORT_DESC_SIZE), /* wDescriptorLength (low byte): Total length of Report descriptor */
HIBYTE(HID_REPORT_DESC_SIZE), /* wDescriptorLength (high byte): Total length of Report descriptor */
};
FLASH uint8_t HID_ReportDesc[] ={
0x06, 0xD0, 0xF1, /* Usage Page (FIDO Alliance Page) */
0x09, 0x01, /* Usage (U2F Authenticator Device) */
0xA1, 0x01, /* Collection (Application) */
/* 7 */
0x09, 0x20, /* Usage (Input Report Data) */
0x15, 0x00, /* Logical Minimum (0) */
0x26, 0xFF, 0x00, /* Logical Maximum (255) */
0x75, 0x08, /* Report Size (8) */
0x95, MAX_PACKET_SIZE, /* Report Count (64) */
0x81, 0x02, /* Input (Data, Variable, Absolute); */
/* 20 */
0x09, 0x21, /* Usage (Output Report Data) */
0x15, 0x00, /* Logical Minimum (0) */
0x26, 0xFF, 0x00, /* Logical Maximum (255) */
0x75, 0x08, /* Report Size (8) */
0x95, MAX_PACKET_SIZE, /* Report Count (64) */
0x91, 0x02, /* Output (Data, Variable, Absolute) */
/* 33 */
0x09, 0x07, /* Usage (7, Reserved) */
0x15, 0x00, /* Logical Minimum (0) */
0x26, 0xFF, 0x00, /* Logical Maximum (255) */
0x75, 0x08, /* Report Size (8) */
0x95, 0x08, /* Report Count (8) */
0xB1, 0x02, /* Feature (2) (???) */
/* 46 */
0xC0 /* End Collection */
/* 47 */
};
// TKEYCTRL Device Descriptor (copy from CfgDesc)
FLASH uint8_t TKEYCTRL_CfgDesc[] = {
0x09, /* bLength: HID Descriptor size */
USB_DESC_TYPE_HID, /* bDescriptorType: HID */
0x11, /* bcdHID (low byte): HID Class Spec release number */
0x01, /* bcdHID (high byte): HID Class Spec release number */
0x00, /* bCountryCode: Hardware target country */
0x01, /* bNumDescriptors: Number of HID class descriptors to follow */
USB_DESC_TYPE_REPORT, /* bDescriptorType: Report */
LOBYTE(TKEYCTRL_REPORT_DESC_SIZE),/* wDescriptorLength (low byte): Total length of Report descriptor */
HIBYTE(TKEYCTRL_REPORT_DESC_SIZE),/* wDescriptorLength (high byte): Total length of Report descriptor */
};
// TKEYCTRL Report Descriptor
FLASH uint8_t TKEYCTRL_ReportDesc[] ={
0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined 0xFF00) */
0x09, 0x01, /* Usage (Vendor Usage 1) */
0xA1, 0x01, /* Collection (Application) */
/* 7 */
0x09, 0x02, /* Usage (Output Report Data), 0x02 defines that the output report carries raw data from the host to the device. */
0x15, 0x00, /* Logical Minimum (0) */
0x26, 0xFF, 0x00, /* Logical Maximum (255) */
0x75, 0x08, /* Report Size (8 bits) */
0x95, MAX_PACKET_SIZE, /* Report Count (64 bytes) */
0x91, 0x02, /* Output (Data, Variable, Absolute) */
/* 20 */
0x09, 0x03, /* Usage (Input Report), 0x03 defines that the input report carries raw data for the host. */
0x15, 0x00, /* Logical Minimum (0) */
0x26, 0xFF, 0x00, /* Logical Maximum (255) */
0x75, 0x08, /* Report Size (8 bits) */
0x95, MAX_PACKET_SIZE, /* Report Count (64 bytes) */
0x81, 0x02, /* Input (Data, Variable, Absolute) */
/* 33 */
0xC0 /* End Collection */
/* 34 */
};
// String Descriptor (Language descriptor )
FLASH uint8_t LangDesc[] = {
4, // Length of this descriptor (in bytes)
0x03, // Descriptor type (String)
0x09, 0x04, // Language ID (English - US)
};
// CDC Parameters: The initial baud rate is 500000, 1 stop bit, no parity, 8 data bits.
XDATA uint8_t LineCoding[7] = { 0x20, 0xA1, 0x07, 0x00, /* Data terminal rate, in bits per second: 500000 */
0x00, /* Stop bits: 0 - 1 Stop bit, 1 - 1.5 Stop bits, 2 - 2 Stop bits */
0x00, /* Parity: 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space */
0x08, /* Data bits (5, 6, 7, 8 or 16) */
};
#define TKEYCTRL_FRAME_SIZE 64
#define HID_FRAME_SIZE 64
#define MAX_CDC_FRAME_SIZE 64
#define UART_TX_BUF_SIZE 64 // Serial transmit buffer
#define UART_RX_BUF_SIZE 140 // Serial receive buffer
/** Communication UART */
XDATA uint8_t UartTxBuf[UART_TX_BUF_SIZE] = { 0 }; // Serial transmit buffer
volatile IDATA uint8_t Ep2ByteLen;
volatile IDATA uint8_t Ep3ByteLen;
volatile IDATA uint8_t Ep4ByteLen;
XDATA uint8_t UartRxBuf[UART_RX_BUF_SIZE] = { 0 }; // Serial receive buffer
volatile IDATA uint8_t UartRxBufInputPointer = 0; // Circular buffer write pointer, bus reset needs to be initialized to 0
volatile IDATA uint8_t UartRxBufOutputPointer = 0; // Take pointer out of circular buffer, bus reset needs to be initialized to 0
volatile IDATA uint8_t UartRxBufByteCount = 0; // Number of unprocessed bytes remaining in the buffer
volatile IDATA uint8_t UartRxBufOverflow = 0;
/** Debug UART */
#define DEBUG_UART_RX_BUF_SIZE 8
XDATA uint8_t DebugUartRxBuf[DEBUG_UART_RX_BUF_SIZE] = { 0 };
volatile IDATA uint8_t DebugUartRxBufInputPointer = 0;
volatile IDATA uint8_t DebugUartRxBufOutputPointer = 0;
volatile IDATA uint8_t DebugUartRxBufByteCount = 0;
/** Endpoint handling */
volatile IDATA uint8_t UsbEp2ByteCount = 0; // Represents the data received by USB endpoint 2 (CDC)
volatile IDATA uint8_t UsbEp3ByteCount = 0; // Represents the data received by USB endpoint 3 (HID)
volatile IDATA uint8_t UsbEp4ByteCount = 0; // Represents the data received by USB endpoint 4 (TKEYCTRL)
volatile IDATA uint8_t Endpoint2UploadBusy = 0; // Whether the upload endpoint 2 (CDC) is busy
volatile IDATA uint8_t Endpoint3UploadBusy = 0; // Whether the upload endpoint 3 (HID) is busy
volatile IDATA uint8_t Endpoint4UploadBusy = 0; // Whether the upload endpoint 4 (TKEYCTRL) is busy
/** TKEYCTRL variables */
XDATA uint8_t TkeyCtrlRxBuf[TKEYCTRL_FRAME_SIZE] = { 0 };
IDATA uint8_t TkeyCtrlRxBufLength = 0;
IDATA uint8_t TkeyCtrlDataAvailable = 0;
/** CDC variables */
XDATA uint8_t CdcRxBuf[MAX_CDC_FRAME_SIZE] = { 0 };
IDATA uint8_t CdcRxBufLength = 0;
IDATA uint8_t CdcDataAvailable = 0;
/** HID variables */
XDATA uint8_t HidRxBuf[HID_FRAME_SIZE] = { 0 };
IDATA uint8_t HidRxBufLength = 0;
IDATA uint8_t HidDataAvailable = 0;
/** Frame data */
#define MODE_TKEYCTRL 0x20
#define MODE_CDC 0x40
#define MODE_HID 0x80
#define MODE_MASK 0xC0
#define NUM_MASK 0x3F
volatile IDATA uint8_t FrameMode = 0;
volatile IDATA uint8_t FrameLength = 0;
volatile IDATA uint8_t FrameRemainingBytes = 0;
volatile IDATA uint8_t FrameStarted = 0;
volatile IDATA uint8_t Halted = 0;
uint32_t increment_pointer(uint32_t pointer, uint32_t increment, uint32_t buffer_size);
uint32_t decrement_pointer(uint32_t pointer, uint32_t decrement, uint32_t buffer_size);
void cts_start(void);
void cts_stop(void);
void check_cts_stop(void);
/*******************************************************************************
* Function Name : USBDeviceCfg()
* Description : USB device mode configuration
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void USBDeviceCfg()
{
USB_CTRL = 0x00; // Clear USB control register
USB_CTRL &= ~bUC_HOST_MODE; // This bit selects the device mode
USB_CTRL |= bUC_DEV_PU_EN | bUC_INT_BUSY | bUC_DMA_EN; // USB device and internal pull-up enable, automatically return to NAK before interrupt flag is cleared
USB_DEV_AD = 0x00; // Device address initialization
#if 0
// USB_CTRL |= bUC_LOW_SPEED;
// UDEV_CTRL |= bUD_LOW_SPEED; // Select low speed 1.5M mode
#else
USB_CTRL &= ~bUC_LOW_SPEED;
UDEV_CTRL &= ~bUD_LOW_SPEED; // Select full speed 12M mode, the default mode
#endif
UDEV_CTRL = bUD_PD_DIS; // Disable DP / DM pull-down resistor
UDEV_CTRL |= bUD_PORT_EN; // Enable physical port
}
/*******************************************************************************
* Function Name : USBDeviceIntCfg()
* Description : USB device mode interrupt initialization
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void USBDeviceIntCfg()
{
USB_INT_EN |= bUIE_SUSPEND; // Enable device suspend interrupt
USB_INT_EN |= bUIE_TRANSFER; // Enable USB transfer completion interrupt
USB_INT_EN |= bUIE_BUS_RST; // Enable device mode USB bus reset interrupt
USB_INT_FG |= (UIF_FIFO_OV | UIF_HST_SOF | UIF_SUSPEND | UIF_TRANSFER | UIF_BUS_RST ); // Clear interrupt flag
IE_USB = 1; // Enable USB interrupt
EA = 1; // Allow microcontroller interrupt
}
/*******************************************************************************
* Function Name : USBDeviceEndPointCfg()
* Description : USB device mode endpoint configuration, simulation compatible
* HID device, in addition to endpoint 0 control transmission,
* also includes endpoint 2 batch upload
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void USBDeviceEndPointCfg()
{
// TODO: Is casting the right thing here? What about endianness?
UEP0_DMA = (uint16_t) Ep0Buffer; // Endpoint 0 data transfer address, Endpoint 4
UEP1_DMA = (uint16_t) Ep1Buffer; // Endpoint 1 sends data transfer address
UEP2_DMA = (uint16_t) Ep2Buffer; // Endpoint 2 IN data transfer address
UEP3_DMA = (uint16_t) Ep3Buffer; // Endpoint 3 IN data transfer address
UEP4_1_MOD = bUEP4_TX_EN | bUEP4_RX_EN | bUEP1_TX_EN; // Endpoint 0 single 8-byte send and receive buffer
// Endpoint 1, transmit enable
// Endpoint 4, single buffer, transmit+receive enable
UEP2_3_MOD = bUEP2_TX_EN | bUEP2_RX_EN | bUEP3_TX_EN | bUEP3_RX_EN; // Endpoint 2, single buffer, transmit+receive enable
// Endpoint 3, single buffer, transmit+receive enable
UEP0_CTRL = UEP_T_RES_NAK | UEP_R_RES_ACK; // Endpoint 0, manual flip, OUT transaction returns ACK, IN transaction returns NAK
UEP1_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK; // Endpoint 1, automatically flips the synchronization flag, IN transaction returns NAK
UEP2_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK; // Endpoint 2, automatically flips the synchronization flag, IN transaction returns NAK, OUT returns ACK
UEP3_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK; // Endpoint 3, automatically flips the synchronization flag, IN transaction returns NAK, OUT returns ACK
UEP4_CTRL = UEP_T_RES_NAK | UEP_R_RES_ACK; // Endpoint 4, manual flip, OUT transaction returns ACK, IN transaction returns NAK
}
/*******************************************************************************
* Function Name : Config_Uart1(uint8_t *cfg_uart)
* Description : Configure serial port 1 parameters
* Input : Serial port configuration parameters Four bit baud rate, stop bit, parity, data bit
* Output : None
* Return : None
*******************************************************************************/
void Config_Uart1(uint8_t *cfg_uart)
{
uint32_t uart1_baud = 0;
*((uint8_t*) &uart1_baud) = cfg_uart[0];
*((uint8_t*) &uart1_baud + 1) = cfg_uart[1];
*((uint8_t*) &uart1_baud + 2) = cfg_uart[2];
*((uint8_t*) &uart1_baud + 3) = cfg_uart[3];
SBAUD1 = 256 - FREQ_SYS / 16 / uart1_baud; // SBAUD1 = 256 - Fsys / 16 / baud rate
IE_UART1 = 1; // Enable UART1 interrupt
}
void usb_irq_setup_handler(void)
{
uint16_t len = USB_RX_LEN;
printStrSetup("Setup ");
if (len == (sizeof(USB_SETUP_REQ))) {
SetupLen = ((uint16_t) UsbSetupBuf->wLengthH << 8) | (UsbSetupBuf->wLengthL);
len = 0; // Defaults to success and uploading 0 length
SetupReq = UsbSetupBuf->bRequest;
// Class-Specific Requests, i.e. HID request, CDC request etc.
if ((UsbSetupBuf->bmRequestType & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD) {
printStrSetup("Class-Specific ");
printStrSetup("SetupReq=");
printStrSetup("0x");
printNumHexSetup(SetupReq);
printStrSetup(" ");
switch(SetupReq) {
case USB_HID_REQ_TYPE_GET_REPORT:
printStrSetup("HID Get Report\n");
break;
case USB_HID_REQ_TYPE_GET_IDLE:
printStrSetup("HID Get Idle\n");
break;
case USB_HID_REQ_TYPE_GET_PROTOCOL:
printStrSetup("HID Get Protocol\n");
break;
case USB_HID_REQ_TYPE_SET_REPORT:
printStrSetup("HID Set Report\n");
break;
case USB_HID_REQ_TYPE_SET_IDLE:
printStrSetup("HID Set Idle\n");
break;
case USB_HID_REQ_TYPE_SET_PROTOCOL:
printStrSetup("HID Set Protocol\n");
break;
case USB_CDC_REQ_TYPE_SET_LINE_CODING:
printStrSetup("CDC Set Line Coding\n");
break;
case USB_CDC_REQ_TYPE_GET_LINE_CODING:
printStrSetup("CDC Get Line Coding\n");
pDescr = LineCoding;
len = sizeof(LineCoding);
len = SetupLen >= DEFAULT_EP0_SIZE ? DEFAULT_EP0_SIZE : SetupLen; // The length of this transmission
memcpy(Ep0Buffer, pDescr, len);
SetupLen -= len;
pDescr += len;
break;
case USB_CDC_REQ_TYPE_SET_CONTROL_LINE_STATE: // Generates RS-232/V.24 style control signals
printStrSetup("CDC Set Control Line State\n");
break;
default:
len = 0xFF; // Command not supported
printStrSetup("Unsupported\n");
break;
}
} // END Non-standard request
else { // Standard Requests
// Request code
switch (SetupReq) {
case USB_GET_DESCRIPTOR: {
switch (UsbSetupBuf->wValueH) {
case USB_DESC_TYPE_DEVICE: // Device descriptor
pDescr = DevDesc; // Send the device descriptor to the buffer to be sent
len = sizeof(DevDesc);
printStrSetup("DevDesc\n");
break;
case USB_DESC_TYPE_CONFIGURATION: // Configuration descriptor
pDescr = CfgDesc; // Send the configuration descriptor to the buffer to be sent
len = sizeof(CfgDesc);
printStrSetup("CfgDesc\n");
break;
case USB_DESC_TYPE_STRING: // String descriptors
if (UsbSetupBuf->wValueL == USB_IDX_LANGID_STR) {
pDescr = LangDesc;
len = sizeof(LangDesc);
printStrSetup("LangDesc\n");
} else if (UsbSetupBuf->wValueL == USB_IDX_MFC_STR) {
pDescr = ManufDesc;
len = sizeof(ManufDesc);
printStrSetup("ManufDesc\n");
} else if (UsbSetupBuf->wValueL == USB_IDX_PRODUCT_STR) {
pDescr = ProdDesc;
len = sizeof(ProdDesc);
printStrSetup("ProdDesc\n");
} else if (UsbSetupBuf->wValueL == USB_IDX_SERIAL_STR) {
pDescr = SerialDesc;
len = sizeof(SerialDesc);
printStrSetup("SerialDesc\n");
} else if (UsbSetupBuf->wValueL == USB_IDX_INTERFACE_CDC_CTRL_STR) {
pDescr = CdcCtrlInterfaceDesc;
len = sizeof(CdcCtrlInterfaceDesc);
printStrSetup("CdcCtrlInterfaceDesc\n");
} else if (UsbSetupBuf->wValueL == USB_IDX_INTERFACE_CDC_DATA_STR) {
pDescr = CdcDataInterfaceDesc;
len = sizeof(CdcDataInterfaceDesc);
printStrSetup("CdcDataInterfaceDesc\n");
} else if (UsbSetupBuf->wValueL == USB_IDX_INTERFACE_FIDO_HID_STR) {
pDescr = FidoHidInterfaceDesc;
len = sizeof(FidoHidInterfaceDesc);
printStrSetup("FidoHidInterfaceDesc\n");
} else if (UsbSetupBuf->wValueL == USB_IDX_INTERFACE_TKEY_CTRL_STR) {
pDescr = TkeyCtrlInterfaceDesc;
len = sizeof(TkeyCtrlInterfaceDesc);
printStrSetup("TkeyCtrlInterfaceDesc\n");
} else {
printStrSetup("Error: USB_DESC_TYPE_STRING\n");
}
break;
case USB_DESC_TYPE_HID:
switch (UsbSetupBuf->wIndexL) {
case 0x02: // Interface 2 (HID)
pDescr = HID_CfgDesc;
len = sizeof(HID_CfgDesc);
printStrSetup("HID_CfgDesc\n");
break;
case 0x03: // Interface 3 (TKEYCTRL)
pDescr = TKEYCTRL_CfgDesc;
len = sizeof(TKEYCTRL_CfgDesc);
printStrSetup("TKEYCTRL_CfgDesc\n");
break;
default:
break;
}
break;
case USB_DESC_TYPE_REPORT:
switch (UsbSetupBuf->wIndexL) {
case 0x02: // Interface 2 (HID)
pDescr = HID_ReportDesc;
len = sizeof(HID_ReportDesc);
printStrSetup("HID_ReportDesc\n");
break;
case 0x03: // Interface 3 (TKEYCTRL)
pDescr = TKEYCTRL_ReportDesc;
len = sizeof(TKEYCTRL_ReportDesc);
printStrSetup("TKEYCTRL_ReportDesc\n");
break;
default:
break;
}
break;
default:
len = 0xFF; // Unsupported command or error
printStrSetup("Unsupported\n");
break;
}
if (SetupLen > len) {
SetupLen = len; // Limit total length
}
len = SetupLen >= DEFAULT_EP0_SIZE ? DEFAULT_EP0_SIZE : SetupLen; // This transmission length
memcpy(Ep0Buffer, pDescr, len); // Copy upload data
SetupLen -= len;
pDescr += len;
}
break;
case USB_SET_ADDRESS:
SetupLen = UsbSetupBuf->wValueL; // Temporary storage of USB device address
printStrSetup("SetAddress\n");
break;
case USB_GET_CONFIGURATION:
Ep0Buffer[0] = UsbConfig;
if (SetupLen >= 1) {
len = 1;
}
printStrSetup("GetConfig\n");
break;
case USB_SET_CONFIGURATION:
UsbConfig = UsbSetupBuf->wValueL;
printStrSetup("SetConfig\n");
break;
case USB_GET_INTERFACE:
printStrSetup("GetInterface\n");
break;
case USB_CLEAR_FEATURE: // Clear Feature
printStrSetup("ClearFeature\n");
if ((UsbSetupBuf->bmRequestType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_DEVICE) { // Remove device
if ((((uint16_t) UsbSetupBuf->wValueH << 8) | UsbSetupBuf->wValueL) == 0x01) {
if (CfgDesc[7] & 0x20) {
// Wake
} else {
len = 0xFF; // Operation failed
printStrSetup("Unsupported\n");
}
} else {
len = 0xFF; // Operation failed
printStrSetup("Unsupported\n");
}
} else if ((UsbSetupBuf->bmRequestType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_ENDP) { // Endpoint
switch (UsbSetupBuf->wIndexL) {
case 0x84:
UEP4_CTRL = (UEP4_CTRL & ~(bUEP_T_TOG | MASK_UEP_T_RES)) | UEP_T_RES_NAK; // Set endpoint 4 IN (TX) NAK
break;
case 0x04:
UEP4_CTRL = (UEP4_CTRL & ~(bUEP_R_TOG | MASK_UEP_R_RES)) | UEP_R_RES_ACK; // Set endpoint 4 OUT (RX) ACK
break;
case 0x83:
UEP3_CTRL = (UEP3_CTRL & ~(bUEP_T_TOG | MASK_UEP_T_RES)) | UEP_T_RES_NAK; // Set endpoint 3 IN (TX) NAK
break;
case 0x03:
UEP3_CTRL = (UEP3_CTRL & ~(bUEP_R_TOG | MASK_UEP_R_RES)) | UEP_R_RES_ACK; // Set endpoint 3 OUT (RX) ACK
break;
case 0x82:
UEP2_CTRL = (UEP2_CTRL & ~(bUEP_T_TOG | MASK_UEP_T_RES)) | UEP_T_RES_NAK; // Set endpoint 2 IN (TX) NACK
break;
case 0x02:
UEP2_CTRL = (UEP2_CTRL & ~(bUEP_R_TOG | MASK_UEP_R_RES)) | UEP_R_RES_ACK; // Set endpoint 2 OUT (RX) ACK
break;
case 0x81:
UEP1_CTRL = (UEP1_CTRL & ~(bUEP_T_TOG | MASK_UEP_T_RES)) | UEP_T_RES_NAK; // Set endpoint 1 IN (TX) NACK
break;
case 0x01:
UEP1_CTRL = (UEP1_CTRL & ~(bUEP_R_TOG | MASK_UEP_R_RES)) | UEP_R_RES_ACK; // Set endpoint 1 OUT (RX) ACK
break;
default:
len = 0xFF; // Unsupported endpoint
printStrSetup("Unsupported\n");
break;
}
} else {
len = 0xFF; // It's not that the endpoint doesn't support it
printStrSetup("Unsupported\n");
}
break;
case USB_SET_FEATURE: // Set Feature
printStrSetup("SetFeature\n");
if (( UsbSetupBuf->bmRequestType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_DEVICE) { // Set up the device
if ((((uint16_t) UsbSetupBuf->wValueH << 8) | UsbSetupBuf->wValueL) == 0x01) {
if (CfgDesc[7] & 0x20) {
printStrSetup("Suspend\n");
while (XBUS_AUX & bUART0_TX) {
; // Wait for sending to complete
}
SAFE_MOD = 0x55;
SAFE_MOD = 0xAA;
WAKE_CTRL = bWAK_BY_USB | bWAK_RXD0_LO | bWAK_RXD1_LO; // USB or RXD0/1 can be woken up when there is a signal
PCON |= PD; // Sleep
SAFE_MOD = 0x55;
SAFE_MOD = 0xAA;
WAKE_CTRL = 0x00;
} else {
len = 0xFF; // Operation failed
}
} else {
len = 0xFF; // Operation failed
}
} else if (( UsbSetupBuf->bmRequestType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_ENDP) { // Set endpoint
if ((((uint16_t) UsbSetupBuf->wValueH << 8) | UsbSetupBuf->wValueL) == 0x00) {
switch (((uint16_t) UsbSetupBuf->wIndexH << 8) | UsbSetupBuf->wIndexL) {
case 0x84:
UEP4_CTRL = (UEP4_CTRL & ~bUEP_T_TOG) | UEP_T_RES_STALL; // Set endpoint 4 IN (TX) Stall (error)
break;
case 0x04:
UEP4_CTRL = (UEP4_CTRL & ~bUEP_R_TOG) | UEP_R_RES_STALL; // Set endpoint 4 OUT (RX) Stall (error)
break;
case 0x83:
UEP3_CTRL = (UEP3_CTRL & ~bUEP_T_TOG) | UEP_T_RES_STALL; // Set endpoint 3 IN (TX) Stall (error)
break;
case 0x03:
UEP3_CTRL = (UEP3_CTRL & ~bUEP_R_TOG) | UEP_R_RES_STALL; // Set endpoint 3 OUT (RX) Stall (error)
break;
case 0x82:
UEP2_CTRL = (UEP2_CTRL & ~bUEP_T_TOG) | UEP_T_RES_STALL; // Set endpoint 2 IN (TX) Stall (error)
break;
case 0x02:
UEP2_CTRL = (UEP2_CTRL & ~bUEP_R_TOG) | UEP_R_RES_STALL; // Set endpoint 2 OUT (RX) Stall (error)
break;
case 0x81:
UEP1_CTRL = (UEP1_CTRL & ~bUEP_T_TOG) | UEP_T_RES_STALL; // Set endpoint 1 IN (TX) Stall (error)
break;
case 0x01:
UEP1_CTRL = (UEP1_CTRL & ~bUEP_R_TOG) | UEP_R_RES_STALL; // Set endpoint 1 OUT (RX) Stall (error)
default:
len = 0xFF; // Operation failed
break;
}
} else {
len = 0xFF; // Operation failed
printStrSetup("Unsupported\n");
}
} else {
len = 0xFF; // Operation failed
printStrSetup("Unsupported\n");
}
break;
case USB_GET_STATUS:
printStrSetup("GetStatus\n");
Ep0Buffer[0] = 0x00;
Ep0Buffer[1] = 0x00;
if (SetupLen >= 2) {
len = 2;
} else {
len = SetupLen;
}
break;
default:
len = 0xFF; // Operation failed
printStrSetup("Unsupported\n");
break;
} // END switch (SetupReq)
} // END Standard request
} else {
len = 0xFF; // Packet length error
}
if (len == 0xFF) {
SetupReq = 0xFF;
UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_STALL | UEP_T_RES_STALL; // STALL
} else if (len <= DEFAULT_EP0_SIZE) { // Upload data or status phase returns 0 length packet
UEP0_T_LEN = len;
UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK; // The default packet is DATA1, return response ACK
} else {
UEP0_T_LEN = 0; // Although it has not yet reached the status stage, it is preset to upload 0-length data packets in advance to prevent the host from entering the status stage early.
UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK; // The default data packet is DATA1, and the response ACK is returned
}
}
/*******************************************************************************
* Function Name : DeviceInterrupt()
* Description : CH559USB interrupt processing function
*******************************************************************************/
#ifdef BUILD_CODE
#define IRQ_USB __interrupt(INT_NO_USB)
#else
#define IRQ_USB
#endif
void DeviceInterrupt(void)IRQ_USB // USB interrupt service routine, using register set 1
{
uint16_t len;
if (UIF_TRANSFER) { // Check USB transfer complete flag
switch (USB_INT_ST & (MASK_UIS_TOKEN | MASK_UIS_ENDP)) {
case UIS_TOKEN_SETUP | 0: // SETUP routine
usb_irq_setup_handler();
break;
case UIS_TOKEN_IN | 0: // Endpoint 0 IN (TX)
switch (SetupReq) {
case USB_GET_DESCRIPTOR:
len = SetupLen >= DEFAULT_EP0_SIZE ? DEFAULT_EP0_SIZE : SetupLen; // The length of this transmission
memcpy(Ep0Buffer, pDescr, len); // Load upload data
SetupLen -= len;
pDescr += len;
UEP0_T_LEN = len;
UEP0_CTRL ^= bUEP_T_TOG; // Sync flag flip
break;
case USB_SET_ADDRESS:
USB_DEV_AD = (USB_DEV_AD & bUDA_GP_BIT) | SetupLen;
UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
break;
default:
UEP0_T_LEN = 0; // The status phase is completed and interrupted or the 0-length data packet is forced to be uploaded to end the control transmission.
UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
break;
}
break;
case UIS_TOKEN_IN | 1: // Endpoint 1 IN (TX), Endpoint interrupts upload
UEP1_T_LEN = 0; // Transmit length must be cleared (Endpoint 1)
UEP1_CTRL = (UEP1_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK; // Default answer NAK
break;
case UIS_TOKEN_IN | 2: // Endpoint 2 IN (TX), Endpoint bulk upload
UEP2_T_LEN = 0; // Transmit length must be cleared (Endpoint 2)
UEP2_CTRL = (UEP2_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK; // Default answer NAK
Endpoint2UploadBusy = 0; // Clear busy flag
break;
case UIS_TOKEN_IN | 3: // Endpoint 3 IN (TX), Endpoint bulk upload
UEP3_T_LEN = 0; // Transmit length must be cleared (Endpoint 3)
UEP3_CTRL = (UEP3_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK; // Default answer NAK
Endpoint3UploadBusy = 0; // Clear busy flag
break;
case UIS_TOKEN_IN | 4: // Endpoint 4 IN (TX), Endpoint bulk upload
UEP4_T_LEN = 0; // Transmit length must be cleared (Endpoint 4)
UEP4_CTRL = (UEP4_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK; // Default answer NAK
UEP4_CTRL ^= bUEP_T_TOG; // Sync flag flip
Endpoint4UploadBusy = 0; // Clear busy flag
break;
case UIS_TOKEN_OUT | 0: // Endpoint 0 OUT (RX)
switch (SetupReq) {
case USB_CDC_REQ_TYPE_SET_LINE_CODING: // We ignore line coding here because baudrate to the FPGA should not change
if (U_TOG_OK) {
UEP0_T_LEN = 0;
UEP0_CTRL |= UEP_R_RES_ACK | UEP_T_RES_ACK; // Prepare to upload 0 packages
}
break;
default:
UEP0_T_LEN = 0;
UEP0_CTRL |= UEP_R_RES_ACK | UEP_T_RES_NAK; // Status phase, responds to IN with NAK
}
break;
case UIS_TOKEN_OUT | 1: // Endpoint 1 OUT (RX), Disabled for now.
// Out-of-sync packets will be dropped
if (U_TOG_OK) {
//UsbEpXByteCount = USB_RX_LEN; // Length of received data
//UEP1_CTRL = (UEP1_CTRL & ~MASK_UEP_R_RES) | UEP_R_RES_NAK; // NAK after receiving a packet of data, the main function finishes processing, and the main function modifies the response mode
}
break;
case UIS_TOKEN_OUT | 2: // Endpoint 2 OUT (RX), Endpoint batch download
// Out-of-sync packets will be dropped
if (U_TOG_OK) {
UsbEp2ByteCount = USB_RX_LEN; // Length of received data
UEP2_CTRL = (UEP2_CTRL & ~MASK_UEP_R_RES) | UEP_R_RES_NAK; // NAK after receiving a packet of data, the main function finishes processing, and the main function modifies the response mode
}
break;
case UIS_TOKEN_OUT | 3: // Endpoint 3 OUT (RX), Endpoint batch download
// Out-of-sync packets will be dropped
if (U_TOG_OK) {
UsbEp3ByteCount = USB_RX_LEN; // Length of received data
UEP3_CTRL = (UEP3_CTRL & ~MASK_UEP_R_RES) | UEP_R_RES_NAK; // NAK after receiving a packet of data, the main function finishes processing, and the main function modifies the response mode
}
break;
case UIS_TOKEN_OUT | 4: // Endpoint 4 OUT (RX), Endpoint batch download
// Out-of-sync packets will be dropped
if (U_TOG_OK) {
UsbEp4ByteCount = USB_RX_LEN; // Length of received data
UEP4_CTRL = (UEP4_CTRL & ~MASK_UEP_R_RES) | UEP_R_RES_NAK; // NAK after receiving a packet of data, the main function finishes processing, and the main function modifies the response mode
UEP4_CTRL ^= bUEP_R_TOG; // Sync flag flip
}
break;
default:
break;
}
UIF_TRANSFER = 0; // Writing 0 clears the interrupt
} else if (UIF_BUS_RST) { // Check device mode USB bus reset interrupt
printStr("Reset\n");
UEP0_CTRL = UEP_T_RES_NAK | UEP_R_RES_ACK;
UEP1_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK;
UEP2_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK;
UEP3_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK;
UEP4_CTRL = UEP_T_RES_NAK | UEP_R_RES_ACK;
USB_DEV_AD = 0x00;
UIF_SUSPEND = 0;
UIF_TRANSFER = 0; // Writing 0 clears the interrupt
UIF_BUS_RST = 0; // Clear interrupt flag
UartRxBufInputPointer = 0; // Circular buffer input pointer
UartRxBufOutputPointer = 0; // Circular buffer read pointer
UartRxBufByteCount = 0; // The number of bytes remaining in the current buffer to be fetched
UsbEp2ByteCount = 0; // USB endpoint 2 (CDC) received length
UsbEp3ByteCount = 0; // USB endpoint 3 (HID) received length
Endpoint2UploadBusy = 0; // Clear busy flag
Endpoint3UploadBusy = 0; // Clear busy flag
FrameMode = 0;
UsbConfig = 0; // Clear configuration values
} else if (UIF_SUSPEND) { // Check USB bus suspend/wake completed
UIF_SUSPEND = 0;
if (USB_MIS_ST & bUMS_SUSPEND) { // Hang
printStr("Suspend\n");
while (XBUS_AUX & bUART0_TX) {
; // Wait for sending to complete
}
SAFE_MOD = 0x55;
SAFE_MOD = 0xAA;
WAKE_CTRL = bWAK_BY_USB | bWAK_RXD0_LO | bWAK_RXD1_LO; // Can be woken up when there is a signal from USB or RXD0/1
PCON |= PD; // Sleep
SAFE_MOD = 0x55;
SAFE_MOD = 0xAA;
WAKE_CTRL = 0x00;
}
} else { // Unexpected IRQ, should not happen
printStr("Unexpected IRQ\n");
USB_INT_FG = 0xFF; // Clear interrupt flag
}
}
/*******************************************************************************
* Function Name : Uart0_ISR()
* Description : Serial debug port receiving interrupt function to realize circular buffer receiving
*******************************************************************************/
#if 1
#ifdef BUILD_CODE
#define IRQ_UART0 __interrupt(INT_NO_UART0)
#else
#define IRQ_UART0
#endif
void Uart0_ISR(void)IRQ_UART0
{
// Check if data has been received
if (RI) {
DebugUartRxBuf[DebugUartRxBufInputPointer++] = SBUF;
if (DebugUartRxBufInputPointer >= DEBUG_UART_RX_BUF_SIZE) {
DebugUartRxBufInputPointer = 0; // Reset write pointer
}
RI = 0;
}
}
uint8_t debug_uart_byte_count()
{
uint8_t in = DebugUartRxBufInputPointer;
uint8_t out = DebugUartRxBufOutputPointer;
if (in < out) {
in = in + DEBUG_UART_RX_BUF_SIZE;
}
return in - out;
}
#endif
/*******************************************************************************
* Function Name : Uart1_ISR()
* Description : Serial port receiving interrupt function to realize circular buffer receiving
*******************************************************************************/
#ifdef BUILD_CODE
#define IRQ_UART1 __interrupt(INT_NO_UART1)
#else
#define IRQ_UART1
#endif
void Uart1_ISR(void)IRQ_UART1
{
// Check if data has been received
if (U1RI) {
UartRxBuf[UartRxBufInputPointer++] = SBUF1;
if (UartRxBufInputPointer == UartRxBufOutputPointer) {
UartRxBufOverflow = 1;
}
if (UartRxBufInputPointer >= UART_RX_BUF_SIZE) {
UartRxBufInputPointer = 0; // Reset write pointer
}
check_cts_stop();
U1RI = 0;
}
}
uint8_t uart_byte_count()
{
uint8_t in = UartRxBufInputPointer;
uint8_t out = UartRxBufOutputPointer;
if (in < out) {
in = in + UART_RX_BUF_SIZE;
}
return in - out;
}
// Copy data from a circular buffer
void circular_copy(uint8_t *dest, uint8_t *src, uint32_t src_size, uint32_t start_pos, uint32_t length) {
// Calculate the remaining space from start_pos to end of buffer
uint32_t remaining_space = src_size - start_pos;
if (length <= remaining_space) {
// If the length to copy doesn't exceed the remaining space, do a single memcpy
memcpy(dest, src + start_pos, length);
} else {
// If the length to copy exceeds the remaining space, split the copy
memcpy(dest, src + start_pos, remaining_space); // Copy from start_pos to end of buffer
memcpy(dest + remaining_space, src, length - remaining_space); // Copy the rest from the beginning of buffer
}
}
// Function to increment a pointer and wrap around the buffer
uint32_t increment_pointer(uint32_t pointer, uint32_t increment, uint32_t buffer_size)
{
return (pointer + increment) % buffer_size;
}
// Function to decrement a pointer and wrap around the buffer
uint32_t decrement_pointer(uint32_t pointer, uint32_t decrement, uint32_t buffer_size)
{
return (pointer + buffer_size - (decrement % buffer_size)) % buffer_size;
}
void cts_start(void)
{
gpio_p1_5_set(); // Signal to FPGA to send more data
}
void cts_stop(void)
{
gpio_p1_5_unset(); // Signal to FPGA to not send more data
}
void check_cts_stop(void)
{
if (uart_byte_count() >= 133) // UartRxBuf is filled to 95% or more
{
cts_stop();
}
}
void main()
{
// Enable GPIO signalling on p1.4 and p1.5
gpio_init_p1_4_in(); // Init GPIO p1.4 to input mode for FPGA_CTS
gpio_init_p1_5_out(); // Init GPIO p1.5 to output mode for CH552_CTS
cts_start(); // Signal OK to send
CfgFsys(); // CH559 clock selection configuration
mDelaymS(5); // Modify the main frequency and wait for the internal crystal to stabilize, which must be added
#if 0
mInitSTDIO(); // Serial port 0, can be used for debugging
#endif
UART1Setup(); // For communication with FPGA
UART1Clean(); // Clean register from spurious data
printStr("\n\nStartup...\n");
USBDeviceCfg();
USBDeviceEndPointCfg(); // Endpoint configuration
USBDeviceIntCfg(); // Interrupt initialization
UEP0_T_LEN = 0; // Transmit length must be cleared (Endpoint 0)
UEP1_T_LEN = 0; // Transmit length must be cleared (Endpoint 1)
UEP2_T_LEN = 0; // Transmit length must be cleared (Endpoint 2)
UEP3_T_LEN = 0; // Transmit length must be cleared (Endpoint 3)
UEP4_T_LEN = 0; // Transmit length must be cleared (Endpoint 4)
while (1) {
if (UsbConfig) {
// Check if Endpoint 2 (CDC) has received data
if (UsbEp2ByteCount) {
Ep2ByteLen = UsbEp2ByteCount; // UsbEp2ByteCount can be maximum 64 bytes
memcpy(UartTxBuf, Ep2Buffer, Ep2ByteLen);
UsbEp2ByteCount = 0;
CH554UART1SendByte(MODE_CDC); // Send CDC mode header
CH554UART1SendByte(Ep2ByteLen); // Send length
CH554UART1SendBuffer(UartTxBuf, Ep2ByteLen);
UEP2_CTRL = (UEP2_CTRL & ~MASK_UEP_R_RES) | UEP_R_RES_ACK; // Enable Endpoint 2 to ACK again
}
// Check if Endpoint 3 (HID) has received data
if (UsbEp3ByteCount) {
Ep3ByteLen = UsbEp3ByteCount; // UsbEp3ByteCount can be maximum 64 bytes
memcpy(UartTxBuf, Ep3Buffer, Ep3ByteLen);
UsbEp3ByteCount = 0;
CH554UART1SendByte(MODE_HID); // Send HID mode header
CH554UART1SendByte(Ep3ByteLen); // Send length (always 64 bytes)
CH554UART1SendBuffer(UartTxBuf, Ep3ByteLen);
UEP3_CTRL = (UEP3_CTRL & ~MASK_UEP_R_RES) | UEP_R_RES_ACK; // Enable Endpoint 3 to ACK again
}
// Check if Endpoint 4 (TKEYCTRL) has received data
if (UsbEp4ByteCount) {
Ep4ByteLen = UsbEp4ByteCount; // UsbEp4ByteCount can be maximum 64 bytes
memcpy(UartTxBuf, Ep0Buffer+64, Ep4ByteLen); // Endpoint 4 receive is at address UEP0_DMA+64
UsbEp4ByteCount = 0;
CH554UART1SendByte(MODE_TKEYCTRL); // Send TKEYCTRL mode header
CH554UART1SendByte(Ep4ByteLen); // Send length (always 64 bytes)
CH554UART1SendBuffer(UartTxBuf, Ep4ByteLen);
UEP4_CTRL = (UEP4_CTRL & ~MASK_UEP_R_RES) | UEP_R_RES_ACK; // Enable Endpoint 4 to ACK again
}
UartRxBufByteCount = uart_byte_count(); // Check amount of data in buffer
if ((UartRxBufByteCount >= 2) && !FrameStarted) { // If we have data and the header is not yet validated
FrameMode = UartRxBuf[UartRxBufOutputPointer]; // Extract frame mode
if ((FrameMode == MODE_CDC) ||
(FrameMode == MODE_HID) ||
(FrameMode == MODE_TKEYCTRL)) {
FrameLength = UartRxBuf[increment_pointer(UartRxBufOutputPointer,
1,
UART_RX_BUF_SIZE)]; // Extract frame length
FrameRemainingBytes = FrameLength;
UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer,
2,
UART_RX_BUF_SIZE); // Start at valid data so skip the mode and length byte
UartRxBufByteCount -= 2; // Subtract the frame mode and frame length bytes from the total byte count
FrameStarted = 1;
} else { // Invalid mode
if (!Halted) {
printStr("Invalid header: 0x");
printNumHex(FrameMode);
printStr(", len = ");
printNumU32(UartRxBuf[increment_pointer(UartRxBufOutputPointer,
1,
UART_RX_BUF_SIZE)]);
printStr("\n");
uint16_t i;
uint8_t print_char_count_out = 0;
for (i=0; i<UART_RX_BUF_SIZE; i++) {
printNumHex(UartRxBuf[increment_pointer(UartRxBufOutputPointer,
i,
UART_RX_BUF_SIZE)]);
print_char_count_out++;
if (print_char_count_out >= 16) {
printStr("\n");
print_char_count_out = 0;
}
}
if (print_char_count_out != 0) {
printStr("\n");
}
printStr("Halting!\n");
Halted = 1;
}
}
}
// Copy TKEYCTRL data from UartRxBuf to TkeyCtrlRxBuf
if (FrameStarted && !TkeyCtrlDataAvailable) {
if (FrameMode == MODE_TKEYCTRL) {
if ((FrameRemainingBytes >= MAX_PACKET_SIZE) &&
(UartRxBufByteCount >= MAX_PACKET_SIZE)) {
circular_copy(TkeyCtrlRxBuf,
UartRxBuf,
UART_RX_BUF_SIZE,
UartRxBufOutputPointer,
MAX_PACKET_SIZE);
TkeyCtrlRxBufLength = MAX_PACKET_SIZE;
// Update output pointer
UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer,
MAX_PACKET_SIZE,
UART_RX_BUF_SIZE);
FrameRemainingBytes -= MAX_PACKET_SIZE;
TkeyCtrlDataAvailable = 1;
cts_start();
}
else if ((FrameRemainingBytes < MAX_PACKET_SIZE) &&
(UartRxBufByteCount >= FrameRemainingBytes)) {
circular_copy(TkeyCtrlRxBuf,
UartRxBuf,
UART_RX_BUF_SIZE,
UartRxBufOutputPointer,
FrameRemainingBytes);
TkeyCtrlRxBufLength = FrameRemainingBytes;
// Update output pointer
UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer,
FrameRemainingBytes,
UART_RX_BUF_SIZE);
FrameRemainingBytes -= FrameRemainingBytes;
TkeyCtrlDataAvailable = 1;
cts_start();
}
}
}
// Copy CDC data from UartRxBuf to CdcRxBuf
if (FrameStarted && !CdcDataAvailable) {
if (FrameMode == MODE_CDC) {
if ((FrameRemainingBytes >= MAX_PACKET_SIZE) &&
(UartRxBufByteCount >= MAX_PACKET_SIZE)) {
circular_copy(CdcRxBuf,
UartRxBuf,
UART_RX_BUF_SIZE,
UartRxBufOutputPointer,
MAX_PACKET_SIZE);
CdcRxBufLength = MAX_PACKET_SIZE;
// Update output pointer
UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer,
MAX_PACKET_SIZE,
UART_RX_BUF_SIZE);
FrameRemainingBytes -= MAX_PACKET_SIZE;
CdcDataAvailable = 1;
cts_start();
}
else if ((FrameRemainingBytes < MAX_PACKET_SIZE) &&
(UartRxBufByteCount >= FrameRemainingBytes)) {
circular_copy(CdcRxBuf,
UartRxBuf,
UART_RX_BUF_SIZE,
UartRxBufOutputPointer,
FrameRemainingBytes);
CdcRxBufLength = FrameRemainingBytes;
// Update output pointer
UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer,
FrameRemainingBytes,
UART_RX_BUF_SIZE);
FrameRemainingBytes -= FrameRemainingBytes;
CdcDataAvailable = 1;
cts_start();
}
}
}
// Copy HID data from UartRxBuf to HidRxBuf
if (FrameStarted && !HidDataAvailable) {
if (FrameMode == MODE_HID) {
// Check if a complete frame has been received
if (UartRxBufByteCount >= FrameRemainingBytes) {
circular_copy(HidRxBuf,
UartRxBuf,
UART_RX_BUF_SIZE,
UartRxBufOutputPointer,
FrameRemainingBytes);
HidRxBufLength = MAX_PACKET_SIZE;
// Update output pointer
UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer,
FrameRemainingBytes,
UART_RX_BUF_SIZE);
HidDataAvailable = 1;
cts_start();
}
}
}
// Check if we should upload data to Endpoint 2 (CDC)
if (CdcDataAvailable && !Endpoint2UploadBusy) {
// Write upload endpoint
memcpy(Ep2Buffer + MAX_PACKET_SIZE, /* Copy to IN buffer of Endpoint 2 */
CdcRxBuf,
CdcRxBufLength);
UEP2_T_LEN = CdcRxBufLength; // Set the number of data bytes that Endpoint 2 is ready to send
UEP2_CTRL = (UEP2_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_ACK; // Answer ACK
Endpoint2UploadBusy = 1; // Set busy flag
CdcDataAvailable = 0;
CdcRxBufLength = 0;
if (FrameRemainingBytes == 0) {
// Complete frame sent, get next header and data
FrameStarted = 0;
}
}
// Check if we should upload data to Endpoint 3 (HID)
if (HidDataAvailable && !Endpoint3UploadBusy) {
// Write upload endpoint
memcpy(Ep3Buffer + MAX_PACKET_SIZE, /* Copy to IN buffer of Endpoint 3 */
HidRxBuf,
HidRxBufLength);
UEP3_T_LEN = MAX_PACKET_SIZE; // Set the number of data bytes that Endpoint 3 is ready to send
UEP3_CTRL = (UEP3_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_ACK; // Answer ACK
Endpoint3UploadBusy = 1; // Set busy flag
HidDataAvailable = 0;
// Get next header and data
FrameStarted = 0;
}
// Check if we should upload data to Endpoint 4 (TKEYCTRL)
if (TkeyCtrlDataAvailable && !Endpoint4UploadBusy) {
if (TkeyCtrlRxBufLength == MAX_PACKET_SIZE) {
// Write upload endpoint
memcpy(Ep0Buffer+128, /* Copy to IN (TX) buffer of Endpoint 4 */
TkeyCtrlRxBuf,
TkeyCtrlRxBufLength);
} else {
memset(Ep0Buffer+128, 0, MAX_PACKET_SIZE);
// Write upload endpoint
memcpy(Ep0Buffer+128, /* Copy to IN (TX) buffer of Endpoint 4 */
TkeyCtrlRxBuf,
TkeyCtrlRxBufLength);
}
UEP4_T_LEN = MAX_PACKET_SIZE; // Set the number of data bytes that Endpoint 4 is ready to send
UEP4_CTRL = (UEP4_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_ACK; // Answer ACK
Endpoint4UploadBusy = 1; // Set busy flag
TkeyCtrlDataAvailable = 0;
TkeyCtrlRxBufLength = 0;
if (FrameRemainingBytes == 0) {
// Complete frame sent, get next header and data
FrameStarted = 0;
}
}
#if 0
DebugUartRxBufByteCount = debug_uart_byte_count();
if (DebugUartRxBufByteCount) {
switch(DebugUartRxBuf[DebugUartRxBufOutputPointer]) {
case 'h':
printStr("h Show help\n");
printStr("r Reset UART1\n");
printStr("s Show status\n");
break;
case 'r':
/** UART */
UartRxBufInputPointer = 0;
UartRxBufOutputPointer = 0;
UartRxBufOverflow = 0;
/** Frame */
FrameMode = 0;
FrameLength = 0;
FrameStarted = 0;
/** CDC */
CdcDataAvailable = 0;
CdcRxBufLength = 0;
CdcLoopCount = 0;
/** HID */
HidDataAvailable = 0;
/** Timeout */
LoopCounter = 0;
LastReceiveCounter = 0;
/** Endpoints */
UEP2_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK;
UEP3_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK;
UEP4_CTRL = UEP_T_RES_NAK | UEP_R_RES_ACK;
UIF_TRANSFER = 0; // Writing 0 clears the interrupt
UIF_BUS_RST = 0; // Clear interrupt flag
Endpoint2UploadBusy = 0;
Endpoint3UploadBusy = 0;
UsbEp2ByteCount = 0; // USB endpoint 2 (CDC) received length
UsbEp3ByteCount = 0; // USB endpoint 3 (HID) received length
/** Misc */
Halted = 0;
printStr("Reset done!\n");
break;
case 's':
printStr("Endpoint2UploadBusy = "); printNumU32(Endpoint2UploadBusy); printStr("\n");
printStr("UsbEp2ByteCount = "); printNumU32(UsbEp2ByteCount); printStr("\n");
printStr("UEP2_CTRL = 0x"); printNumHex(UEP2_CTRL); printStr("\n");
printStr("Endpoint3UploadBusy = "); printNumU32(Endpoint3UploadBusy); printStr("\n");
printStr("UsbEp3ByteCount = "); printNumU32(UsbEp3ByteCount); printStr("\n");
printStr("UEP3_CTRL = 0x"); printNumHex(UEP3_CTRL); printStr("\n");
printStr("Endpoint4UploadBusy = "); printNumU32(Endpoint4UploadBusy); printStr("\n");
printStr("UsbEp4ByteCount = "); printNumU32(UsbEp4ByteCount); printStr("\n");
printStr("UEP4_CTRL = 0x"); printNumHex(UEP4_CTRL); printStr("\n");
printStr("UartRxBufInputPointer = "); printNumU32(UartRxBufInputPointer); printStr("\n");
printStr("UartRxBufOutputPointer = "); printNumU32(UartRxBufOutputPointer); printStr("\n");
printStr("UartRxBufOverflow = "); printNumU32(UartRxBufOverflow); printStr("\n");
printStr("UartRxBufByteCount = "); printNumU32(UartRxBufByteCount); printStr("\n");
printStr("FrameMode = 0x"); printNumHex(FrameMode); printStr("\n");
printStr("FrameLength = "); printNumU32(FrameLength); printStr("\n");
printStr("FrameStarted = "); printNumU32(FrameStarted); printStr("\n");
printStr("CdcDataAvailable = "); printNumU32(CdcDataAvailable); printStr("\n");
printStr("HidDataAvailable = "); printNumU32(HidDataAvailable); printStr("\n");
printStr("Halted = "); printNumU32(Halted); printStr("\n");
break;
default:
printStr("\n");
break;
}
// Update out pointer
DebugUartRxBufOutputPointer = increment_pointer(DebugUartRxBufOutputPointer,
DebugUartRxBufByteCount,
DEBUG_UART_RX_BUF_SIZE);
}
#endif
} /* END if (UsbConfig) */
} /* END while (1) */
}