From b443359e9c73beb54cc82acde5f0d5b397e31d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Th=C3=B6rnblad?= Date: Thu, 4 Jul 2024 18:24:07 +0200 Subject: [PATCH] ch552: Add USB HID and protocol support over UART - Add USB HID support. - Introduce a small protocol to distinguish between CDC and HID data sent over the UART. - Add some debug printing. - Cleanup of code and formatting. --- hw/usb_interface/ch552_fw/Makefile | 11 +- hw/usb_interface/ch552_fw/Makefile.include | 2 + .../ch552_fw/encode_usb_strings.py | 6 +- hw/usb_interface/ch552_fw/include/ch554.h | 556 +++--- hw/usb_interface/ch552_fw/include/ch554_usb.h | 241 ++- hw/usb_interface/ch552_fw/include/debug.c | 219 ++- hw/usb_interface/ch552_fw/include/debug.h | 239 ++- hw/usb_interface/ch552_fw/include/mem.h | 32 + hw/usb_interface/ch552_fw/include/print.c | 188 ++ hw/usb_interface/ch552_fw/include/print.h | 42 + .../ch552_fw/include/usb_strings.h | 32 +- hw/usb_interface/ch552_fw/main.c | 1617 +++++++++++------ 12 files changed, 2047 insertions(+), 1138 deletions(-) create mode 100644 hw/usb_interface/ch552_fw/include/mem.h create mode 100644 hw/usb_interface/ch552_fw/include/print.c create mode 100644 hw/usb_interface/ch552_fw/include/print.h diff --git a/hw/usb_interface/ch552_fw/Makefile b/hw/usb_interface/ch552_fw/Makefile index 6cf184d..71d8183 100644 --- a/hw/usb_interface/ch552_fw/Makefile +++ b/hw/usb_interface/ch552_fw/Makefile @@ -3,7 +3,6 @@ TARGET = usb_device_cdc CH554_SDCC=~/ch554_sdcc/ CHPROG=chprog - # Adjust the XRAM location and size to leave space for the USB DMA buffers # Buffer layout in XRAM: # 0x0000 Ep0Buffer[8] @@ -11,8 +10,11 @@ CHPROG=chprog # 0x0080 EP2Buffer[2*64] # # This takes a total of 256bytes, so there are 768 bytes left. -XRAM_SIZE = 0x0300 -XRAM_LOC = 0x0100 +#XRAM_SIZE = 0x0300 +#XRAM_LOC = 0x0100 + +XRAM_SIZE = 0x0400 +XRAM_LOC = 0x0000 FREQ_SYS = 16000000 @@ -21,7 +23,8 @@ usb_strings.h: encode_usb_strings.py C_FILES = \ main.c \ - include/debug.c + include/debug.c \ + include/print.c pre-flash: diff --git a/hw/usb_interface/ch552_fw/Makefile.include b/hw/usb_interface/ch552_fw/Makefile.include index 1174754..d4f7a8c 100644 --- a/hw/usb_interface/ch552_fw/Makefile.include +++ b/hw/usb_interface/ch552_fw/Makefile.include @@ -8,6 +8,8 @@ WCHISP ?= wchisptool -g -f ####################################################### +EXTRA_FLAGS = -D BUILD_CODE + FREQ_SYS ?= 24000000 XRAM_SIZE ?= 0x0400 diff --git a/hw/usb_interface/ch552_fw/encode_usb_strings.py b/hw/usb_interface/ch552_fw/encode_usb_strings.py index 399618e..151d2f6 100755 --- a/hw/usb_interface/ch552_fw/encode_usb_strings.py +++ b/hw/usb_interface/ch552_fw/encode_usb_strings.py @@ -37,17 +37,17 @@ if __name__ == "__main__": f.write('#ifndef USB_STRINGS\n') f.write('#define USB_STRINGS\n') - f.write('unsigned char __code Prod_Des[]={{ // "{}"\n'.format(product)) + f.write('unsigned char __code ProdDesc[]={{ // "{}"\n'.format(product)) f.write(' ') f.write(', '.join(['0x{:02x}'.format(i) for i in string_to_descriptor(product)])) f.write('\n};\n\n') - f.write('unsigned char __code Manuf_Des[]={{ // "{}"\n'.format(manufacturer)) + f.write('unsigned char __code ManufDesc[]={{ // "{}"\n'.format(manufacturer)) f.write(' ') f.write(', '.join(['0x{:02x}'.format(i) for i in string_to_descriptor(manufacturer)])) f.write('\n};\n\n') - f.write('unsigned char __code SerDes[]={{ // "{}"\n'.format(serial)) + f.write('unsigned char __code SerialDesc[]={{ // "{}"\n'.format(serial)) f.write(' ') f.write(', '.join(['0x{:02x}'.format(i) for i in string_to_descriptor(serial)])) f.write('\n};\n\n') diff --git a/hw/usb_interface/ch552_fw/include/ch554.h b/hw/usb_interface/ch552_fw/include/ch554.h index bb263dd..33ebc3d 100644 --- a/hw/usb_interface/ch552_fw/include/ch554.h +++ b/hw/usb_interface/ch552_fw/include/ch554.h @@ -16,31 +16,31 @@ Header file for CH554 microcontrollers. /* sbit are bit addressable, others are byte addressable */ /* System Registers */ -SFR(PSW, 0xD0); // program status word - SBIT(CY, 0xD0, 7); // carry flag - SBIT(AC, 0xD0, 6); // auxiliary carry flag - SBIT(F0, 0xD0, 5); // bit addressable general purpose flag 0 - SBIT(RS1, 0xD0, 4); // register R0-R7 bank selection high bit - SBIT(RS0, 0xD0, 3); // register R0-R7 bank selection low bit +SFR(PSW, 0xD0); // program status word + SBIT(CY, 0xD0, 7); // carry flag + SBIT(AC, 0xD0, 6); // auxiliary carry flag + SBIT(F0, 0xD0, 5); // bit addressable general purpose flag 0 + SBIT(RS1, 0xD0, 4); // register R0-R7 bank selection high bit + SBIT(RS0, 0xD0, 3); // register R0-R7 bank selection low bit #define MASK_PSW_RS 0x18 // bit mask of register R0-R7 bank selection // RS1 & RS0: register R0-R7 bank selection // 00 - bank 0, R0-R7 @ address 0x00-0x07 // 01 - bank 1, R0-R7 @ address 0x08-0x0F // 10 - bank 2, R0-R7 @ address 0x10-0x17 // 11 - bank 3, R0-R7 @ address 0x18-0x1F - SBIT(OV, 0xD0, 2); // overflow flag - SBIT(F1, 0xD0, 1); // bit addressable general purpose flag 1 - SBIT(P, 0xD0, 0); // ReadOnly: parity flag -SFR(ACC, 0xE0); // accumulator -SFR(B, 0xF0); // general purpose register B -SFR(SP, 0x81); // stack pointer + SBIT(OV, 0xD0, 2); // overflow flag + SBIT(F1, 0xD0, 1); // bit addressable general purpose flag 1 + SBIT(P, 0xD0, 0); // ReadOnly: parity flag +SFR(ACC, 0xE0); // accumulator +SFR(B, 0xF0); // general purpose register B +SFR(SP, 0x81); // stack pointer //sfr16 DPTR = 0x82; // DPTR pointer, little-endian -SFR(DPL, 0x82); // data pointer low -SFR(DPH, 0x83); // data pointer high -SFR(SAFE_MOD, 0xA1); // WriteOnly: writing safe mode +SFR(DPL, 0x82); // data pointer low +SFR(DPH, 0x83); // data pointer high +SFR(SAFE_MOD, 0xA1); // WriteOnly: writing safe mode //sfr CHIP_ID = 0xA1; // ReadOnly: reading chip ID #define CHIP_ID SAFE_MOD -SFR(GLOBAL_CFG, 0xB1); // global config, Write@SafeMode +SFR(GLOBAL_CFG, 0xB1); // global config, Write@SafeMode #define bBOOT_LOAD 0x20 // ReadOnly: boot loader status for discriminating BootLoader or Application: set 1 by power on reset, clear 0 by software reset #define bSW_RESET 0x10 // software reset bit, auto clear by hardware #define bCODE_WE 0x08 // enable flash-ROM (include code & Data-Flash) being program or erasing: 0=writing protect, 1=enable program and erase @@ -49,7 +49,7 @@ SFR(GLOBAL_CFG, 0xB1); // global config, Write@SafeMode #define bWDOG_EN 0x01 // enable watch-dog reset if watch-dog timer overflow: 0=as timer only, 1=enable reset if timer overflow /* Clock and Sleep and Power Registers */ -SFR(PCON, 0x87); // power control and reset flag +SFR(PCON, 0x87); // power control and reset flag #define SMOD 0x80 // baud rate selection for UART0 mode 1/2/3: 0=slow(Fsys/128 @mode2, TF1/32 @mode1/3, no effect for TF2), // 1=fast(Fsys/32 @mode2, TF1/16 @mode1/3, no effect for TF2) #define bRST_FLAG1 0x20 // ReadOnly: recent reset flag high bit @@ -67,7 +67,7 @@ SFR(PCON, 0x87); // power control and reset flag #define GF1 0x08 // general purpose flag bit 1 #define GF0 0x04 // general purpose flag bit 0 #define PD 0x02 // power-down enable bit, auto clear by wake-up hardware -SFR(CLOCK_CFG, 0xB9); // system clock config: lower 3 bits for system clock Fsys, Write@SafeMode +SFR(CLOCK_CFG, 0xB9); // system clock config: lower 3 bits for system clock Fsys, Write@SafeMode #define bOSC_EN_INT 0x80 // internal oscillator enable and original clock selection: 1=enable & select internal clock, 0=disable & select external clock #define bOSC_EN_XT 0x40 // external oscillator enable, need quartz crystal or ceramic resonator between XI and XO pins #define bWDOG_IF_TO 0x20 // ReadOnly: watch-dog timer overflow interrupt flag, cleared by reload watch-dog count or auto cleared when MCU enter interrupt routine @@ -91,7 +91,7 @@ SFR(CLOCK_CFG, 0xB9); // system clock config: lower 3 bits for system clock Fsys Fsys = Fpll/128 = 750KHz: 0 0 1 Fsys = Fpll/512 =187.5KHz: 0 0 0 */ -SFR(WAKE_CTRL, 0xA9); // wake-up control, Write@SafeMode +SFR(WAKE_CTRL, 0xA9); // wake-up control, Write@SafeMode #define bWAK_BY_USB 0x80 // enable wake-up by USB event #define bWAK_RXD1_LO 0x40 // enable wake-up by RXD1 low level #define bWAK_P1_5_LO 0x20 // enable wake-up by pin P1.5 low level @@ -100,43 +100,43 @@ SFR(WAKE_CTRL, 0xA9); // wake-up control, Write@SafeMode #define bWAK_RST_HI 0x04 // enable wake-up by pin RST high level #define bWAK_P3_2E_3L 0x02 // enable wake-up by pin P3.2 (INT0) edge or pin P3.3 (INT1) low level #define bWAK_RXD0_LO 0x01 // enable wake-up by RXD0 low level -SFR(RESET_KEEP, 0xFE); // value keeper during reset -SFR(WDOG_COUNT, 0xFF); // watch-dog count, count by clock frequency Fsys/65536 +SFR(RESET_KEEP, 0xFE); // value keeper during reset +SFR(WDOG_COUNT, 0xFF); // watch-dog count, count by clock frequency Fsys/65536 /* Interrupt Registers */ -SFR(IE, 0xA8); // interrupt enable - SBIT(EA, 0xA8, 7); // enable global interrupts: 0=disable, 1=enable if E_DIS=0 - SBIT(E_DIS, 0xA8, 6); // disable global interrupts, intend to inhibit interrupt during some flash-ROM operation: 0=enable if EA=1, 1=disable - SBIT(ET2, 0xA8, 5); // enable timer2 interrupt - SBIT(ES, 0xA8, 4); // enable UART0 interrupt - SBIT(ET1, 0xA8, 3); // enable timer1 interrupt - SBIT(EX1, 0xA8, 2); // enable external interrupt INT1 - SBIT(ET0, 0xA8, 1); // enable timer0 interrupt - SBIT(EX0, 0xA8, 0); // enable external interrupt INT0 -SFR(IP, 0xB8); // interrupt priority and current priority - SBIT(PH_FLAG, 0xB8, 7); // ReadOnly: high level priority action flag - SBIT(PL_FLAG, 0xB8, 6); // ReadOnly: low level priority action flag +SFR(IE, 0xA8); // interrupt enable + SBIT(EA, 0xA8, 7); // enable global interrupts: 0=disable, 1=enable if E_DIS=0 + SBIT(E_DIS, 0xA8, 6); // disable global interrupts, intend to inhibit interrupt during some flash-ROM operation: 0=enable if EA=1, 1=disable + SBIT(ET2, 0xA8, 5); // enable timer2 interrupt + SBIT(ES, 0xA8, 4); // enable UART0 interrupt + SBIT(ET1, 0xA8, 3); // enable timer1 interrupt + SBIT(EX1, 0xA8, 2); // enable external interrupt INT1 + SBIT(ET0, 0xA8, 1); // enable timer0 interrupt + SBIT(EX0, 0xA8, 0); // enable external interrupt INT0 +SFR(IP, 0xB8); // interrupt priority and current priority + SBIT(PH_FLAG, 0xB8, 7); // ReadOnly: high level priority action flag + SBIT(PL_FLAG, 0xB8, 6); // ReadOnly: low level priority action flag // PH_FLAG & PL_FLAG: current interrupt priority // 00 - no interrupt now // 01 - low level priority interrupt action now // 10 - high level priority interrupt action now // 11 - unknown error - SBIT(PT2, 0xB8, 5); // timer2 interrupt priority level - SBIT(PS, 0xB8, 4); // UART0 interrupt priority level - SBIT(PT1, 0xB8, 3); // timer1 interrupt priority level - SBIT(PX1, 0xB8, 2); // external interrupt INT1 priority level - SBIT(PT0, 0xB8, 1); // timer0 interrupt priority level - SBIT(PX0, 0xB8, 0); // external interrupt INT0 priority level -SFR(IE_EX, 0xE8); // extend interrupt enable - SBIT(IE_WDOG, 0xE8, 7); // enable watch-dog timer interrupt - SBIT(IE_GPIO, 0xE8, 6); // enable GPIO input interrupt - SBIT(IE_PWMX, 0xE8, 5); // enable PWM1/2 interrupt - SBIT(IE_UART1, 0xE8, 4); // enable UART1 interrupt - SBIT(IE_ADC, 0xE8, 3); // enable ADC interrupt - SBIT(IE_USB, 0xE8, 2); // enable USB interrupt - SBIT(IE_TKEY, 0xE8, 1); // enable touch-key timer interrupt - SBIT(IE_SPI0, 0xE8, 0); // enable SPI0 interrupt -SFR(IP_EX, 0xE9); // extend interrupt priority + SBIT(PT2, 0xB8, 5); // timer2 interrupt priority level + SBIT(PS, 0xB8, 4); // UART0 interrupt priority level + SBIT(PT1, 0xB8, 3); // timer1 interrupt priority level + SBIT(PX1, 0xB8, 2); // external interrupt INT1 priority level + SBIT(PT0, 0xB8, 1); // timer0 interrupt priority level + SBIT(PX0, 0xB8, 0); // external interrupt INT0 priority level +SFR(IE_EX, 0xE8); // extend interrupt enable + SBIT(IE_WDOG, 0xE8, 7); // enable watch-dog timer interrupt + SBIT(IE_GPIO, 0xE8, 6); // enable GPIO input interrupt + SBIT(IE_PWMX, 0xE8, 5); // enable PWM1/2 interrupt + SBIT(IE_UART1, 0xE8, 4); // enable UART1 interrupt + SBIT(IE_ADC, 0xE8, 3); // enable ADC interrupt + SBIT(IE_USB, 0xE8, 2); // enable USB interrupt + SBIT(IE_TKEY, 0xE8, 1); // enable touch-key timer interrupt + SBIT(IE_SPI0, 0xE8, 0); // enable SPI0 interrupt +SFR(IP_EX, 0xE9); // extend interrupt priority #define bIP_LEVEL 0x80 // ReadOnly: current interrupt nested level: 0=no interrupt or two levels, 1=one level #define bIP_GPIO 0x40 // GPIO input interrupt priority level #define bIP_PWMX 0x20 // PWM1/2 interrupt priority level @@ -145,7 +145,7 @@ SFR(IP_EX, 0xE9); // extend interrupt priority #define bIP_USB 0x04 // USB interrupt priority level #define bIP_TKEY 0x02 // touch-key timer interrupt priority level #define bIP_SPI0 0x01 // SPI0 interrupt priority level -SFR(GPIO_IE, 0xC7); // GPIO interrupt enable +SFR(GPIO_IE, 0xC7); // GPIO interrupt enable #define bIE_IO_EDGE 0x80 // enable GPIO edge interrupt: 0=low/high level, 1=falling/rising edge #define bIE_RXD1_LO 0x40 // enable interrupt by RXD1 low level / falling edge #define bIE_P1_5_LO 0x20 // enable interrupt by pin P1.5 low level / falling edge @@ -156,13 +156,13 @@ SFR(GPIO_IE, 0xC7); // GPIO interrupt enable #define bIE_RXD0_LO 0x01 // enable interrupt by RXD0 low level / falling edge /* FlashROM and Data-Flash Registers */ -SFR16(ROM_ADDR, 0x84); // address for flash-ROM, little-endian -SFR(ROM_ADDR_L, 0x84); // address low byte for flash-ROM -SFR(ROM_ADDR_H, 0x85); // address high byte for flash-ROM -SFR16(ROM_DATA, 0x8E); // data for flash-ROM writing, little-endian -SFR(ROM_DATA_L, 0x8E); // data low byte for flash-ROM writing, data byte for Data-Flash reading/writing -SFR(ROM_DATA_H, 0x8F); // data high byte for flash-ROM writing -SFR(ROM_CTRL, 0x86); // WriteOnly: flash-ROM control +SFR16(ROM_ADDR, 0x84); // address for flash-ROM, little-endian +SFR(ROM_ADDR_L, 0x84); // address low byte for flash-ROM +SFR(ROM_ADDR_H, 0x85); // address high byte for flash-ROM +SFR16(ROM_DATA, 0x8E); // data for flash-ROM writing, little-endian +SFR(ROM_DATA_L, 0x8E); // data low byte for flash-ROM writing, data byte for Data-Flash reading/writing +SFR(ROM_DATA_H, 0x8F); // data high byte for flash-ROM writing +SFR(ROM_CTRL, 0x86); // WriteOnly: flash-ROM control #define ROM_CMD_WRITE 0x9A // WriteOnly: flash-ROM word or Data-Flash byte write operation command #define ROM_CMD_READ 0x8E // WriteOnly: Data-Flash byte read operation command //sfr ROM_STATUS = 0x86; // ReadOnly: flash-ROM status @@ -171,36 +171,36 @@ SFR(ROM_CTRL, 0x86); // WriteOnly: flash-ROM control #define bROM_CMD_ERR 0x02 // ReadOnly: flash-ROM operation command error flag: 0=command accepted, 1=unknown command /* Port Registers */ -SFR(P1, 0x90); // port 1 input & output - SBIT(SCK, 0x90, 7); // serial clock for SPI0 - SBIT(TXD1, 0x90, 7); // TXD output for UART1 - SBIT(TIN5, 0x90, 7); // TIN5 for Touch-Key - SBIT(MISO, 0x90, 6); // master serial data input or slave serial data output for SPI0 - SBIT(RXD1, 0x90, 6); // RXD input for UART1 - SBIT(TIN4, 0x90, 6); // TIN4 for Touch-Key - SBIT(MOSI, 0x90, 5); // master serial data output or slave serial data input for SPI0 - SBIT(PWM1, 0x90, 5); // PWM output for PWM1 - SBIT(TIN3, 0x90, 5); // TIN3 for Touch-Key - SBIT(UCC2, 0x90, 5); // CC2 for USB type-C - SBIT(AIN2, 0x90, 5); // AIN2 for ADC - SBIT(T2_, 0x90, 4); // alternate pin for T2 - SBIT(CAP1_, 0x90, 4); // alternate pin for CAP1 - SBIT(SCS, 0x90, 4); // slave chip-selection input for SPI0 - SBIT(TIN2, 0x90, 4); // TIN2 for Touch-Key - SBIT(UCC1, 0x90, 4); // CC1 for USB type-C - SBIT(AIN1, 0x90, 4); // AIN1 for ADC - SBIT(TXD_, 0x90, 3); // alternate pin for TXD of UART0 - SBIT(RXD_, 0x90, 2); // alternate pin for RXD of UART0 - SBIT(T2EX, 0x90, 1); // external trigger input for timer2 reload & capture - SBIT(CAP2, 0x90, 1); // capture2 input for timer2 - SBIT(TIN1, 0x90, 1); // TIN1 for Touch-Key - SBIT(VBUS2, 0x90, 1); // VBUS2 for USB type-C - SBIT(AIN0, 0x90, 1); // AIN0 for ADC - SBIT(T2, 0x90, 0); // external count input - SBIT(CAP1, 0x90, 0); // capture1 input for timer2 - SBIT(TIN0, 0x90, 0); // TIN0 for Touch-Key -SFR(P1_MOD_OC, 0x92); // port 1 output mode: 0=push-pull, 1=open-drain -SFR(P1_DIR_PU, 0x93); // port 1 direction for push-pull or pullup enable for open-drain +SFR(P1, 0x90); // port 1 input & output + SBIT(SCK, 0x90, 7); // serial clock for SPI0 + SBIT(TXD1, 0x90, 7); // TXD output for UART1 + SBIT(TIN5, 0x90, 7); // TIN5 for Touch-Key + SBIT(MISO, 0x90, 6); // master serial data input or slave serial data output for SPI0 + SBIT(RXD1, 0x90, 6); // RXD input for UART1 + SBIT(TIN4, 0x90, 6); // TIN4 for Touch-Key + SBIT(MOSI, 0x90, 5); // master serial data output or slave serial data input for SPI0 + SBIT(PWM1, 0x90, 5); // PWM output for PWM1 + SBIT(TIN3, 0x90, 5); // TIN3 for Touch-Key + SBIT(UCC2, 0x90, 5); // CC2 for USB type-C + SBIT(AIN2, 0x90, 5); // AIN2 for ADC + SBIT(T2_, 0x90, 4); // alternate pin for T2 + SBIT(CAP1_, 0x90, 4); // alternate pin for CAP1 + SBIT(SCS, 0x90, 4); // slave chip-selection input for SPI0 + SBIT(TIN2, 0x90, 4); // TIN2 for Touch-Key + SBIT(UCC1, 0x90, 4); // CC1 for USB type-C + SBIT(AIN1, 0x90, 4); // AIN1 for ADC + SBIT(TXD_, 0x90, 3); // alternate pin for TXD of UART0 + SBIT(RXD_, 0x90, 2); // alternate pin for RXD of UART0 + SBIT(T2EX, 0x90, 1); // external trigger input for timer2 reload & capture + SBIT(CAP2, 0x90, 1); // capture2 input for timer2 + SBIT(TIN1, 0x90, 1); // TIN1 for Touch-Key + SBIT(VBUS2, 0x90, 1); // VBUS2 for USB type-C + SBIT(AIN0, 0x90, 1); // AIN0 for ADC + SBIT(T2, 0x90, 0); // external count input + SBIT(CAP1, 0x90, 0); // capture1 input for timer2 + SBIT(TIN0, 0x90, 0); // TIN0 for Touch-Key +SFR(P1_MOD_OC, 0x92); // port 1 output mode: 0=push-pull, 1=open-drain +SFR(P1_DIR_PU, 0x93); // port 1 direction for push-pull or pullup enable for open-drain // Pn_MOD_OC & Pn_DIR_PU: pin input & output configuration for Pn (n=1/3) // 0 0: float input only, without pullup resistance // 0 1: push-pull output, strong driving high level and low level @@ -227,25 +227,25 @@ SFR(P1_DIR_PU, 0x93); // port 1 direction for push-pull or pullup enable for ope #define bAIN0 0x02 // AIN0 for ADC #define bT2 0x01 // external count input or clock output for timer2 #define bCAP1 bT2 // capture1 input for timer2 -SFR(P2, 0xA0); // port 2 -SFR(P3, 0xB0); // port 3 input & output - SBIT(UDM, 0xB0, 7); // ReadOnly: pin UDM input - SBIT(UDP, 0xB0, 6); // ReadOnly: pin UDP input - SBIT(T1, 0xB0, 5); // external count input for timer1 - SBIT(PWM2, 0xB0, 4); // PWM output for PWM2 - SBIT(RXD1_, 0xB0, 4); // alternate pin for RXD1 - SBIT(T0, 0xB0, 4); // external count input for timer0 - SBIT(INT1, 0xB0, 3); // external interrupt 1 input - SBIT(TXD1_, 0xB0, 2); // alternate pin for TXD1 - SBIT(INT0, 0xB0, 2); // external interrupt 0 input - SBIT(VBUS1, 0xB0, 2); // VBUS1 for USB type-C - SBIT(AIN3, 0xB0, 2); // AIN3 for ADC - SBIT(PWM2_, 0xB0, 1); // alternate pin for PWM2 - SBIT(TXD, 0xB0, 1); // TXD output for UART0 - SBIT(PWM1_, 0xB0, 0); // alternate pin for PWM1 - SBIT(RXD, 0xB0, 0); // RXD input for UART0 -SFR(P3_MOD_OC, 0x96); // port 3 output mode: 0=push-pull, 1=open-drain -SFR(P3_DIR_PU, 0x97); // port 3 direction for push-pull or pullup enable for open-drain +SFR(P2, 0xA0); // port 2 +SFR(P3, 0xB0); // port 3 input & output + SBIT(UDM, 0xB0, 7); // ReadOnly: pin UDM input + SBIT(UDP, 0xB0, 6); // ReadOnly: pin UDP input + SBIT(T1, 0xB0, 5); // external count input for timer1 + SBIT(PWM2, 0xB0, 4); // PWM output for PWM2 + SBIT(RXD1_, 0xB0, 4); // alternate pin for RXD1 + SBIT(T0, 0xB0, 4); // external count input for timer0 + SBIT(INT1, 0xB0, 3); // external interrupt 1 input + SBIT(TXD1_, 0xB0, 2); // alternate pin for TXD1 + SBIT(INT0, 0xB0, 2); // external interrupt 0 input + SBIT(VBUS1, 0xB0, 2); // VBUS1 for USB type-C + SBIT(AIN3, 0xB0, 2); // AIN3 for ADC + SBIT(PWM2_, 0xB0, 1); // alternate pin for PWM2 + SBIT(TXD, 0xB0, 1); // TXD output for UART0 + SBIT(PWM1_, 0xB0, 0); // alternate pin for PWM1 + SBIT(RXD, 0xB0, 0); // RXD input for UART0 +SFR(P3_MOD_OC, 0x96); // port 3 output mode: 0=push-pull, 1=open-drain +SFR(P3_DIR_PU, 0x97); // port 3 direction for push-pull or pullup enable for open-drain #define bUDM 0x80 // ReadOnly: pin UDM input #define bUDP 0x40 // ReadOnly: pin UDP input #define bT1 0x20 // external count input for timer1 @@ -261,7 +261,7 @@ SFR(P3_DIR_PU, 0x97); // port 3 direction for push-pull or pullup enable for ope #define bTXD 0x02 // TXD output for UART0 #define bPWM1_ 0x01 // alternate pin for PWM1 #define bRXD 0x01 // RXD input for UART0 -SFR(PIN_FUNC, 0xC6); // pin function selection +SFR(PIN_FUNC, 0xC6); // pin function selection #define bUSB_IO_EN 0x80 // USB UDP/UDM I/O pin enable: 0=P3.6/P3.7 as GPIO, 1=P3.6/P3.7 as USB #define bIO_INT_ACT 0x40 // ReadOnly: GPIO interrupt request action status #define bUART1_PIN_X 0x20 // UART1 alternate pin enable: 0=RXD1/TXD1 on P1.6/P1.7, 1=RXD1/TXD1 on P3.4/P3.2 @@ -270,25 +270,25 @@ SFR(PIN_FUNC, 0xC6); // pin function selection #define bPWM1_PIN_X 0x04 // PWM1 alternate pin enable: 0=PWM1 on P1.5, 1=PWM1 on P3.0 #define bT2EX_PIN_X 0x02 // T2EX/CAP2 alternate pin enable: 0=T2EX/CAP2 on P1.1, 1=T2EX/CAP2 on RST #define bT2_PIN_X 0x01 // T2/CAP1 alternate pin enable: 0=T2/CAP1 on P1.1, 1=T2/CAP1 on P1.4 -SFR(XBUS_AUX, 0xA2); // xBUS auxiliary setting -#define bUART0_TX 0x80 // ReadOnly: indicate UART0 transmittal status -#define bUART0_RX 0x40 // ReadOnly: indicate UART0 receiving status +SFR(XBUS_AUX, 0xA2); // xBUS auxiliary setting +#define bUART0_TX 0x80 // ReadOnly: indicate UART0 transmit status +#define bUART0_RX 0x40 // ReadOnly: indicate UART0 receive status #define bSAFE_MOD_ACT 0x20 // ReadOnly: safe mode action status #define GF2 0x08 // general purpose flag bit 2 #define bDPTR_AUTO_INC 0x04 // enable DPTR auto increase if finished MOVX_@DPTR instruction #define DPS 0x01 // dual DPTR selection: 0=DPTR0 selected, 1=DPTR1 selected /* Timer0/1 Registers */ -SFR(TCON, 0x88); // timer 0/1 control and external interrupt control - SBIT(TF1, 0x88, 7); // timer1 overflow & interrupt flag, auto cleared when MCU enter interrupt routine - SBIT(TR1, 0x88, 6); // timer1 run enable - SBIT(TF0, 0x88, 5); // timer0 overflow & interrupt flag, auto cleared when MCU enter interrupt routine - SBIT(TR0, 0x88, 4); // timer0 run enable - SBIT(IE1, 0x88, 3); // INT1 interrupt flag, auto cleared when MCU enter interrupt routine - SBIT(IT1, 0x88, 2); // INT1 interrupt type: 0=low level action, 1=falling edge action - SBIT(IE0, 0x88, 1); // INT0 interrupt flag, auto cleared when MCU enter interrupt routine - SBIT(IT0, 0x88, 0); // INT0 interrupt type: 0=low level action, 1=falling edge action -SFR(TMOD, 0x89); // timer 0/1 mode +SFR(TCON, 0x88); // timer 0/1 control and external interrupt control + SBIT(TF1, 0x88, 7); // timer1 overflow & interrupt flag, auto cleared when MCU enter interrupt routine + SBIT(TR1, 0x88, 6); // timer1 run enable + SBIT(TF0, 0x88, 5); // timer0 overflow & interrupt flag, auto cleared when MCU enter interrupt routine + SBIT(TR0, 0x88, 4); // timer0 run enable + SBIT(IE1, 0x88, 3); // INT1 interrupt flag, auto cleared when MCU enter interrupt routine + SBIT(IT1, 0x88, 2); // INT1 interrupt type: 0=low level action, 1=falling edge action + SBIT(IE0, 0x88, 1); // INT0 interrupt flag, auto cleared when MCU enter interrupt routine + SBIT(IT0, 0x88, 0); // INT0 interrupt type: 0=low level action, 1=falling edge action +SFR(TMOD, 0x89); // timer 0/1 mode #define bT1_GATE 0x80 // gate control of timer1: 0=timer1 run enable while TR1=1, 1=timer1 run enable while P3.3 (INT1) pin is high and TR1=1 #define bT1_CT 0x40 // counter or timer mode selection for timer1: 0=timer, use internal clock, 1=counter, use P3.5 (T1) pin falling edge as clock #define bT1_M1 0x20 // timer1 mode high bit @@ -309,41 +309,41 @@ SFR(TMOD, 0x89); // timer 0/1 mode // 01: mode 1, 16-bit timer or counter by cascaded TH0 and TL0 // 10: mode 2, TL0 operates as 8-bit timer or counter, and TH0 provide initial value for TL0 auto-reload // 11: mode 3, TL0 is 8-bit timer or counter controlled by standard timer0 bits, TH0 is 8-bit timer using TF1 and controlled by TR1, timer1 run enable if it is not mode 3 -SFR(TL0, 0x8A); // low byte of timer 0 count -SFR(TL1, 0x8B); // low byte of timer 1 count -SFR(TH0, 0x8C); // high byte of timer 0 count -SFR(TH1, 0x8D); // high byte of timer 1 count +SFR(TL0, 0x8A); // low byte of timer 0 count +SFR(TL1, 0x8B); // low byte of timer 1 count +SFR(TH0, 0x8C); // high byte of timer 0 count +SFR(TH1, 0x8D); // high byte of timer 1 count /* UART0 Registers */ -SFR(SCON, 0x98); // UART0 control (serial port control) - SBIT(SM0, 0x98, 7); // UART0 mode bit0, selection data bit: 0=8 bits data, 1=9 bits data - SBIT(SM1, 0x98, 6); // UART0 mode bit1, selection baud rate: 0=fixed, 1=variable +SFR(SCON, 0x98); // UART0 control (serial port control) + SBIT(SM0, 0x98, 7); // UART0 mode bit0, selection data bit: 0=8 bits data, 1=9 bits data + SBIT(SM1, 0x98, 6); // UART0 mode bit1, selection baud rate: 0=fixed, 1=variable // SM0 & SM1: UART0 mode // 00 - mode 0, shift Register, baud rate fixed at: Fsys/12 // 01 - mode 1, 8-bit UART, baud rate = variable by timer1 or timer2 overflow rate // 10 - mode 2, 9-bit UART, baud rate fixed at: Fsys/128@SMOD=0, Fsys/32@SMOD=1 // 11 - mode 3, 9-bit UART, baud rate = variable by timer1 or timer2 overflow rate - SBIT(SM2, 0x98, 5); // enable multi-device communication in mode 2/3 + SBIT(SM2, 0x98, 5); // enable multi-device communication in mode 2/3 #define MASK_UART0_MOD 0xE0 // bit mask of UART0 mode - SBIT(REN, 0x98, 4); // enable UART0 receiving - SBIT(TB8, 0x98, 3); // the 9th transmitted data bit in mode 2/3 - SBIT(RB8, 0x98, 2); // 9th data bit received in mode 2/3, or stop bit received for mode 1 - SBIT(TI, 0x98, 1); // transmit interrupt flag, set by hardware after completion of a serial transmittal, need software clear - SBIT(RI, 0x98, 0); // receive interrupt flag, set by hardware after completion of a serial receiving, need software clear -SFR(SBUF, 0x99); // UART0 data buffer: reading for receiving, writing for transmittal + SBIT(REN, 0x98, 4); // enable UART0 receive + SBIT(TB8, 0x98, 3); // the 9th transmitted data bit in mode 2/3 + SBIT(RB8, 0x98, 2); // 9th data bit received in mode 2/3, or stop bit received for mode 1 + SBIT(TI, 0x98, 1); // transmit interrupt flag, set by hardware after completion of a serial transmit, need software clear + SBIT(RI, 0x98, 0); // receive interrupt flag, set by hardware after completion of a serial receive, need software clear +SFR(SBUF, 0x99); // UART0 data buffer: reading for receive, writing for transmit /* Timer2/Capture2 Registers */ -SFR(T2CON, 0xC8); // timer 2 control - SBIT(TF2, 0xC8, 7); // timer2 overflow & interrupt flag, need software clear, the flag will not be set when either RCLK=1 or TCLK=1 - SBIT(CAP1F, 0xC8, 7); // timer2 capture 1 interrupt flag, set by T2 edge trigger if bT2_CAP1_EN=1, need software clear - SBIT(EXF2, 0xC8, 6); // timer2 external flag, set by T2EX edge trigger if EXEN2=1, need software clear - SBIT(RCLK, 0xC8, 5); // selection UART0 receiving clock: 0=timer1 overflow pulse, 1=timer2 overflow pulse - SBIT(TCLK, 0xC8, 4); // selection UART0 transmittal clock: 0=timer1 overflow pulse, 1=timer2 overflow pulse - SBIT(EXEN2, 0xC8, 3); // enable T2EX trigger function: 0=ignore T2EX, 1=trigger reload or capture by T2EX edge - SBIT(TR2, 0xC8, 2); // timer2 run enable - SBIT(C_T2, 0xC8, 1); // timer2 clock source selection: 0=timer base internal clock, 1=external edge counter base T2 falling edge - SBIT(CP_RL2, 0xC8, 0); // timer2 function selection (force 0 if RCLK=1 or TCLK=1): 0=timer and auto reload if count overflow or T2EX edge, 1=capture by T2EX edge -SFR(T2MOD, 0xC9); // timer 2 mode and timer 0/1/2 clock mode +SFR(T2CON, 0xC8); // timer 2 control + SBIT(TF2, 0xC8, 7); // timer2 overflow & interrupt flag, need software clear, the flag will not be set when either RCLK=1 or TCLK=1 + SBIT(CAP1F, 0xC8, 7); // timer2 capture 1 interrupt flag, set by T2 edge trigger if bT2_CAP1_EN=1, need software clear + SBIT(EXF2, 0xC8, 6); // timer2 external flag, set by T2EX edge trigger if EXEN2=1, need software clear + SBIT(RCLK, 0xC8, 5); // selection UART0 receive clock: 0=timer1 overflow pulse, 1=timer2 overflow pulse + SBIT(TCLK, 0xC8, 4); // selection UART0 transmit clock: 0=timer1 overflow pulse, 1=timer2 overflow pulse + SBIT(EXEN2, 0xC8, 3); // enable T2EX trigger function: 0=ignore T2EX, 1=trigger reload or capture by T2EX edge + SBIT(TR2, 0xC8, 2); // timer2 run enable + SBIT(C_T2, 0xC8, 1); // timer2 clock source selection: 0=timer base internal clock, 1=external edge counter base T2 falling edge + SBIT(CP_RL2, 0xC8, 0); // timer2 function selection (force 0 if RCLK=1 or TCLK=1): 0=timer and auto reload if count overflow or T2EX edge, 1=capture by T2EX edge +SFR(T2MOD, 0xC9); // timer 2 mode and timer 0/1/2 clock mode #define bTMR_CLK 0x80 // fastest internal clock mode for timer 0/1/2 under faster clock mode: 0=use divided clock, 1=use original Fsys as clock without dividing #define bT2_CLK 0x40 // timer2 internal clock frequency selection: 0=standard clock, Fsys/12 for timer mode, Fsys/4 for UART0 clock mode, // 1=faster clock, Fsys/4 @bTMR_CLK=0 or Fsys @bTMR_CLK=1 for timer mode, Fsys/2 @bTMR_CLK=0 or Fsys @bTMR_CLK=1 for UART0 clock mode @@ -357,20 +357,20 @@ SFR(T2MOD, 0xC9); // timer 2 mode and timer 0/1/2 clock mode // 11: from rising edge to rising edge #define T2OE 0x02 // enable timer2 generated clock output: 0=disable output, 1=enable clock output at T2 pin, frequency = TF2/2 #define bT2_CAP1_EN 0x01 // enable T2 trigger function for capture 1 of timer2 if RCLK=0 & TCLK=0 & CP_RL2=1 & C_T2=0 & T2OE=0 -SFR16(RCAP2, 0xCA); // reload & capture value, little-endian -SFR(RCAP2L, 0xCA); // low byte of reload & capture value -SFR(RCAP2H, 0xCB); // high byte of reload & capture value -SFR16(T2COUNT, 0xCC); // counter, little-endian -SFR(TL2, 0xCC); // low byte of timer 2 count -SFR(TH2, 0xCD); // high byte of timer 2 count -SFR16(T2CAP1, 0xCE); // ReadOnly: capture 1 value for timer2 -SFR(T2CAP1L, 0xCE); // ReadOnly: capture 1 value low byte for timer2 -SFR(T2CAP1H, 0xCF); // ReadOnly: capture 1 value high byte for timer2 +SFR16(RCAP2, 0xCA); // reload & capture value, little-endian +SFR(RCAP2L, 0xCA); // low byte of reload & capture value +SFR(RCAP2H, 0xCB); // high byte of reload & capture value +SFR16(T2COUNT, 0xCC); // counter, little-endian +SFR(TL2, 0xCC); // low byte of timer 2 count +SFR(TH2, 0xCD); // high byte of timer 2 count +SFR16(T2CAP1, 0xCE); // ReadOnly: capture 1 value for timer2 +SFR(T2CAP1L, 0xCE); // ReadOnly: capture 1 value low byte for timer2 +SFR(T2CAP1H, 0xCF); // ReadOnly: capture 1 value high byte for timer2 /* PWM1/2 Registers */ -SFR(PWM_DATA2, 0x9B); // PWM data for PWM2 -SFR(PWM_DATA1, 0x9C); // PWM data for PWM1 -SFR(PWM_CTRL, 0x9D); // PWM 1/2 control +SFR(PWM_DATA2, 0x9B); // PWM data for PWM2 +SFR(PWM_DATA1, 0x9C); // PWM data for PWM1 +SFR(PWM_CTRL, 0x9D); // PWM 1/2 control #define bPWM_IE_END 0x80 // enable interrupt for PWM mode cycle end #define bPWM2_POLAR 0x40 // PWM2 output polarity: 0=default low and high action, 1=default high and low action #define bPWM1_POLAR 0x20 // PWM1 output polarity: 0=default low and high action, 1=default high and low action @@ -378,19 +378,19 @@ SFR(PWM_CTRL, 0x9D); // PWM 1/2 control #define bPWM2_OUT_EN 0x08 // PWM2 output enable #define bPWM1_OUT_EN 0x04 // PWM1 output enable #define bPWM_CLR_ALL 0x02 // force clear FIFO and count of PWM1/2 -SFR(PWM_CK_SE, 0x9E); // clock divisor setting +SFR(PWM_CK_SE, 0x9E); // clock divisor setting /* SPI0/Master0/Slave Registers */ -SFR(SPI0_STAT, 0xF8); // SPI 0 status - SBIT(S0_FST_ACT, 0xF8, 7); // ReadOnly: indicate first byte received status for SPI0 - SBIT(S0_IF_OV, 0xF8, 6); // interrupt flag for slave mode FIFO overflow, direct bit address clear or write 1 to clear - SBIT(S0_IF_FIRST, 0xF8, 5); // interrupt flag for first byte received, direct bit address clear or write 1 to clear - SBIT(S0_IF_BYTE, 0xF8, 4); // interrupt flag for a byte data exchanged, direct bit address clear or write 1 to clear or accessing FIFO to clear if bS0_AUTO_IF=1 - SBIT(S0_FREE, 0xF8, 3); // ReadOnly: SPI0 free status - SBIT(S0_T_FIFO, 0xF8, 2); // ReadOnly: tx FIFO count for SPI0 - SBIT(S0_R_FIFO, 0xF8, 0); // ReadOnly: rx FIFO count for SPI0 -SFR(SPI0_DATA, 0xF9); // FIFO data port: reading for receiving, writing for transmittal -SFR(SPI0_CTRL, 0xFA); // SPI 0 control +SFR(SPI0_STAT, 0xF8); // SPI 0 status + SBIT(S0_FST_ACT, 0xF8, 7); // ReadOnly: indicate first byte received status for SPI0 + SBIT(S0_IF_OV, 0xF8, 6); // interrupt flag for slave mode FIFO overflow, direct bit address clear or write 1 to clear + SBIT(S0_IF_FIRST, 0xF8, 5); // interrupt flag for first byte received, direct bit address clear or write 1 to clear + SBIT(S0_IF_BYTE, 0xF8, 4); // interrupt flag for a byte data exchanged, direct bit address clear or write 1 to clear or accessing FIFO to clear if bS0_AUTO_IF=1 + SBIT(S0_FREE, 0xF8, 3); // ReadOnly: SPI0 free status + SBIT(S0_T_FIFO, 0xF8, 2); // ReadOnly: tx FIFO count for SPI0 + SBIT(S0_R_FIFO, 0xF8, 0); // ReadOnly: rx FIFO count for SPI0 +SFR(SPI0_DATA, 0xF9); // FIFO data port: reading for receive, writing for transmit +SFR(SPI0_CTRL, 0xFA); // SPI 0 control #define bS0_MISO_OE 0x80 // SPI0 MISO output enable #define bS0_MOSI_OE 0x40 // SPI0 MOSI output enable #define bS0_SCK_OE 0x20 // SPI0 SCK output enable @@ -399,10 +399,10 @@ SFR(SPI0_CTRL, 0xFA); // SPI 0 control #define bS0_2_WIRE 0x04 // enable SPI0 two wire mode: 0=3 wire (SCK+MOSI+MISO), 1=2 wire (SCK+MISO) #define bS0_CLR_ALL 0x02 // force clear FIFO and count of SPI0 #define bS0_AUTO_IF 0x01 // enable FIFO accessing to auto clear S0_IF_BYTE interrupt flag -SFR(SPI0_CK_SE, 0xFB); // clock divisor setting +SFR(SPI0_CK_SE, 0xFB); // clock divisor setting //sfr SPI0_S_PRE = 0xFB; // preset value for SPI slave #define SPI0_S_PRE SPI0_CK_SE -SFR(SPI0_SETUP, 0xFC); // SPI 0 setup +SFR(SPI0_SETUP, 0xFC); // SPI 0 setup #define bS0_MODE_SLV 0x80 // SPI0 slave mode: 0=master, 1=slave #define bS0_IE_FIFO_OV 0x40 // enable interrupt for slave mode FIFO overflow #define bS0_IE_FIRST 0x20 // enable interrupt for first byte received for SPI0 slave mode @@ -412,39 +412,39 @@ SFR(SPI0_SETUP, 0xFC); // SPI 0 setup #define bS0_SLV_PRELOAD 0x01 // ReadOnly: SPI0 slave mode data pre-loading status just after chip-selection /* UART1 Registers */ -SFR(SCON1, 0xC0); // UART1 control (serial port control) - SBIT(U1SM0, 0xC0, 7); // UART1 mode, selection data bit: 0=8 bits data, 1=9 bits data - SBIT(U1SMOD, 0xC0, 5); // UART1 2X baud rate selection: 0=slow(Fsys/32/(256-SBAUD1)), 1=fast(Fsys/16/(256-SBAUD1)) - SBIT(U1REN, 0xC0, 4); // enable UART1 receiving - SBIT(U1TB8, 0xC0, 3); // the 9th transmitted data bit in 9 bits data mode - SBIT(U1RB8, 0xC0, 2); // 9th data bit received in 9 bits data mode, or stop bit received for 8 bits data mode - SBIT(U1TI, 0xC0, 1); // transmit interrupt flag, set by hardware after completion of a serial transmittal, need software clear - SBIT(U1RI, 0xC0, 0); // receive interrupt flag, set by hardware after completion of a serial receiving, need software clear -SFR(SBUF1, 0xC1); // UART1 data buffer: reading for receiving, writing for transmittal -SFR(SBAUD1, 0xC2); // UART1 baud rate setting +SFR(SCON1, 0xC0); // UART1 control (serial port control) + SBIT(U1SM0, 0xC0, 7); // UART1 mode, selection data bit: 0=8 bits data, 1=9 bits data + SBIT(U1SMOD, 0xC0, 5); // UART1 2X baud rate selection: 0=slow(Fsys/32/(256-SBAUD1)), 1=fast(Fsys/16/(256-SBAUD1)) + SBIT(U1REN, 0xC0, 4); // enable UART1 receive + SBIT(U1TB8, 0xC0, 3); // the 9th transmitted data bit in 9 bits data mode + SBIT(U1RB8, 0xC0, 2); // 9th data bit received in 9 bits data mode, or stop bit received for 8 bits data mode + SBIT(U1TI, 0xC0, 1); // transmit interrupt flag, set by hardware after completion of a serial transmit, need software clear + SBIT(U1RI, 0xC0, 0); // receive interrupt flag, set by hardware after completion of a serial receive, need software clear +SFR(SBUF1, 0xC1); // UART1 data buffer: reading for receive, writing for transmit +SFR(SBAUD1, 0xC2); // UART1 baud rate setting /* ADC and comparator Registers */ -SFR(ADC_CTRL, 0x80); // ADC control - SBIT(CMPO, 0x80, 7); // ReadOnly: comparator result input - SBIT(CMP_IF, 0x80, 6); // flag for comparator result changed, direct bit address clear - SBIT(ADC_IF, 0x80, 5); // interrupt flag for ADC finished, direct bit address clear - SBIT(ADC_START, 0x80, 4); // set 1 to start ADC, auto cleared when ADC finished - SBIT(CMP_CHAN, 0x80, 3); // comparator IN- input channel selection: 0=AIN1, 1=AIN3 - SBIT(ADC_CHAN1, 0x80, 1); // ADC/comparator IN+ channel selection high bit - SBIT(ADC_CHAN0, 0x80, 0); // ADC/comparator IN+ channel selection low bit +SFR(ADC_CTRL, 0x80); // ADC control + SBIT(CMPO, 0x80, 7); // ReadOnly: comparator result input + SBIT(CMP_IF, 0x80, 6); // flag for comparator result changed, direct bit address clear + SBIT(ADC_IF, 0x80, 5); // interrupt flag for ADC finished, direct bit address clear + SBIT(ADC_START, 0x80, 4); // set 1 to start ADC, auto cleared when ADC finished + SBIT(CMP_CHAN, 0x80, 3); // comparator IN- input channel selection: 0=AIN1, 1=AIN3 + SBIT(ADC_CHAN1, 0x80, 1); // ADC/comparator IN+ channel selection high bit + SBIT(ADC_CHAN0, 0x80, 0); // ADC/comparator IN+ channel selection low bit // ADC_CHAN1 & ADC_CHAN0: ADC/comparator IN+ channel selection // 00: AIN0(P1.1) // 01: AIN1(P1.4) // 10: AIN2(P1.5) // 11: AIN3(P3.2) -SFR(ADC_CFG, 0x9A); // ADC config +SFR(ADC_CFG, 0x9A); // ADC config #define bADC_EN 0x08 // control ADC power: 0=shut down ADC, 1=enable power for ADC #define bCMP_EN 0x04 // control comparator power: 0=shut down comparator, 1=enable power for comparator #define bADC_CLK 0x01 // ADC clock frequency selection: 0=slow clock, 384 Fosc cycles for each ADC, 1=fast clock, 96 Fosc cycles for each ADC -SFR(ADC_DATA, 0x9F); // ReadOnly: ADC data +SFR(ADC_DATA, 0x9F); // ReadOnly: ADC data /* Touch-key timer Registers */ -SFR(TKEY_CTRL, 0xC3); // touch-key control +SFR(TKEY_CTRL, 0xC3); // touch-key control #define bTKC_IF 0x80 // ReadOnly: interrupt flag for touch-key timer, cleared by writing touch-key control or auto cleared when start touch-key checking #define bTKC_2MS 0x10 // touch-key timer cycle selection: 0=1mS, 1=2mS #define bTKC_CHAN2 0x04 // touch-key channel selection high bit @@ -459,13 +459,13 @@ SFR(TKEY_CTRL, 0xC3); // touch-key control // 101: TIN4(P1.6) // 110: TIN5(P1.7) // 111: enable touch-key but disable all channel -SFR16(TKEY_DAT, 0xC4); // ReadOnly: touch-key data, little-endian -SFR(TKEY_DATL, 0xC4); // ReadOnly: low byte of touch-key data -SFR(TKEY_DATH, 0xC5); // ReadOnly: high byte of touch-key data +SFR16(TKEY_DAT, 0xC4); // ReadOnly: touch-key data, little-endian +SFR(TKEY_DATL, 0xC4); // ReadOnly: low byte of touch-key data +SFR(TKEY_DATH, 0xC5); // ReadOnly: high byte of touch-key data #define bTKD_CHG 0x80 // ReadOnly: indicate control changed, current data maybe invalid /* USB/Host/Device Registers */ -SFR(USB_C_CTRL, 0x91); // USB type-C control +SFR(USB_C_CTRL, 0x91); // USB type-C control #define bVBUS2_PD_EN 0x80 // USB VBUS2 10K pulldown resistance: 0=disable, 1=enable pullup #define bUCC2_PD_EN 0x40 // USB CC2 5.1K pulldown resistance: 0=disable, 1=enable pulldown #define bUCC2_PU1_EN 0x20 // USB CC2 pullup resistance control high bit @@ -479,7 +479,7 @@ SFR(USB_C_CTRL, 0x91); // USB type-C control // 01: enable 56K pullup resistance for default USB power // 10: enable 22K pullup resistance for 1.5A USB power // 11: enable 10K pullup resistance for 3A USB power -SFR(UDEV_CTRL, 0xD1); // USB device physical port control +SFR(UDEV_CTRL, 0xD1); // USB device physical port control #define bUD_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable #define bUD_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level #define bUD_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level @@ -494,50 +494,50 @@ SFR(UDEV_CTRL, 0xD1); // USB device physical port control #define bUH_LOW_SPEED 0x04 // enable USB port low speed: 0=full speed, 1=low speed #define bUH_BUS_RESET 0x02 // control USB bus reset: 0=normal, 1=force bus reset #define bUH_PORT_EN 0x01 // enable USB port: 0=disable, 1=enable port, automatic disabled if USB device detached -SFR(UEP1_CTRL, 0xD2); // endpoint 1 control -#define bUEP_R_TOG 0x80 // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1 -#define bUEP_T_TOG 0x40 // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1 +SFR(UEP1_CTRL, 0xD2); // endpoint 1 control +#define bUEP_R_TOG 0x80 // expected data toggle flag of USB endpoint X receive (OUT): 0=DATA0, 1=DATA1 +#define bUEP_T_TOG 0x40 // prepared data toggle flag of USB endpoint X transmit (IN): 0=DATA0, 1=DATA1 #define bUEP_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle -#define bUEP_R_RES1 0x08 // handshake response type high bit for USB endpoint X receiving (OUT) -#define bUEP_R_RES0 0x04 // handshake response type low bit for USB endpoint X receiving (OUT) -#define MASK_UEP_R_RES 0x0C // bit mask of handshake response type for USB endpoint X receiving (OUT) +#define bUEP_R_RES1 0x08 // handshake response type high bit for USB endpoint X receive (OUT) +#define bUEP_R_RES0 0x04 // handshake response type low bit for USB endpoint X receive (OUT) +#define MASK_UEP_R_RES 0x0C // bit mask of handshake response type for USB endpoint X receive (OUT) #define UEP_R_RES_ACK 0x00 #define UEP_R_RES_TOUT 0x04 #define UEP_R_RES_NAK 0x08 #define UEP_R_RES_STALL 0x0C -// bUEP_R_RES1 & bUEP_R_RES0: handshake response type for USB endpoint X receiving (OUT) +// bUEP_R_RES1 & bUEP_R_RES0: handshake response type for USB endpoint X receive (OUT) // 00: ACK (ready) // 01: no response, time out to host, for non-zero endpoint isochronous transactions // 10: NAK (busy) // 11: STALL (error) -#define bUEP_T_RES1 0x02 // handshake response type high bit for USB endpoint X transmittal (IN) -#define bUEP_T_RES0 0x01 // handshake response type low bit for USB endpoint X transmittal (IN) -#define MASK_UEP_T_RES 0x03 // bit mask of handshake response type for USB endpoint X transmittal (IN) +#define bUEP_T_RES1 0x02 // handshake response type high bit for USB endpoint X transmit (IN) +#define bUEP_T_RES0 0x01 // handshake response type low bit for USB endpoint X transmit (IN) +#define MASK_UEP_T_RES 0x03 // bit mask of handshake response type for USB endpoint X transmit (IN) #define UEP_T_RES_ACK 0x00 #define UEP_T_RES_TOUT 0x01 #define UEP_T_RES_NAK 0x02 #define UEP_T_RES_STALL 0x03 -// bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmittal (IN) +// bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmit (IN) // 00: DATA0 or DATA1 then expecting ACK (ready) // 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions // 10: NAK (busy) // 11: STALL (error) -SFR(UEP1_T_LEN, 0xD3); // endpoint 1 transmittal length -SFR(UEP2_CTRL, 0xD4); // endpoint 2 control -SFR(UEP2_T_LEN, 0xD5); // endpoint 2 transmittal length -SFR(UEP3_CTRL, 0xD6); // endpoint 3 control -SFR(UEP3_T_LEN, 0xD7); // endpoint 3 transmittal length -SFR(USB_INT_FG, 0xD8); // USB interrupt flag - SBIT(U_IS_NAK, 0xD8, 7); // ReadOnly: indicate current USB transfer is NAK received - SBIT(U_TOG_OK, 0xD8, 6); // ReadOnly: indicate current USB transfer toggle is OK - SBIT(U_SIE_FREE, 0xD8, 5); // ReadOnly: indicate USB SIE free status - SBIT(UIF_FIFO_OV, 0xD8, 4); // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear - SBIT(UIF_HST_SOF, 0xD8, 3); // host SOF timer interrupt flag for USB host, direct bit address clear or write 1 to clear - SBIT(UIF_SUSPEND, 0xD8, 2); // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear - SBIT(UIF_TRANSFER, 0xD8, 1); // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear - SBIT(UIF_DETECT, 0xD8, 0); // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear - SBIT(UIF_BUS_RST, 0xD8, 0); // bus reset event interrupt flag for USB device mode, direct bit address clear or write 1 to clear -SFR(USB_INT_ST, 0xD9); // ReadOnly: USB interrupt status +SFR(UEP1_T_LEN, 0xD3); // endpoint 1 transmit length +SFR(UEP2_CTRL, 0xD4); // endpoint 2 control +SFR(UEP2_T_LEN, 0xD5); // endpoint 2 transmit length +SFR(UEP3_CTRL, 0xD6); // endpoint 3 control +SFR(UEP3_T_LEN, 0xD7); // endpoint 3 transmit length +SFR(USB_INT_FG, 0xD8); // USB interrupt flag + SBIT(U_IS_NAK, 0xD8, 7); // ReadOnly: indicate current USB transfer is NAK received + SBIT(U_TOG_OK, 0xD8, 6); // ReadOnly: indicate current USB transfer toggle is OK + SBIT(U_SIE_FREE, 0xD8, 5); // ReadOnly: indicate USB SIE free status + SBIT(UIF_FIFO_OV, 0xD8, 4); // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear + SBIT(UIF_HST_SOF, 0xD8, 3); // host SOF timer interrupt flag for USB host, direct bit address clear or write 1 to clear + SBIT(UIF_SUSPEND, 0xD8, 2); // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear + SBIT(UIF_TRANSFER, 0xD8, 1); // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear + SBIT(UIF_DETECT, 0xD8, 0); // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear + SBIT(UIF_BUS_RST, 0xD8, 0); // bus reset event interrupt flag for USB device mode, direct bit address clear or write 1 to clear +SFR(USB_INT_ST, 0xD9); // ReadOnly: USB interrupt status #define bUIS_IS_NAK 0x80 // ReadOnly: indicate current USB transfer is NAK received for USB device mode #define bUIS_TOG_OK 0x40 // ReadOnly: indicate current USB transfer toggle is OK #define bUIS_TOKEN1 0x20 // ReadOnly: current token PID code bit 1 received for USB device mode @@ -554,21 +554,21 @@ SFR(USB_INT_ST, 0xD9); // ReadOnly: USB interrupt status // 11: SETUP token PID received #define MASK_UIS_ENDP 0x0F // ReadOnly: bit mask of current transfer endpoint number for USB device mode #define MASK_UIS_H_RES 0x0F // ReadOnly: bit mask of current transfer handshake response for USB host mode: 0000=no response, time out from device, others=handshake response PID received -SFR(USB_MIS_ST, 0xDA); // ReadOnly: USB miscellaneous status +SFR(USB_MIS_ST, 0xDA); // ReadOnly: USB miscellaneous status #define bUMS_SOF_PRES 0x80 // ReadOnly: indicate host SOF timer presage status #define bUMS_SOF_ACT 0x40 // ReadOnly: indicate host SOF timer action status for USB host #define bUMS_SIE_FREE 0x20 // ReadOnly: indicate USB SIE free status -#define bUMS_R_FIFO_RDY 0x10 // ReadOnly: indicate USB receiving FIFO ready status (not empty) +#define bUMS_R_FIFO_RDY 0x10 // ReadOnly: indicate USB receive FIFO ready status (not empty) #define bUMS_BUS_RESET 0x08 // ReadOnly: indicate USB bus reset status #define bUMS_SUSPEND 0x04 // ReadOnly: indicate USB suspend status #define bUMS_DM_LEVEL 0x02 // ReadOnly: indicate UDM level saved at device attached to USB host #define bUMS_DEV_ATTACH 0x01 // ReadOnly: indicate device attached status on USB host -SFR(USB_RX_LEN, 0xDB); // ReadOnly: USB receiving length -SFR(UEP0_CTRL, 0xDC); // endpoint 0 control -SFR(UEP0_T_LEN, 0xDD); // endpoint 0 transmittal length -SFR(UEP4_CTRL, 0xDE); // endpoint 4 control -SFR(UEP4_T_LEN, 0xDF); // endpoint 4 transmittal length -SFR(USB_INT_EN, 0xE1); // USB interrupt enable +SFR(USB_RX_LEN, 0xDB); // ReadOnly: USB receive length +SFR(UEP0_CTRL, 0xDC); // endpoint 0 control +SFR(UEP0_T_LEN, 0xDD); // endpoint 0 transmit length +SFR(UEP4_CTRL, 0xDE); // endpoint 4 control +SFR(UEP4_T_LEN, 0xDF); // endpoint 4 transmit length +SFR(USB_INT_EN, 0xE1); // USB interrupt enable #define bUIE_DEV_SOF 0x80 // enable interrupt for SOF received for USB device mode #define bUIE_DEV_NAK 0x40 // enable interrupt for NAK responded for USB device mode #define bUIE_FIFO_OV 0x10 // enable interrupt for FIFO overflow @@ -577,7 +577,7 @@ SFR(USB_INT_EN, 0xE1); // USB interrupt enable #define bUIE_TRANSFER 0x02 // enable interrupt for USB transfer completion #define bUIE_DETECT 0x01 // enable interrupt for USB device detected event for USB host mode #define bUIE_BUS_RST 0x01 // enable interrupt for USB bus reset event for USB device mode -SFR(USB_CTRL, 0xE2); // USB base control +SFR(USB_CTRL, 0xE2); // USB base control #define bUC_HOST_MODE 0x80 // enable USB host mode: 0=device mode, 1=host mode #define bUC_LOW_SPEED 0x40 // enable USB low speed: 0=full speed, 1=low speed #define bUC_DEV_PU_EN 0x20 // USB device enable and internal pullup resistance enable @@ -596,82 +596,82 @@ SFR(USB_CTRL, 0xE2); // USB base control #define bUC_RESET_SIE 0x04 // force reset USB SIE, need software clear #define bUC_CLR_ALL 0x02 // force clear FIFO and count of USB #define bUC_DMA_EN 0x01 // DMA enable and DMA interrupt enable for USB -SFR(USB_DEV_AD, 0xE3); // USB device address, lower 7 bits for USB device address +SFR(USB_DEV_AD, 0xE3); // USB device address, lower 7 bits for USB device address #define bUDA_GP_BIT 0x80 // general purpose bit #define MASK_USB_ADDR 0x7F // bit mask for USB device address -SFR16(UEP2_DMA, 0xE4); // endpoint 2 buffer start address, little-endian -SFR(UEP2_DMA_L, 0xE4); // endpoint 2 buffer start address low byte -SFR(UEP2_DMA_H, 0xE5); // endpoint 2 buffer start address high byte -SFR16(UEP3_DMA, 0xE6); // endpoint 3 buffer start address, little-endian -SFR(UEP3_DMA_L, 0xE6); // endpoint 3 buffer start address low byte -SFR(UEP3_DMA_H, 0xE7); // endpoint 3 buffer start address high byte -SFR(UEP4_1_MOD, 0xEA); // endpoint 4/1 mode -#define bUEP1_RX_EN 0x80 // enable USB endpoint 1 receiving (OUT) -#define bUEP1_TX_EN 0x40 // enable USB endpoint 1 transmittal (IN) +SFR16(UEP2_DMA, 0xE4); // endpoint 2 buffer start address, little-endian +SFR(UEP2_DMA_L, 0xE4); // endpoint 2 buffer start address low byte +SFR(UEP2_DMA_H, 0xE5); // endpoint 2 buffer start address high byte +SFR16(UEP3_DMA, 0xE6); // endpoint 3 buffer start address, little-endian +SFR(UEP3_DMA_L, 0xE6); // endpoint 3 buffer start address low byte +SFR(UEP3_DMA_H, 0xE7); // endpoint 3 buffer start address high byte +SFR(UEP4_1_MOD, 0xEA); // endpoint 4/1 mode +#define bUEP1_RX_EN 0x80 // enable USB endpoint 1 receive (OUT) +#define bUEP1_TX_EN 0x40 // enable USB endpoint 1 transmit (IN) #define bUEP1_BUF_MOD 0x10 // buffer mode of USB endpoint 1 // bUEPn_RX_EN & bUEPn_TX_EN & bUEPn_BUF_MOD: USB endpoint 1/2/3 buffer mode, buffer start address is UEPn_DMA // 0 0 x: disable endpoint and disable buffer -// 1 0 0: 64 bytes buffer for receiving (OUT endpoint) -// 1 0 1: dual 64 bytes buffer by toggle bit bUEP_R_TOG selection for receiving (OUT endpoint), total=128bytes -// 0 1 0: 64 bytes buffer for transmittal (IN endpoint) -// 0 1 1: dual 64 bytes buffer by toggle bit bUEP_T_TOG selection for transmittal (IN endpoint), total=128bytes -// 1 1 0: 64 bytes buffer for receiving (OUT endpoint) + 64 bytes buffer for transmittal (IN endpoint), total=128bytes -// 1 1 1: dual 64 bytes buffer by bUEP_R_TOG selection for receiving (OUT endpoint) + dual 64 bytes buffer by bUEP_T_TOG selection for transmittal (IN endpoint), total=256bytes -#define bUEP4_RX_EN 0x08 // enable USB endpoint 4 receiving (OUT) -#define bUEP4_TX_EN 0x04 // enable USB endpoint 4 transmittal (IN) +// 1 0 0: 64 bytes buffer for receive (OUT endpoint) +// 1 0 1: dual 64 bytes buffer by toggle bit bUEP_R_TOG selection for receive (OUT endpoint), total=128bytes +// 0 1 0: 64 bytes buffer for transmit (IN endpoint) +// 0 1 1: dual 64 bytes buffer by toggle bit bUEP_T_TOG selection for transmit (IN endpoint), total=128bytes +// 1 1 0: 64 bytes buffer for receive (OUT endpoint) + 64 bytes buffer for transmit (IN endpoint), total=128bytes +// 1 1 1: dual 64 bytes buffer by bUEP_R_TOG selection for receive (OUT endpoint) + dual 64 bytes buffer by bUEP_T_TOG selection for transmit (IN endpoint), total=256bytes +#define bUEP4_RX_EN 0x08 // enable USB endpoint 4 receive (OUT) +#define bUEP4_TX_EN 0x04 // enable USB endpoint 4 transmit (IN) // bUEP4_RX_EN & bUEP4_TX_EN: USB endpoint 4 buffer mode, buffer start address is UEP0_DMA -// 0 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) -// 1 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 receiving (OUT endpoint), total=128bytes -// 0 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=128bytes -// 1 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) -// + 64 bytes buffer for endpoint 4 receiving (OUT endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=192bytes -SFR(UEP2_3_MOD, 0xEB); // endpoint 2/3 mode -#define bUEP3_RX_EN 0x80 // enable USB endpoint 3 receiving (OUT) -#define bUEP3_TX_EN 0x40 // enable USB endpoint 3 transmittal (IN) +// 0 0: single 64 bytes buffer for endpoint 0 receive & transmit (OUT & IN endpoint) +// 1 0: single 64 bytes buffer for endpoint 0 receive & transmit (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 receive (OUT endpoint), total=128bytes +// 0 1: single 64 bytes buffer for endpoint 0 receive & transmit (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 transmit (IN endpoint), total=128bytes +// 1 1: single 64 bytes buffer for endpoint 0 receive & transmit (OUT & IN endpoint) +// + 64 bytes buffer for endpoint 4 receive (OUT endpoint) + 64 bytes buffer for endpoint 4 transmit (IN endpoint), total=192bytes +SFR(UEP2_3_MOD, 0xEB); // endpoint 2/3 mode +#define bUEP3_RX_EN 0x80 // enable USB endpoint 3 receive (OUT) +#define bUEP3_TX_EN 0x40 // enable USB endpoint 3 transmit (IN) #define bUEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3 -#define bUEP2_RX_EN 0x08 // enable USB endpoint 2 receiving (OUT) -#define bUEP2_TX_EN 0x04 // enable USB endpoint 2 transmittal (IN) +#define bUEP2_RX_EN 0x08 // enable USB endpoint 2 receive (OUT) +#define bUEP2_TX_EN 0x04 // enable USB endpoint 2 transmit (IN) #define bUEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2 -SFR16(UEP0_DMA, 0xEC); // endpoint 0 buffer start address, little-endian -SFR(UEP0_DMA_L, 0xEC); // endpoint 0 buffer start address low byte -SFR(UEP0_DMA_H, 0xED); // endpoint 0 buffer start address high byte -SFR16(UEP1_DMA, 0xEE); // endpoint 1 buffer start address, little-endian -SFR(UEP1_DMA_L, 0xEE); // endpoint 1 buffer start address low byte -SFR(UEP1_DMA_H, 0xEF); // endpoint 1 buffer start address high byte +SFR16(UEP0_DMA, 0xEC); // endpoint 0 buffer start address, little-endian +SFR(UEP0_DMA_L, 0xEC); // endpoint 0 buffer start address low byte +SFR(UEP0_DMA_H, 0xED); // endpoint 0 buffer start address high byte +SFR16(UEP1_DMA, 0xEE); // endpoint 1 buffer start address, little-endian +SFR(UEP1_DMA_L, 0xEE); // endpoint 1 buffer start address low byte +SFR(UEP1_DMA_H, 0xEF); // endpoint 1 buffer start address high byte //sfr UH_SETUP = 0xD2; // host aux setup #define UH_SETUP UEP1_CTRL #define bUH_PRE_PID_EN 0x80 // USB host PRE PID enable for low speed device via hub #define bUH_SOF_EN 0x40 // USB host automatic SOF enable //sfr UH_RX_CTRL = 0xD4; // host receiver endpoint control #define UH_RX_CTRL UEP2_CTRL -#define bUH_R_TOG 0x80 // expected data toggle flag of host receiving (IN): 0=DATA0, 1=DATA1 +#define bUH_R_TOG 0x80 // expected data toggle flag of host receive (IN): 0=DATA0, 1=DATA1 #define bUH_R_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle -#define bUH_R_RES 0x04 // prepared handshake response type for host receiving (IN): 0=ACK (ready), 1=no response, time out to device, for isochronous transactions +#define bUH_R_RES 0x04 // prepared handshake response type for host receive (IN): 0=ACK (ready), 1=no response, time out to device, for isochronous transactions //sfr UH_EP_PID = 0xD5; // host endpoint and token PID, lower 4 bits for endpoint number, upper 4 bits for token PID #define UH_EP_PID UEP2_T_LEN #define MASK_UH_TOKEN 0xF0 // bit mask of token PID for USB host transfer #define MASK_UH_ENDP 0x0F // bit mask of endpoint number for USB host transfer -//sfr UH_TX_CTRL = 0xD6; // host transmittal endpoint control +//sfr UH_TX_CTRL = 0xD6; // host transmit endpoint control #define UH_TX_CTRL UEP3_CTRL -#define bUH_T_TOG 0x40 // prepared data toggle flag of host transmittal (SETUP/OUT): 0=DATA0, 1=DATA1 +#define bUH_T_TOG 0x40 // prepared data toggle flag of host transmit (SETUP/OUT): 0=DATA0, 1=DATA1 #define bUH_T_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle -#define bUH_T_RES 0x01 // expected handshake response type for host transmittal (SETUP/OUT): 0=ACK (ready), 1=no response, time out from device, for isochronous transactions -//sfr UH_TX_LEN = 0xD7; // host transmittal endpoint transmittal length +#define bUH_T_RES 0x01 // expected handshake response type for host transmit (SETUP/OUT): 0=ACK (ready), 1=no response, time out from device, for isochronous transactions +//sfr UH_TX_LEN = 0xD7; // host transmit endpoint transmit length #define UH_TX_LEN UEP3_T_LEN //sfr UH_EP_MOD = 0xEB; // host endpoint mode #define UH_EP_MOD UEP2_3_MOD -#define bUH_EP_TX_EN 0x40 // enable USB host OUT endpoint transmittal +#define bUH_EP_TX_EN 0x40 // enable USB host OUT endpoint transmit #define bUH_EP_TBUF_MOD 0x10 // buffer mode of USB host OUT endpoint // bUH_EP_TX_EN & bUH_EP_TBUF_MOD: USB host OUT endpoint buffer mode, buffer start address is UH_TX_DMA // 0 x: disable endpoint and disable buffer -// 1 0: 64 bytes buffer for transmittal (OUT endpoint) -// 1 1: dual 64 bytes buffer by toggle bit bUH_T_TOG selection for transmittal (OUT endpoint), total=128bytes -#define bUH_EP_RX_EN 0x08 // enable USB host IN endpoint receiving +// 1 0: 64 bytes buffer for transmit (OUT endpoint) +// 1 1: dual 64 bytes buffer by toggle bit bUH_T_TOG selection for transmit (OUT endpoint), total=128bytes +#define bUH_EP_RX_EN 0x08 // enable USB host IN endpoint receive #define bUH_EP_RBUF_MOD 0x01 // buffer mode of USB host IN endpoint // bUH_EP_RX_EN & bUH_EP_RBUF_MOD: USB host IN endpoint buffer mode, buffer start address is UH_RX_DMA // 0 x: disable endpoint and disable buffer -// 1 0: 64 bytes buffer for receiving (IN endpoint) -// 1 1: dual 64 bytes buffer by toggle bit bUH_R_TOG selection for receiving (IN endpoint), total=128bytes +// 1 0: 64 bytes buffer for receive (IN endpoint) +// 1 1: dual 64 bytes buffer by toggle bit bUH_R_TOG selection for receive (IN endpoint), total=128bytes //sfr16 UH_RX_DMA = 0xE4; // host rx endpoint buffer start address, little-endian #define UH_RX_DMA UEP2_DMA //sfr UH_RX_DMA_L = 0xE4; // host rx endpoint buffer start address low byte diff --git a/hw/usb_interface/ch552_fw/include/ch554_usb.h b/hw/usb_interface/ch552_fw/include/ch554_usb.h index 34d0d25..57695da 100644 --- a/hw/usb_interface/ch552_fw/include/ch554_usb.h +++ b/hw/usb_interface/ch552_fw/include/ch554_usb.h @@ -11,6 +11,8 @@ Header file for CH554 microcontrollers. #ifndef __USB_DEF__ #define __USB_DEF__ +#include "mem.h" + /*----- USB constant and structure define --------------------------------*/ /* USB PID */ @@ -53,34 +55,41 @@ Header file for CH554 microcontrollers. #define HUB_SET_DESCRIPTOR 0x07 #endif -/* USB HID class request code */ -#ifndef HID_GET_REPORT -#define HID_GET_REPORT 0x01 -#define HID_GET_IDLE 0x02 -#define HID_GET_PROTOCOL 0x03 -#define HID_SET_REPORT 0x09 -#define HID_SET_IDLE 0x0A -#define HID_SET_PROTOCOL 0x0B -#endif - /* Bit define for USB request type */ -#ifndef USB_REQ_TYP_MASK -#define USB_REQ_TYP_IN 0x80 /* control IN, device to host */ -#define USB_REQ_TYP_OUT 0x00 /* control OUT, host to device */ -#define USB_REQ_TYP_READ 0x80 /* control read, device to host */ -#define USB_REQ_TYP_WRITE 0x00 /* control write, host to device */ -#define USB_REQ_TYP_MASK 0x60 /* bit mask of request type */ -#define USB_REQ_TYP_STANDARD 0x00 -#define USB_REQ_TYP_CLASS 0x20 -#define USB_REQ_TYP_VENDOR 0x40 -#define USB_REQ_TYP_RESERVED 0x60 -#define USB_REQ_RECIP_MASK 0x1F /* bit mask of request recipient */ +#ifndef USB_REQ_TYPE_MASK +#define USB_REQ_TYPE_IN 0x80 /* Control IN, device to host */ +#define USB_REQ_TYPE_OUT 0x00 /* Control OUT, host to device */ +#define USB_REQ_TYPE_READ 0x80 /* Control read, device to host */ +#define USB_REQ_TYPE_WRITE 0x00 /* Control write, host to device */ +#define USB_REQ_TYPE_MASK 0x60 /* Bit mask of request type */ +#define USB_REQ_TYPE_STANDARD 0x00 +#define USB_REQ_TYPE_CLASS 0x20 +#define USB_REQ_TYPE_VENDOR 0x40 +#define USB_REQ_TYPE_RESERVED 0x60 +#define USB_REQ_RECIP_MASK 0x1F /* Bit mask of request recipient */ #define USB_REQ_RECIP_DEVICE 0x00 #define USB_REQ_RECIP_INTERF 0x01 #define USB_REQ_RECIP_ENDP 0x02 #define USB_REQ_RECIP_OTHER 0x03 #endif +/* USB HID class request code */ +#ifndef USB_HID_REQ_TYPE +#define USB_HID_REQ_TYPE_GET_REPORT 0x01 +#define USB_HID_REQ_TYPE_GET_IDLE 0x02 +#define USB_HID_REQ_TYPE_GET_PROTOCOL 0x03 +#define USB_HID_REQ_TYPE_SET_REPORT 0x09 +#define USB_HID_REQ_TYPE_SET_IDLE 0x0A +#define USB_HID_REQ_TYPE_SET_PROTOCOL 0x0B +#endif + +/* USB CDC class request code */ +#ifndef USB_CDC_REQ_TYPE +#define USB_CDC_REQ_TYPE_SET_LINE_CODING 0x20 +#define USB_CDC_REQ_TYPE_GET_LINE_CODING 0x21 +#define USB_CDC_REQ_TYPE_SET_CONTROL_LINE_STATE 0x22 +#endif + /* USB request type for hub class request */ #ifndef HUB_GET_HUB_DESCRIPTOR #define HUB_CLEAR_HUB_FEATURE 0x20 @@ -96,95 +105,127 @@ Header file for CH554 microcontrollers. /* Hub class feature selectors */ #ifndef HUB_PORT_RESET -#define HUB_C_HUB_LOCAL_POWER 0 -#define HUB_C_HUB_OVER_CURRENT 1 -#define HUB_PORT_CONNECTION 0 -#define HUB_PORT_ENABLE 1 -#define HUB_PORT_SUSPEND 2 -#define HUB_PORT_OVER_CURRENT 3 -#define HUB_PORT_RESET 4 -#define HUB_PORT_POWER 8 -#define HUB_PORT_LOW_SPEED 9 -#define HUB_C_PORT_CONNECTION 16 -#define HUB_C_PORT_ENABLE 17 -#define HUB_C_PORT_SUSPEND 18 -#define HUB_C_PORT_OVER_CURRENT 19 -#define HUB_C_PORT_RESET 20 +#define HUB_C_HUB_LOCAL_POWER 0 +#define HUB_C_HUB_OVER_CURRENT 1 +#define HUB_PORT_CONNECTION 0 +#define HUB_PORT_ENABLE 1 +#define HUB_PORT_SUSPEND 2 +#define HUB_PORT_OVER_CURRENT 3 +#define HUB_PORT_RESET 4 +#define HUB_PORT_POWER 8 +#define HUB_PORT_LOW_SPEED 9 +#define HUB_C_PORT_CONNECTION 16 +#define HUB_C_PORT_ENABLE 17 +#define HUB_C_PORT_SUSPEND 18 +#define HUB_C_PORT_OVER_CURRENT 19 +#define HUB_C_PORT_RESET 20 #endif /* USB descriptor type */ -#ifndef USB_DESCR_TYP_DEVICE -#define USB_DESCR_TYP_DEVICE 0x01 -#define USB_DESCR_TYP_CONFIG 0x02 -#define USB_DESCR_TYP_STRING 0x03 -#define USB_DESCR_TYP_INTERF 0x04 -#define USB_DESCR_TYP_ENDP 0x05 -#define USB_DESCR_TYP_QUALIF 0x06 -#define USB_DESCR_TYP_SPEED 0x07 -#define USB_DESCR_TYP_OTG 0x09 -#define USB_DESCR_TYP_HID 0x21 -#define USB_DESCR_TYP_REPORT 0x22 -#define USB_DESCR_TYP_PHYSIC 0x23 -#define USB_DESCR_TYP_CS_INTF 0x24 -#define USB_DESCR_TYP_CS_ENDP 0x25 -#define USB_DESCR_TYP_HUB 0x29 +#ifndef USB_DESC_TYPE_DEVICE +#define USB_DESC_TYPE_DEVICE 0x01 // USB 1.1 +#define USB_DESC_TYPE_CONFIGURATION 0x02 // USB 1.1 +#define USB_DESC_TYPE_STRING 0x03 // USB 1.1 +#define USB_DESC_TYPE_INTERFACE 0x04 // USB 1.1 +#define USB_DESC_TYPE_ENDPOINT 0x05 // USB 1.1 +#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06 // USB 2.0 +#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07 // USB 2.0 +#define USB_DESC_TYPE_INTERFACE_POWER 0x08 // USB 2.0 +#define USB_DESC_TYPE_OTG 0x09 // USB 2.0 +#define USB_DESC_TYPE_DEBUG 0x0A // USB 2.0 +#define USB_DESC_TYPE_INTERFACE_ASSOCIATION 0x0B // USB 2.0 +#define USB_DESC_TYPE_BOS 0x0F // USB 3.x (Binary Object Store) +#define USB_DESC_TYPE_DEVICE_CAPABILITY 0x10 // USB 3.x +#define USB_DESC_TYPE_HID 0x21 // HID 1.11 +#define USB_DESC_TYPE_REPORT 0x22 // HID 1.11 +#define USB_DESC_TYPE_PHYSICAL 0x23 // HID 1.11 +#define USB_DESC_TYPE_CS_INTERFACE 0x24 // Class-Specific (Audio, HID, CDC, etc.) +#define USB_DESC_TYPE_CS_ENDPOINT 0x25 // Class-Specific (Audio, Not HID normally, CDC, etc.) +#define USB_DESC_TYPE_SUPERSPEED_USB_ENDPOINT_COMPANION 0x30 // USB 3.x +#define USB_DESC_TYPE_SUPERSPEEDPLUS_ISOCHRONOUS_ENDPOINT_COMPANION 0x31 // USB 3.x #endif /* USB device class */ -#ifndef USB_DEV_CLASS_HUB -#define USB_DEV_CLASS_RESERVED 0x00 -#define USB_DEV_CLASS_AUDIO 0x01 -#define USB_DEV_CLASS_COMMUNIC 0x02 -#define USB_DEV_CLASS_HID 0x03 -#define USB_DEV_CLASS_MONITOR 0x04 -#define USB_DEV_CLASS_PHYSIC_IF 0x05 -#define USB_DEV_CLASS_POWER 0x06 -#define USB_DEV_CLASS_PRINTER 0x07 -#define USB_DEV_CLASS_STORAGE 0x08 -#define USB_DEV_CLASS_HUB 0x09 -#define USB_DEV_CLASS_VEN_SPEC 0xFF +#ifndef USB_DEV_CLASS + // Descriptor Usage; Description ; Examples +#define USB_DEV_CLASS_RESERVED 0x00 // Device ; Unspecified ; Device class is unspecified, interface descriptors are used to determine needed drivers +#define USB_DEV_CLASS_AUDIO 0x01 // Interface ; Audio ; Speaker, microphone, sound card, MIDI +#define USB_DEV_CLASS_CDC_CONTROL 0x02 // Both ; Communications and CDC control ; UART and RS-232 serial adapter, modem, Wi-Fi adapter, Ethernet adapter. Used together with class 0Ah (CDC-Data) below +#define USB_DEV_CLASS_HID 0x03 // Interface ; Human interface device (HID) ; Keyboard, mouse, joystick +#define USB_DEV_CLASS_PHYSICAL 0x05 // Interface ; Physical interface device (PID) ; Force feedback joystick +#define USB_DEV_CLASS_IMAGE 0x06 // Interface ; Media (PTP/MTP) ; Scanner, Camera +#define USB_DEV_CLASS_PRINTER 0x07 // Interface ; Printer ; Laser printer, inkjet printer, CNC machine +#define USB_DEV_CLASS_MASS_STORAGE 0x08 // Interface ; USB mass storage, USB Attached SCSI ; USB flash drive, memory card reader, digital audio player, digital camera, external drive +#define USB_DEV_CLASS_HUB 0x09 // Device ; USB hub ; High speed USB hub +#define USB_DEV_CLASS_CDC_DATA 0x0A // Interface ; CDC-Data ; Used together with class 02h (Communications and CDC Control) above +#define USB_DEV_CLASS_SMART_CARD 0x0B // Interface ; Smart card ; USB smart card reader +#define USB_DEV_CLASS_CONTENT_SECURITY 0x0D // Interface ; Content security ; Fingerprint reader +#define USB_DEV_CLASS_VIDEO 0x0E // Interface ; Video ; Webcam +#define USB_DEV_CLASS_PERSONAL_HEALTHCARE 0x0F // Interface ; Personal healthcare device class (PHDC) ; Pulse monitor (watch) +#define USB_DEV_CLASS_AUDIO_VIDEO DEVICES 0x10 // Interface ; Audio/Video (AV) ; Webcam, TV +#define USB_DEV_CLASS_BILLBOARD 0x11 // Device ; Billboard ; Describes USB-C alternate modes supported by device +#define USB_DEV_CLASS_USB_TYPE_C_BRIDGE 0x12 // Interface ; ; +#define USB_DEV_CLASS_USB_BULK_DISPLAY 0x13 // Interface ; ; +#define USB_DEV_CLASS_MCTP_OVER_USB 0x14 // Interface ; ; +#define USB_DEV_CLASS_I3C_DEVICE_CLASS 0x3C // Interface ; ; +#define USB_DEV_CLASS_DIAGNOSTIC_DEVICE 0xDC // Both ; Diagnostic device ; USB compliance testing device +#define USB_DEV_CLASS_WIRELESS_CONTROLLER 0xE0 // Interface ; Wireless Controller ; Bluetooth adapter, Microsoft RNDIS +#define USB_DEV_CLASS_MISCELLANEOUS 0xEF // Both ; Miscellaneous ; ActiveSync device +#define USB_DEV_CLASS_APPLICATION_SPECIFIC 0xFE // Interface ; Application-specific ; IrDA Bridge, Test & Measurement Class (USBTMC), USB DFU (Device Firmware Upgrade) +#define USB_DEV_CLASS_VENDOR_SPECIFIC 0xFF // Both ; Vendor-specific ; Indicates that a device needs vendor-specific drivers #endif /* USB endpoint type and attributes */ -#ifndef USB_ENDP_TYPE_MASK -#define USB_ENDP_DIR_MASK 0x80 -#define USB_ENDP_ADDR_MASK 0x0F -#define USB_ENDP_TYPE_MASK 0x03 -#define USB_ENDP_TYPE_CTRL 0x00 -#define USB_ENDP_TYPE_ISOCH 0x01 -#define USB_ENDP_TYPE_BULK 0x02 -#define USB_ENDP_TYPE_INTER 0x03 +#ifndef USB_EP_TYPE_MASK +#define USB_EP_TYPE_CONTROL 0x00 +#define USB_EP_TYPE_ISOCHRONOUS 0x01 +#define USB_EP_TYPE_BULK 0x02 +#define USB_EP_TYPE_INTERRUPT 0x03 + +#define USB_EP_DIR_MASK 0x80 +#define USB_EP_ADDR_MASK 0x0F +#define USB_EP_TYPE_MASK 0x03 +#endif + +/* USB string index */ +#ifndef USB_IDX_STR +#define USB_IDX_LANGID_STR 0x00 +#define USB_IDX_MFC_STR 0x01 +#define USB_IDX_PRODUCT_STR 0x02 +#define USB_IDX_SERIAL_STR 0x03 +#define USB_IDX_CONFIG_STR 0x04 +#define USB_IDX_INTERFACE_STR 0x05 #endif #ifndef USB_DEVICE_ADDR -#define USB_DEVICE_ADDR 0x02 /* ĬϵUSB豸ַ */ +#define USB_DEVICE_ADDR 0x02 #endif -#ifndef DEFAULT_ENDP0_SIZE -#define DEFAULT_ENDP0_SIZE 8 /* default maximum packet size for endpoint 0 */ +#ifndef DEFAULT_EP0_SIZE +#define DEFAULT_EP0_SIZE 8 /* Default maximum packet size for Endpoint 0 */ #endif -#ifndef DEFAULT_ENDP1_SIZE -#define DEFAULT_ENDP1_SIZE 8 /* default maximum packet size for endpoint 1 */ +#ifndef DEFAULT_EP1_SIZE +#define DEFAULT_EP1_SIZE 8 /* Default maximum packet size for Endpoint 1 */ #endif #ifndef MAX_PACKET_SIZE -#define MAX_PACKET_SIZE 64 /* maximum packet size */ +#define MAX_PACKET_SIZE 64 /* Maximum packet size */ #endif #ifndef USB_BO_CBW_SIZE -#define USB_BO_CBW_SIZE 0x1F /* CBWܳ */ -#define USB_BO_CSW_SIZE 0x0D /* ״̬CSWܳ */ +#define USB_BO_CBW_SIZE 0x1F +#define USB_BO_CSW_SIZE 0x0D #endif #ifndef USB_BO_CBW_SIG0 -#define USB_BO_CBW_SIG0 0x55 /* CBWʶ־'USBC' */ +#define USB_BO_CBW_SIG0 0x55 #define USB_BO_CBW_SIG1 0x53 #define USB_BO_CBW_SIG2 0x42 #define USB_BO_CBW_SIG3 0x43 -#define USB_BO_CSW_SIG0 0x55 /* ״̬CSWʶ־'USBS' */ +#define USB_BO_CSW_SIG0 0x55 #define USB_BO_CSW_SIG1 0x53 #define USB_BO_CSW_SIG2 0x42 #define USB_BO_CSW_SIG3 0x53 #endif typedef struct _USB_SETUP_REQ { - uint8_t bRequestType; + uint8_t bmRequestType; uint8_t bRequest; uint8_t wValueL; uint8_t wValueH; @@ -194,7 +235,7 @@ typedef struct _USB_SETUP_REQ { uint8_t wLengthH; } USB_SETUP_REQ, *PUSB_SETUP_REQ; -typedef USB_SETUP_REQ __xdata *PXUSB_SETUP_REQ; +typedef USB_SETUP_REQ XDATA *PXUSB_SETUP_REQ; typedef struct _USB_DEVICE_DESCR { uint8_t bLength; @@ -217,7 +258,7 @@ typedef struct _USB_DEVICE_DESCR { uint8_t bNumConfigurations; } USB_DEV_DESCR, *PUSB_DEV_DESCR; -typedef USB_DEV_DESCR __xdata *PXUSB_DEV_DESCR; +typedef USB_DEV_DESCR XDATA *PXUSB_DEV_DESCR; typedef struct _USB_CONFIG_DESCR { uint8_t bLength; @@ -231,7 +272,7 @@ typedef struct _USB_CONFIG_DESCR { uint8_t MaxPower; } USB_CFG_DESCR, *PUSB_CFG_DESCR; -typedef USB_CFG_DESCR __xdata *PXUSB_CFG_DESCR; +typedef USB_CFG_DESCR XDATA *PXUSB_CFG_DESCR; typedef struct _USB_INTERF_DESCR { uint8_t bLength; @@ -245,7 +286,7 @@ typedef struct _USB_INTERF_DESCR { uint8_t iInterface; } USB_ITF_DESCR, *PUSB_ITF_DESCR; -typedef USB_ITF_DESCR __xdata *PXUSB_ITF_DESCR; +typedef USB_ITF_DESCR XDATA *PXUSB_ITF_DESCR; typedef struct _USB_ENDPOINT_DESCR { uint8_t bLength; @@ -257,7 +298,7 @@ typedef struct _USB_ENDPOINT_DESCR { uint8_t bInterval; } USB_ENDP_DESCR, *PUSB_ENDP_DESCR; -typedef USB_ENDP_DESCR __xdata *PXUSB_ENDP_DESCR; +typedef USB_ENDP_DESCR XDATA *PXUSB_ENDP_DESCR; typedef struct _USB_CONFIG_DESCR_LONG { USB_CFG_DESCR cfg_descr; @@ -265,7 +306,7 @@ typedef struct _USB_CONFIG_DESCR_LONG { USB_ENDP_DESCR endp_descr[1]; } USB_CFG_DESCR_LONG, *PUSB_CFG_DESCR_LONG; -typedef USB_CFG_DESCR_LONG __xdata *PXUSB_CFG_DESCR_LONG; +typedef USB_CFG_DESCR_LONG XDATA *PXUSB_CFG_DESCR_LONG; typedef struct _USB_HUB_DESCR { uint8_t bDescLength; @@ -279,7 +320,7 @@ typedef struct _USB_HUB_DESCR { uint8_t PortPwrCtrlMask; } USB_HUB_DESCR, *PUSB_HUB_DESCR; -typedef USB_HUB_DESCR __xdata *PXUSB_HUB_DESCR; +typedef USB_HUB_DESCR XDATA *PXUSB_HUB_DESCR; typedef struct _USB_HID_DESCR { uint8_t bLength; @@ -293,9 +334,9 @@ typedef struct _USB_HID_DESCR { uint8_t wDescriptorLengthH; } USB_HID_DESCR, *PUSB_HID_DESCR; -typedef USB_HID_DESCR __xdata *PXUSB_HID_DESCR; +typedef USB_HID_DESCR XDATA *PXUSB_HID_DESCR; -typedef struct _UDISK_BOC_CBW { /* command of BulkOnly USB-FlashDisk */ +typedef struct _UDISK_BOC_CBW { /* Command of BulkOnly USB-FlashDisk */ uint8_t mCBW_Sig0; uint8_t mCBW_Sig1; uint8_t mCBW_Sig2; @@ -307,16 +348,16 @@ typedef struct _UDISK_BOC_CBW { /* command of BulkOnly USB-FlashDisk */ uint8_t mCBW_DataLen0; uint8_t mCBW_DataLen1; uint8_t mCBW_DataLen2; - uint8_t mCBW_DataLen3; /* uppest byte of data length, always is 0 */ - uint8_t mCBW_Flag; /* transfer direction and etc. */ + uint8_t mCBW_DataLen3; /* MSB byte of data length, always is 0 */ + uint8_t mCBW_Flag; /* Transfer direction and etc. */ uint8_t mCBW_LUN; - uint8_t mCBW_CB_Len; /* length of command block */ - uint8_t mCBW_CB_Buf[16]; /* command block buffer */ + uint8_t mCBW_CB_Len; /* Length of command block */ + uint8_t mCBW_CB_Buf[16]; /* Command block buffer */ } UDISK_BOC_CBW, *PUDISK_BOC_CBW; -typedef UDISK_BOC_CBW __xdata *PXUDISK_BOC_CBW; +typedef UDISK_BOC_CBW XDATA *PXUDISK_BOC_CBW; -typedef struct _UDISK_BOC_CSW { /* status of BulkOnly USB-FlashDisk */ +typedef struct _UDISK_BOC_CSW { /* Status of BulkOnly USB-FlashDisk */ uint8_t mCSW_Sig0; uint8_t mCSW_Sig1; uint8_t mCSW_Sig2; @@ -325,13 +366,13 @@ typedef struct _UDISK_BOC_CSW { /* status of BulkOnly USB-FlashDisk */ uint8_t mCSW_Tag1; uint8_t mCSW_Tag2; uint8_t mCSW_Tag3; - uint8_t mCSW_Residue0; /* return: remainder bytes */ + uint8_t mCSW_Residue0; /* Return: remainder bytes */ uint8_t mCSW_Residue1; uint8_t mCSW_Residue2; - uint8_t mCSW_Residue3; /* uppest byte of remainder length, always is 0 */ - uint8_t mCSW_Status; /* return: result status */ + uint8_t mCSW_Residue3; /* MSB byte of remainder length, always is 0 */ + uint8_t mCSW_Status; /* Return: result status */ } UDISK_BOC_CSW, *PUDISK_BOC_CSW; -typedef UDISK_BOC_CSW __xdata *PXUDISK_BOC_CSW; +typedef UDISK_BOC_CSW XDATA *PXUDISK_BOC_CSW; #endif // __USB_DEF__ diff --git a/hw/usb_interface/ch552_fw/include/debug.c b/hw/usb_interface/ch552_fw/include/debug.c index de91a0c..fac182d 100644 --- a/hw/usb_interface/ch552_fw/include/debug.c +++ b/hw/usb_interface/ch552_fw/include/debug.c @@ -4,10 +4,10 @@ * Version : V1.0 * Date : 2017/01/20 * Description : CH554 DEBUG Interface - CH554 main frequency modification, delay function definition -                     Serial port 0 and serial port 1 initialization -                     Serial port 0 and serial port 1 transceiver subfunctions -                     Watchdog initialization + CH554 main frequency modification, delay function definition + Serial port 0 and serial port 1 initialization + Serial port 0 and serial port 1 transceiver subfunctions + Watchdog initialization *******************************************************************************/ #include @@ -17,42 +17,40 @@ /******************************************************************************* * Function Name : CfgFsys( ) -* Description : CH554 clock selection and configuration function, Fsys 6MHz is used by default, FREQ_SYS can be passed -                 CLOCK_CFG configuration, the formula is as follows: -                 Fsys = (Fosc * 4 / (CLOCK_CFG & MASK_SYS_CK_SEL); the specific clock needs to be configured by yourself +* Description : CH554 clock selection and configuration function, Fsys 6MHz is used by default, FREQ_SYS can be passed + CLOCK_CFG configuration, the formula is as follows: + Fsys = (Fosc * 4 / (CLOCK_CFG & MASK_SYS_CK_SEL); the specific clock needs to be configured by yourself *******************************************************************************/ -void CfgFsys( ) +void CfgFsys() { - SAFE_MOD = 0x55; - SAFE_MOD = 0xAA; -// CLOCK_CFG |= bOSC_EN_XT; // Enable external crystal -// CLOCK_CFG & = ~ bOSC_EN_INT; // Turn off the internal crystal + SAFE_MOD = 0x55; + SAFE_MOD = 0xAA; +// CLOCK_CFG |= bOSC_EN_XT; // Enable external crystal +// CLOCK_CFG & = ~ bOSC_EN_INT; // Turn off the internal crystal #if FREQ_SYS == 32000000 - CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x07; // 32MHz + CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x07; // 32MHz #elif FREQ_SYS == 24000000 - CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x06; // 24MHz + CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x06; // 24MHz #elif FREQ_SYS == 16000000 - CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x05; // 16MHz + CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x05; // 16MHz #elif FREQ_SYS == 12000000 - CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x04; // 12MHz + CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x04; // 12MHz #elif FREQ_SYS == 6000000 - CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x03; // 6MHz + CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x03; // 6MHz #elif FREQ_SYS == 3000000 - CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x02; // 3MHz + CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x02; // 3MHz #elif FREQ_SYS == 750000 - CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x01; // 750KHz + CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x01; // 750KHz #elif FREQ_SYS == 187500 - CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x00; // 187.5MHz + CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x00; // 187.5MHz #else - #warning FREQ_SYS invalid or not set +#warning FREQ_SYS invalid or not set #endif - SAFE_MOD = 0x00; + SAFE_MOD = 0x00; } - - /******************************************************************************* * Function Name : mDelayus(UNIT16 n) * Description : us delay function @@ -60,55 +58,55 @@ void CfgFsys( ) * Output : None * Return : None *******************************************************************************/ -void mDelayuS( uint16_t n ) // Delay in uS +void mDelayuS(uint16_t n) // Delay in uS { -#ifdef FREQ_SYS -#if FREQ_SYS <= 6000000 - n >>= 2; +#ifdef FREQ_SYS + #if FREQ_SYS <= 6000000 + n >>= 2; + #endif + #if FREQ_SYS <= 3000000 + n >>= 2; + #endif + #if FREQ_SYS <= 750000 + n >>= 4; + #endif #endif -#if FREQ_SYS <= 3000000 - n >>= 2; + while (n) { // Total = 12~13 Fsys cycles, 1uS @Fsys=12MHz + ++SAFE_MOD; // 2 Fsys cycles, for higher Fsys, add operation here +#ifdef FREQ_SYS + #if FREQ_SYS >= 14000000 + ++SAFE_MOD; + #endif + #if FREQ_SYS >= 16000000 + ++SAFE_MOD; + #endif + #if FREQ_SYS >= 18000000 + ++SAFE_MOD; + #endif + #if FREQ_SYS >= 20000000 + ++SAFE_MOD; + #endif + #if FREQ_SYS >= 22000000 + ++SAFE_MOD; + #endif + #if FREQ_SYS >= 24000000 + ++SAFE_MOD; + #endif + #if FREQ_SYS >= 26000000 + ++SAFE_MOD; + #endif + #if FREQ_SYS >= 28000000 + ++SAFE_MOD; + #endif + #if FREQ_SYS >= 30000000 + ++SAFE_MOD; + #endif + #if FREQ_SYS >= 32000000 + ++SAFE_MOD; + #endif #endif -#if FREQ_SYS <= 750000 - n >>= 4; -#endif -#endif - while ( n ) { // total = 12~13 Fsys cycles, 1uS @Fsys=12MHz - ++ SAFE_MOD; // 2 Fsys cycles, for higher Fsys, add operation here -#ifdef FREQ_SYS -#if FREQ_SYS >= 14000000 - ++ SAFE_MOD; -#endif -#if FREQ_SYS >= 16000000 - ++ SAFE_MOD; -#endif -#if FREQ_SYS >= 18000000 - ++ SAFE_MOD; -#endif -#if FREQ_SYS >= 20000000 - ++ SAFE_MOD; -#endif -#if FREQ_SYS >= 22000000 - ++ SAFE_MOD; -#endif -#if FREQ_SYS >= 24000000 - ++ SAFE_MOD; -#endif -#if FREQ_SYS >= 26000000 - ++ SAFE_MOD; -#endif -#if FREQ_SYS >= 28000000 - ++ SAFE_MOD; -#endif -#if FREQ_SYS >= 30000000 - ++ SAFE_MOD; -#endif -#if FREQ_SYS >= 32000000 - ++ SAFE_MOD; -#endif -#endif - -- n; - } + --n; + } } /******************************************************************************* @@ -118,17 +116,17 @@ void mDelayuS( uint16_t n ) // Delay in uS * Output : None * Return : None *******************************************************************************/ -void mDelaymS( uint16_t n ) // Delay in mS +void mDelaymS(uint16_t n) // Delay in mS { - while ( n ) { -#ifdef DELAY_MS_HW - while ( ( TKEY_CTRL & bTKC_IF ) == 0 ); - while ( TKEY_CTRL & bTKC_IF ); + while (n) { +#ifdef DELAY_MS_HW + while ( ( TKEY_CTRL & bTKC_IF ) == 0 ); + while ( TKEY_CTRL & bTKC_IF ); #else - mDelayuS( 1000 ); + mDelayuS(1000); #endif - -- n; - } + --n; + } } #if SDCC < 370 @@ -162,42 +160,41 @@ int getchar() { #endif // Set pin p1.4 and p1.5 to GPIO output mode. -void gpio_init(){ - // p1.4 - P1_MOD_OC &= ~0x10; - P1_DIR_PU |= 0x10; - - // p1.5 - P1_MOD_OC &= ~0x20; - P1_DIR_PU |= 0x20; +void gpio_init() +{ + // p1.4 + P1_MOD_OC &= ~0x10; + P1_DIR_PU |= 0x10; + // p1.5 + P1_MOD_OC &= ~0x20; + P1_DIR_PU |= 0x20; } -void gpio_set(uint8_t pin) { - switch (pin) - { - case 0x10: // p1.4 - P1 |= 0x10; - break; - case 0x20: // p1.5 - P1 |= 0x20; - break; - default: // do nothing, unsupported pin. - break; - } +void gpio_set(uint8_t pin) +{ + switch (pin) { + case 0x10: // p1.4 + P1 |= 0x10; + break; + case 0x20: // p1.5 + P1 |= 0x20; + break; + default: // do nothing, unsupported pin. + break; + } } -void gpio_unset(uint8_t pin) { - switch (pin) - { - case 0x10: - P1 &= ~0x10; - break; - case 0x20: - P1 &= ~0x20; - break; - default: // do nothing, unsupported pin. - break; - } - +void gpio_unset(uint8_t pin) +{ + switch (pin) { + case 0x10: + P1 &= ~0x10; + break; + case 0x20: + P1 &= ~0x20; + break; + default: // do nothing, unsupported pin. + break; + } } diff --git a/hw/usb_interface/ch552_fw/include/debug.h b/hw/usb_interface/ch552_fw/include/debug.h index 3729bbd..c4166b5 100644 --- a/hw/usb_interface/ch552_fw/include/debug.h +++ b/hw/usb_interface/ch552_fw/include/debug.h @@ -1,133 +1,201 @@ - +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + /* Debug */ /* Provide printf subroutine and delay function */ - #pragma once #include -#ifndef UART0_BAUD -#define UART0_BAUD 9600 +#include "ch554.h" + +// UART1 baud rates +// Setting Actual % error +//Std 9600 9615.38 0.16% +// 14400 14492.75 0.64% +//Std 19200 19230.77 0.16% +//Std 38400 38461.54 0.16% +//Std 57600 58823.53 2.12% +// 100000 100000 0.00% +//Std 115200 111111.1 -3.55% +// 128000 142857.14 11.61% +//Std 230400 250000 8.51% +// 250000 250000 0% +// 256000 333333.33 30.21% +//Std 460800 500000 8.51% +//Std 500000 500000 0% +//Std 576000 +//Std 921600 +//Std 1000000 1000000 0.00% + +#ifndef UART0_BAUD +//#define UART0_BAUD 115200 +#define UART0_BAUD 1000000 #endif #ifndef UART1_BAUD -#define UART1_BAUD 9600 +#define UART1_BAUD 500000 +//#define UART1_BAUD 1000000 #endif -void CfgFsys( ); // CH554 clock selection and configuration - -void mDelayuS (uint16_t n); // Delay in units of uS -void mDelaymS (uint16_t n); // Delay in mS +void CfgFsys(); // CH554 clock selection and configuration +void mDelayuS(uint16_t n); // Delay in units of uS +void mDelaymS(uint16_t n); // Delay in mS /******************************************************************************* -* Function Name : CH554UART0Alter() -* Description : CH554 serial port 0 pin mapping, serial port mapping to P0.2 and P0.3 - -*******************************************************************************/ + * Function Name : CH554UART0Alter() + * Description : Set the alternate pin mappings for UART0 (RX on P1.2, TX on P1.3) + *******************************************************************************/ inline void CH554UART0Alter() { - PIN_FUNC |= bUART0_PIN_X; //串口映射到P1.2和P1.3 + PIN_FUNC |= bUART0_PIN_X; // RX on P1.2, TX on P1.3 } /******************************************************************************* -* Function Name : mInitSTDIO() -* Description : CH554 serial port 0 is initialized, T1 is used as the baud rate generator of UART0 by default, T2 can also be used -                   As a baud rate generator -*******************************************************************************/ -inline void mInitSTDIO( ) + * Function Name : mInitSTDIO() + * Description : CH554 UART0 is initialized + * T1 is used as the baud rate generator of UART0 by default + * T2 can also be used as baud rate generator + * RX on P3.0, TX on P3.1 + *******************************************************************************/ +inline void mInitSTDIO( ) { uint32_t x; uint8_t x2; - SM0 = 0; - SM1 = 1; - SM2 = 0; //Serial port 0 usage mode 1 - //Use Timer1 as a baud rate generator - RCLK = 0; //UART0 receive clock - TCLK = 0; //UART0 transmit clock - PCON |= SMOD; - x = 10 * FREQ_SYS / UART0_BAUD / 16; //If you change the main frequency, be careful not to overflow the value of x + SM0 = 0; // 8-bit data asynchronous communication + SM1 = 1; // Variable baud rate, which is generated by timer T1 or T2 + + // With SM0=0 and SM1=1 we are now in UART0 Mode 1 + + SM2 = 0; // In Mode 1, SM2=0 gives that the Receive interrupt flag bit is set when receiving data and the reception is valid + + // Use Timer1 as a baud rate generator + RCLK = 0; // UART0 receive clock + TCLK = 0; // UART0 transmit clock + + PCON |= SMOD; // Set Fast mode for UART0 baud rate communication + x = 10 * FREQ_SYS / UART0_BAUD / 16; // If you change the main frequency, be careful not to overflow the value of x x2 = x % 10; x /= 10; - if ( x2 >= 5 ) x ++; //rounding - - TMOD = TMOD & ~ bT1_GATE & ~ bT1_CT & ~ MASK_T1_MOD | bT1_M1; //0X20, Timer1 as 8-bit auto-reload timer - T2MOD = T2MOD | bTMR_CLK | bT1_CLK; //Timer1 clock selection - TH1 = 0-x; //12MHz crystal oscillator, buad / 12 is the actual need to set the baud rate - TR1 = 1; //Start timer 1 - TI = 1; - REN = 1; //Serial 0 receive enable + if (x2 >= 5) { + x++; // Rounding + } + TMOD = (TMOD & ~bT1_GATE & ~bT1_CT & ~MASK_T1_MOD) | bT1_M1; // Timer1 as 8-bit auto-reload timer + T2MOD = T2MOD | bTMR_CLK | bT1_CLK; // Timer1 clock selection + TH1 = 0-x; // 12MHz crystal oscillator, buad / 12 is the actual need to set the baud rate + TR1 = 1; // Start timer 1 + TI = 1; // Enable transmit interrupt + REN = 1; // UART0 receive enable + ES = 1; // UART0 interrupt enable } /******************************************************************************* -* Function Name : CH554UART0RcvByte() -* Description : CH554UART0 receives a byte -* Return : SBUF -*******************************************************************************/ -inline uint8_t CH554UART0RcvByte( ) + * Function Name : CH554UART0RcvByte() + * Description : CH554UART0 receives a byte + * Return : SBUF + *******************************************************************************/ +inline uint8_t CH554UART0RcvByte() { - while(RI == 0); // wait for uart rx interrupt flag + while (RI == 0) + ; // Wait for uart rx interrupt flag RI = 0; return SBUF; } /******************************************************************************* -* Function Name : CH554UART0SendByte(uint8_t SendDat) -* Description : CH554UART0 sends a byte -* Input : uint8_t SendDat; the data to be sent -*******************************************************************************/ + * Function Name : CH554UART0SendByte(uint8_t SendDat) + * Description : CH554UART0 sends a byte + * Input : uint8_t SendDat; the data to be sent + *******************************************************************************/ inline void CH554UART0SendByte(uint8_t SendDat) { - - SBUF = SendDat; - while(TI ==0); // wait for transmit to finish (TI == 1) - TI = 0; + SBUF = SendDat; + while (TI == 0) + ; // Wait for transmit to finish (TI == 1) + TI = 0; } /******************************************************************************* -* Function Name : CH554UART1Alter() -* Description : Set the alternate pin mappings for UART1 (TX on P3.2, RX on P3.4) -*******************************************************************************/ + * Function Name : CH554UART1Alter() + * Description : Set the alternate pin mappings for UART1 (RX on P3.4, TX on P3.2) + *******************************************************************************/ inline void CH554UART1Alter() { - PIN_FUNC |= bUART1_PIN_X; + PIN_FUNC |= bUART1_PIN_X; // RX on P3.4, TX on P3.2 } /******************************************************************************* -* Function Name : UART1Setup() -* Description : CH554串口1初始化 -*******************************************************************************/ -inline void UART1Setup() + * Function Name : UART1Setup() + * Description : CH554 serial port 1 initialization + * RX on P1.6, TX on P1.7 + * + *******************************************************************************/ +inline void UART1Setup() { - U1SM0 = 0; //UART1选择8位数据位 - U1SMOD = 1; //快速模式 - U1REN = 1; //使能接收 - // should correct for rounding in SBAUD1 calculation - SBAUD1 = 256 - FREQ_SYS/16/UART1_BAUD; + U1SM0 = 0; // UART1 selects 8-bit data bit + U1SMOD = 1; // Fast mode + U1REN = 1; // Enable receiving + // Should correct for rounding in SBAUD1 calculation + SBAUD1 = 256 - FREQ_SYS/16/UART1_BAUD; // Calculation for Fast mode + IE_UART1 = 1; // Enable UART1 interrupt } /******************************************************************************* -* Function Name : CH554UART1RcvByte() -* Description : CH554UART1接收一个字节 -* Return : SBUF -*******************************************************************************/ + * Function Name : UART1Clean() + * Description : Read out spurious data + *******************************************************************************/ +inline void UART1Clean() +{ + uint8_t tmp; + + while (U1RI) { + tmp = SBUF1; + U1RI = 0; + } +} + +/******************************************************************************* + * Function Name : CH554UART1RcvByte() + * Description : CH554UART1 receives a byte + * Return : SBUF + *******************************************************************************/ inline uint8_t CH554UART1RcvByte( ) { - while(U1RI == 0); //查询接收,中断方式可不用 + while (U1RI == 0) // Query reception, interrupt mode is not required + ; U1RI = 0; return SBUF1; } /******************************************************************************* -* Function Name : CH554UART1SendByte(uint8_t SendDat) -* Description : CH554UART1发送一个字节 -* Input : uint8_t SendDat;要发送的数据 -*******************************************************************************/ + * Function Name : CH554UART1SendByte(uint8_t SendDat) + * Description : CH554UART1 sends a byte + * Input : uint8_t SendDat; data to be sent + *******************************************************************************/ inline void CH554UART1SendByte(uint8_t SendDat) { - SBUF1 = SendDat; //查询发送,中断方式可不用下面2条语句,但发送前需TI=0 - while(U1TI ==0); + SBUF1 = SendDat; // Query sending, the interrupt mode does not need the following two statements, but TI=0 is required before sending + while (U1TI == 0) + ; + U1TI = 0; +} + +/******************************************************************************* + * Function Name : CH554UART1SendBuffer(uint8_t SendDat) + * Description : CH554UART1 sends a complete buffer + * Input : uint8_t *Buf; Data to be sent + * Input : uint32_t Len; Length of data + *******************************************************************************/ +inline void CH554UART1SendBuffer(uint8_t *Buf, uint32_t Len) +{ + uint32_t Count = 0; + while (Count < Len) { + SBUF1 = Buf[Count++]; + while (U1TI == 0) + ; U1TI = 0; + } } #if SDCC < 370 @@ -149,16 +217,15 @@ int getchar(void); *******************************************************************************/ inline void CH554WDTModeSelect(uint8_t mode) { - SAFE_MOD = 0x55; - SAFE_MOD = 0xaa; //Enter Safe Mode - if(mode){ - GLOBAL_CFG |= bWDOG_EN; //Start watchdog reset - } - - else GLOBAL_CFG &= ~bWDOG_EN; //Start watchdog only as a timer - SAFE_MOD = 0x00; //exit safe Mode - WDOG_COUNT = 0; //Watchdog assignment initial value - + SAFE_MOD = 0x55; + SAFE_MOD = 0xaa; // Enter Safe Mode + if (mode) { + GLOBAL_CFG |= bWDOG_EN; // Start watchdog reset + } else { + GLOBAL_CFG &= ~bWDOG_EN; //Start watchdog only as a timer + } + SAFE_MOD = 0x00; // Exit safe Mode + WDOG_COUNT = 0; // Watchdog assignment initial value } /******************************************************************************* @@ -173,12 +240,12 @@ inline void CH554WDTModeSelect(uint8_t mode) *******************************************************************************/ inline void CH554WDTFeed(uint8_t tim) { - - WDOG_COUNT = tim; // Watchdog counter assignment - + WDOG_COUNT = tim; // Watchdog counter assignment } // Set pin p1.4 and p1.5 to GPIO output mode. void gpio_init(); void gpio_set(uint8_t pin); void gpio_unset(uint8_t pin); + +#endif diff --git a/hw/usb_interface/ch552_fw/include/mem.h b/hw/usb_interface/ch552_fw/include/mem.h new file mode 100644 index 0000000..31e7b85 --- /dev/null +++ b/hw/usb_interface/ch552_fw/include/mem.h @@ -0,0 +1,32 @@ +#ifndef __MEM_PART_H__ +#define __MEM_PART_H__ + +// https://github.com/contiki-os/contiki/wiki/8051-Memory-Spaces + +#ifdef BUILD_CODE +#define IDATA __idata +#define XDATA __xdata +#define AT0000 __at(0x0000) // 0x000 0 +#define AT0008 __at(0x0008) // 0x008, 8 +#define AT0010 __at(0x0010) // 0x010, 16 +#define AT0040 __at(0x0040) // 0x040, 64 +#define AT0050 __at(0x0050) // 0x050, 80 +#define AT0080 __at(0x0080) // 0x080, 128 +#define AT0090 __at(0x0090) // 0x090, 144 +#define AT0100 __at(0x0100) // 0x100, 256 +#define FLASH __code +#else +#define IDATA +#define XDATA +#define AT0000 +#define AT0008 +#define AT0010 +#define AT0040 +#define AT0050 +#define AT0080 +#define AT0090 +#define AT0100 +#define FLASH +#endif + +#endif diff --git a/hw/usb_interface/ch552_fw/include/print.c b/hw/usb_interface/ch552_fw/include/print.c new file mode 100644 index 0000000..d65f6e4 --- /dev/null +++ b/hw/usb_interface/ch552_fw/include/print.c @@ -0,0 +1,188 @@ +#include + +#include "debug.h" +#include "print.h" + +void printStr(uint8_t *str) +{ +#ifdef DEBUG_PRINT + while (*str != 0) { + CH554UART0SendByte(*str); + ++str; + } +#else + (void)str; +#endif +} + +void printChar(uint8_t c) +{ +#ifdef DEBUG_PRINT + CH554UART0SendByte(c); +#else + (void)c; +#endif +} + +#ifdef USE_NUM_U8 +int8_t uint8_to_str(uint8_t *buf, uint8_t bufsize, uint8_t n) +{ + uint8_t *start; + +#ifdef USE_NEGATIVE_NUMS + if (n < 0) { // Handle negative numbers. + if (!bufsize) { + return -1; + } + *buf++ = '-'; + bufsize--; + } +#endif + + start = buf; // Remember the start of the string. This will come into play at the end. + + do { + // Handle the current digit. + uint8_t digit; + if (!bufsize) { + return -1; + } + digit = n % 10; +#ifdef USE_NEGATIVE_NUMS + if (digit < 0) { + digit *= -1; + } +#endif + *buf++ = digit + '0'; + bufsize--; + n /= 10; + } while (n); + + // Terminate the string. + if (!bufsize) { + return -1; + } + *buf = 0; + + // We wrote the string backwards, i.e. with least significant digits first. Now reverse the string. + --buf; + while (start < buf) { + uint8_t a = *start; + *start = *buf; + *buf = a; + ++start; + --buf; + } + + return 0; +} +#endif + +#ifdef USE_NUM_U32 +int8_t uint32_to_str(uint8_t *buf, uint8_t bufsize, uint32_t n) +{ + uint8_t *start; + +#ifdef USE_NEGATIVE_NUMS + if (n < 0) { // Handle negative numbers. + if (!bufsize) { + return -1; + } + *buf++ = '-'; + bufsize--; + } +#endif + + start = buf; // Remember the start of the string. This will come into play at the end. + + do { + // Handle the current digit. + uint8_t digit; + if (!bufsize) { + return -1; + } + digit = n % 10; +#ifdef USE_NEGATIVE_NUMS + if (digit < 0) { + digit *= -1; + } +#endif + *buf++ = digit + '0'; + bufsize--; + n /= 10; + } while (n); + + // Terminate the string. + if (!bufsize) { + return -1; + } + *buf = 0; + + // We wrote the string backwards, i.e. with least significant digits first. Now reverse the string. + --buf; + while (start < buf) { + uint8_t a = *start; + *start = *buf; + *buf = a; + ++start; + --buf; + } + + return 0; +} +#endif + +#ifdef USE_NUM_U8 +void printNumU8(uint8_t num) +{ +#ifdef DEBUG_PRINT + uint8_t num_str[4] = { 0 }; + int8_t ret; + ret = uint8_to_str(num_str, 4, num); + if (!ret) { + printStr(num_str); + } +#endif +} +#endif + +#ifdef USE_NUM_U32 +void printNumU32(uint32_t num) +{ +#ifdef DEBUG_PRINT + uint8_t num_str[11] = { 0 }; + int8_t ret; + ret = uint32_to_str(num_str, 10, num); + if (!ret) { + printStr(num_str); + } +#else + (void)num; +#endif +} +#endif + +void printNumHex(uint8_t num) +{ +#ifdef DEBUG_PRINT + // High nibble + uint8_t val = num >> 4; + if (val <= 9) { + val = val + '0'; + } else { + val = (val-10) + 'A'; + } + printChar(val); + + // Low nibble + val = num & 0x0F; + if (val <= 9) { + val = val + '0'; + } else { + val = (val-10) + 'A'; + } + printChar(val); +#else + (void)num; +#endif +} diff --git a/hw/usb_interface/ch552_fw/include/print.h b/hw/usb_interface/ch552_fw/include/print.h new file mode 100644 index 0000000..ccebd58 --- /dev/null +++ b/hw/usb_interface/ch552_fw/include/print.h @@ -0,0 +1,42 @@ +#ifndef __PRINT_H__ +#define __PRINT_H__ + +#include + +#define DEBUG_PRINT +//#define DEBUG_SETUP +//#define UART_OUT_DEBUG +//#define USE_NUM_U8 +#define USE_NUM_U32 +//#define USE_NEGATIVE_NUMS + +void printStr(uint8_t *str); +void printChar(uint8_t c); + +#ifdef DEBUG_SETUP +#define printStrSetup(x) printStr(x) +#define printNumHexSetup(x) printNumHex(x) +#else +#define printStrSetup(x) +#define printNumHexSetup(x) +#endif + +#ifdef USE_NUM_U8 +int8_t uint8_to_str(uint8_t *buf, uint8_t bufsize, uint8_t n); +#endif + +#ifdef USE_NUM_U32 +int8_t uint32_to_str(uint8_t *buf, uint8_t bufsize, uint32_t n); +#endif + +#ifdef USE_NUM_U8 +void printNumU8(uint8_t num); +#endif + +#ifdef USE_NUM_U32 +void printNumU32(uint32_t num); +#endif + +void printNumHex(uint8_t num); + +#endif diff --git a/hw/usb_interface/ch552_fw/include/usb_strings.h b/hw/usb_interface/ch552_fw/include/usb_strings.h index 8ac2f19..e811160 100644 --- a/hw/usb_interface/ch552_fw/include/usb_strings.h +++ b/hw/usb_interface/ch552_fw/include/usb_strings.h @@ -1,15 +1,31 @@ -#ifndef USB_STRINGS -#define USB_STRINGS -unsigned char __code Prod_Des[]={ // "MTA1-USB-V1" - 0x18, 0x03, 0x4d, 0x00, 0x54, 0x00, 0x41, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x55, 0x00, 0x53, 0x00, 0x42, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x31, 0x00 +#ifndef __USB_STRINGS_H__ +#define __USB_STRINGS_H__ + +#include "mem.h" + +unsigned char FLASH ProdDesc[]={ // "MTA1-USB-V1" + 0x18, 0x03, 0x4d, 0x00, 0x54, 0x00, 0x41, 0x00, + 0x31, 0x00, 0x2d, 0x00, 0x55, 0x00, 0x53, 0x00, + 0x42, 0x00, 0x2d, 0x00, 0x56, 0x00, 0x31, 0x00 }; -unsigned char __code Manuf_Des[]={ // "Tillitis" - 0x12, 0x03, 0x54, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, 0x73, 0x00 +unsigned char FLASH ManufDesc[]={ // "Tillitis" + 0x12, 0x03, 0x54, 0x00, 0x69, 0x00, 0x6c, 0x00, + 0x6c, 0x00, 0x69, 0x00, 0x74, 0x00, 0x69, 0x00, + 0x73, 0x00 }; -unsigned char __code SerDes[]={ // "68de5d27-e223-4874-bc76-a54d6e84068f" - 0x4a, 0x03, 0x36, 0x00, 0x38, 0x00, 0x64, 0x00, 0x65, 0x00, 0x35, 0x00, 0x64, 0x00, 0x32, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x65, 0x00, 0x32, 0x00, 0x32, 0x00, 0x33, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x38, 0x00, 0x37, 0x00, 0x34, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x63, 0x00, 0x37, 0x00, 0x36, 0x00, 0x2d, 0x00, 0x61, 0x00, 0x35, 0x00, 0x34, 0x00, 0x64, 0x00, 0x36, 0x00, 0x65, 0x00, 0x38, 0x00, 0x34, 0x00, 0x30, 0x00, 0x36, 0x00, 0x38, 0x00, 0x66, 0x00 +unsigned char FLASH SerialDesc[]={ // "68de5d27-e223-4874-bc76-a54d6e84068f" + 0x4a, 0x03, 0x36, 0x00, 0x38, 0x00, 0x64, 0x00, + 0x65, 0x00, 0x35, 0x00, 0x64, 0x00, 0x32, 0x00, + 0x37, 0x00, 0x2d, 0x00, 0x65, 0x00, 0x32, 0x00, + 0x32, 0x00, 0x33, 0x00, 0x2d, 0x00, 0x34, 0x00, + 0x38, 0x00, 0x37, 0x00, 0x34, 0x00, 0x2d, 0x00, + 0x62, 0x00, 0x63, 0x00, 0x37, 0x00, 0x36, 0x00, + 0x2d, 0x00, 0x61, 0x00, 0x35, 0x00, 0x34, 0x00, + 0x64, 0x00, 0x36, 0x00, 0x65, 0x00, 0x38, 0x00, + 0x34, 0x00, 0x30, 0x00, 0x36, 0x00, 0x38, 0x00, + 0x66, 0x00 }; #endif diff --git a/hw/usb_interface/ch552_fw/main.c b/hw/usb_interface/ch552_fw/main.c index 8fbfef6..f12925f 100644 --- a/hw/usb_interface/ch552_fw/main.c +++ b/hw/usb_interface/ch552_fw/main.c @@ -1,659 +1,1180 @@ -/********************************** (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 -*******************************************************************************/ +/********************************** (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 #include #include #include #include -#include - -__xdata __at (0x0000) uint8_t Ep0Buffer[DEFAULT_ENDP0_SIZE]; // Endpoint 0 OUT & IN buffer, must be an even address -__xdata __at (0x0040) uint8_t Ep1Buffer[DEFAULT_ENDP1_SIZE]; //Endpoint 1 upload buffer -__xdata __at (0x0080) uint8_t Ep2Buffer[2*MAX_PACKET_SIZE]; //Endpoint 2 IN & OUT buffer, must be an even address - -uint16_t SetupLen; -uint8_t SetupReq,Count,UsbConfig; -const uint8_t * pDescr; //USB configuration flag -USB_SETUP_REQ SetupReqBuf; //Temporary Setup package -#define UsbSetupBuf ((PUSB_SETUP_REQ)Ep0Buffer) - -#define SET_LINE_CODING 0X20 // Configures DTE rate, stop-bits, parity, and number-of-character -#define GET_LINE_CODING 0X21 // This request allows the host to find out the currently configured line coding. -#define SET_CONTROL_LINE_STATE 0X22 // This request generates RS-232/V.24 style control signals. - - -/*设备描述符*/ -__code uint8_t DevDesc[] = {0x12,0x01,0x10,0x01,0x02,0x00,0x00,DEFAULT_ENDP0_SIZE, -// 0x86,0x1a, // VID -// 0x22,0x57, // PID - 0x07,0x12, // VID - 0x87,0x88, // PID - 0x00,0x01,0x01,0x02, - 0x03,0x01 - }; -__code uint8_t CfgDesc[] ={ - 0x09,0x02,0x43,0x00,0x02,0x01,0x00,0xa0,0x32, //Configuration descriptor (two interfaces) -// The following is the interface 0 (CDC interface) descriptor - 0x09,0x04,0x00,0x00,0x01,0x02,0x02,0x01,0x00, // CDC interface descriptor (one endpoint) - //The following is the function descriptor - 0x05,0x24,0x00,0x10,0x01, //Function descriptor (header) - 0x05,0x24,0x01,0x00,0x00, //Management descriptor (no data interface) 03 01 - 0x04,0x24,0x02,0x02, //stand by,Set_Line_Coding、Set_Control_Line_State、Get_Line_Coding、Serial_State - 0x05,0x24,0x06,0x00,0x01, //CDC interface numbered 0; data interface numbered 1 - 0x07,0x05,0x81,0x03,0x08,0x00,0xFF, //Interrupt upload endpoint descriptor - //The following is the interface 1 (data interface) descriptor - 0x09,0x04,0x01,0x00,0x02,0x0a,0x00,0x00,0x00, //Data interface descriptor - 0x07,0x05,0x02,0x02,0x40,0x00,0x00, //Endpoint descriptor - 0x07,0x05,0x82,0x02,0x40,0x00,0x00, //Endpoint descriptor -}; -/*字符串描述符*/ -unsigned char __code LangDes[]={0x04,0x03,0x09,0x04}; //Language descriptor +#include "debug.h" +#include "mem.h" +#include "print.h" #include "usb_strings.h" -//unsigned char __code SerDes[]={ //Serial number string descriptor -// 0x14,0x03, -// 0x32,0x00,0x30,0x00,0x31,0x00,0x37,0x00,0x2D,0x00, -// 0x32,0x00,0x2D,0x00, -// 0x32,0x00,0x35,0x00 -// }; -//unsigned char __code Prod_Des[]={ //Product string descriptor -// 0x14,0x03, -// 0x43,0x00,0x48,0x00,0x35,0x00,0x35,0x00,0x34,0x00,0x5F,0x00, -// 0x43,0x00,0x44,0x00,0x43,0x00, -// }; -//unsigned char __code Manuf_Des[]={ -// 0x0A,0x03, -// 0x5F,0x6c,0xCF,0x82,0x81,0x6c,0x52,0x60, -//}; +XDATA AT0000 uint8_t Ep0Buffer[DEFAULT_EP0_SIZE] = { 0 }; // Endpoint 0, Default endpoint, OUT & IN buffer, must be an even address +XDATA AT0008 uint8_t Ep1Buffer[DEFAULT_EP1_SIZE] = { 0 }; // Endpoint 1, CDC Ctrl, IN[8] buffer +XDATA AT0010 uint8_t Ep2Buffer[2*MAX_PACKET_SIZE] = { 0 }; // Endpoint 2, CDC Data, buffer OUT[64]+IN[64], must be an even address +XDATA AT0090 uint8_t Ep3Buffer[2*MAX_PACKET_SIZE] = { 0 }; // Endpoint 3, HID, buffer OUT[64]+IN[64], must be an even address -//cdc参数 -__xdata uint8_t LineCoding[7]={0x00,0xe1,0x00,0x00,0x00,0x00,0x08}; //The initial baud rate is 57600, 1 stop bit, no parity, 8 data bits. +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 UART_REV_LEN 64 //Serial receive buffer size -__idata uint8_t Receive_Uart_Buf[UART_REV_LEN]; //Serial receive buffer -volatile __idata uint8_t Uart_Input_Point = 0; //Circular buffer write pointer, bus reset needs to be initialized to 0 -volatile __idata uint8_t Uart_Output_Point = 0; //Take pointer out of circular buffer, bus reset needs to be initialized to 0 -volatile __idata uint8_t UartByteCount = 0; //Number of bytes remaining in the current buffer +#define UsbSetupBuf ((PUSB_SETUP_REQ)Ep0Buffer) +#define CDC_CTRL_EPIN_ADDR 0x81 // CDC Ctrl Endpoint IN Address +#define CDC_CTRL_EPIN_SIZE DEFAULT_EP1_SIZE // CDC Ctrl Endpoint IN Size -volatile __idata uint8_t USBByteCount = 0; //Represents the data received by the USB endpoint -volatile __idata uint8_t USBBufOutPoint = 0; //Fetch data pointer +#define CDC_DATA_EPOUT_ADDR 0x02 // CDC Data Endpoint OUT Address +#define CDC_DATA_EPOUT_SIZE MAX_PACKET_SIZE // CDC Data Endpoint OUT Size -volatile __idata uint8_t UpPoint2_Busy = 0; //Whether the upload endpoint is busy +#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 CDC_CTRL_FS_BINTERVAL 0xFF // 255 ms polling interval at Full Speed +#define CDC_DATA_FS_BINTERVAL 1 /* was: 0 */ // 1 ms polling interval at Full Speed +#define HID_FS_BINTERVAL 1 // 1 ms polling interval at Full Speed + +#define HID_REPORT_DESC_SIZE 47 // HID Report Descriptor size + +#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 */ + 0x10, /* bcdUSB (low byte), USB Specification Release Number in Binary-Coded Decimal (1.10 is 110h) */ + 0x01, /* bcdUSB (high byte) USB Specification Release Number in Binary-Coded Decimal (1.10 is 110h) */ + 0x00, /* bDeviceClass */ // Each configuration has its own class + 0x00, /* bDeviceSubClass */ // Each configuration has its own sub-class + 0x00, /* bDeviceProtocol */ // Each configuration has its own protocol + DEFAULT_EP0_SIZE, /* bMaxPacketSize */ + 0x07, /* idVendor */ // VID LOBYTE + 0x12, /* idVendor */ // VID HIBYTE + 0x87, /* idProduct */ // PID LOBYTE + 0x88, /* idProduct */ // PID HIBYTE + 0x00, /* bcdDevice (low byte, i.e. YY) rel. XX.YY */ + 0x01, /* bcdDevice (high byte, i.e. XX) rel. XX.YY */ // Orig: 0x02 + 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 */ + 99U, /* wTotalLength (low byte): Bytes returned */ + 0x00, /* wTotalLength (high byte): Bytes returned */ + 0x03, /* bNumInterfaces: 3 interfaces (1 CDC Ctrl, 1 CDC Data, 1 HID) */ + 0x01, /* bConfigurationValue: Configuration value */ + 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ + 0xA0, /*Mouse:0xE0,whatis:0xC0?*/ /* bmAttributes: Bus powered and Support Remote Wake-up */ + 0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */ + /******************** Interface 0, CDC Ctrl Descriptor (one endpoint) ********************/ + /* 9 */ + 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 */ + 0x00, /* iInterface: Index of string descriptor */ + /******************** Header Functional Descriptor ********************/ + /* 18 */ + 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) ********************/ + /* 23 */ + 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 ********************/ + /* 28 */ + 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 ********************/ + /* 32 */ + 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) ********************/ + /* 37 */ + 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) ********************/ + /* 44 */ + 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 */ + 0x00, /* iInterface: Index of string descriptor */ + /******************** CDC Data Endpoint descriptor (OUT) ********************/ + /* 53 */ + 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) ********************/ + /* 60 */ + 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) ********************/ + /* 67 */ + 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 */ + 0x00, /* iInterface: Index of string descriptor */ + /******************** HID Device Descriptor ********************/ + /* 76 */ + 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) ********************/ + /* 85 */ + 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) ********************/ + /* 92 */ + 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 */ + /* 99 */ +}; + +// 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) */ + + 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); */ + + 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); */ + + 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) (???) */ + + 0xC0 /* End Collection */ +}; + +// String Descriptor (Language descriptor ) +FLASH uint8_t LangDesc[] = { + 0x04, 0x03, 0x09, 0x04 +}; + +// 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 HID_FRAME_SIZE 64 +#define MAX_CDC_FRAME_SIZE 32 + +#define UART_TX_BUF_SIZE 64 // Serial transmit buffer +#define UART_RX_BUF_SIZE ((HID_FRAME_SIZE*2)+4) // Serial receive buffer + +/** Communication UART */ +XDATA uint8_t UartTxBuf[UART_TX_BUF_SIZE] = { 0 }; // Serial transmit buffer +volatile IDATA uint8_t byte_len; + +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 Endpoint2UploadBusy = 0; // Whether the upload endpoint 2 (CDC) is busy +volatile IDATA uint8_t Endpoint3UploadBusy = 0; // Whether the upload endpoint 3 (HID) is busy + +/** CDC and HID variables */ +volatile IDATA uint32_t LoopCounter = 0; +volatile IDATA uint32_t LastReceiveCounter = 0; + +XDATA uint8_t CdcRxBuf[MAX_CDC_FRAME_SIZE] = { 0 }; +IDATA uint8_t CdcRxBufLength = 0; +IDATA uint8_t CdcDataAvailable = 0; +IDATA uint32_t CdcLoopCount = 0; + +XDATA uint8_t HidRxBuf[HID_FRAME_SIZE] = { 0 }; +IDATA uint8_t HidRxBufLength; +IDATA uint8_t HidDataAvailable; + +/** Frame data */ +#define FRAME_TIMEOUT 10000 // Timeout in number of main loop iterations + +#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 FrameStarted = 0; +volatile IDATA uint8_t Halted = 0; /******************************************************************************* -* Function Name : USBDeviceCfg() -* Description : USB device mode configuration -* Input : None -* Output : None -* Return : None -*******************************************************************************/ + * 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 - // USB_CTRL |= bUC_LOW_SPEED; - // UDEV_CTRL |= bUD_LOW_SPEED; //Select low speed 1.5M mode + 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 - UDEV_CTRL = bUD_PD_DIS; // Disable DP / DM pull-down resistor - UDEV_CTRL |= bUD_PORT_EN; //Enable physical port + 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 -*******************************************************************************/ + * 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 |= 0x1F; //Clear interrupt flag - IE_USB = 1; //Enable USB interrupt - EA = 1; //Allow microcontroller interrupt + 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 -*******************************************************************************/ + * 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? - UEP1_DMA = (uint16_t) Ep1Buffer; //Endpoint 1 sends data transfer address - UEP2_DMA = (uint16_t) Ep2Buffer; //Endpoint 2 IN data transfer address - UEP2_3_MOD = 0xCC; //Endpoint 2/3 single buffer transceiver enable - 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 + UEP0_DMA = (uint16_t) Ep0Buffer; // Endpoint 0 data transfer address + 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 = bUEP1_TX_EN; // Endpoint 1, transmit enable; Endpoint 0 single 8-byte send and receive buffer + UEP2_3_MOD = bUEP2_TX_EN | bUEP2_RX_EN | bUEP3_TX_EN | bUEP3_RX_EN; // Endpoint 2/3, single buffer, transmit+receive enable + + UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; // 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 - UEP1_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK; //Endpoint 1 automatically flips the synchronization flag, IN transaction returns NAK - UEP0_DMA = (uint16_t) Ep0Buffer; //Endpoint 0 data transfer address - UEP4_1_MOD = 0X40; //Endpoint 1 upload buffer; endpoint 0 single 64-byte send and receive buffer - UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; //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 -*******************************************************************************/ + * 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_buad = 0; - *((uint8_t *)&uart1_buad) = cfg_uart[0]; - *((uint8_t *)&uart1_buad+1) = cfg_uart[1]; - *((uint8_t *)&uart1_buad+2) = cfg_uart[2]; - *((uint8_t *)&uart1_buad+3) = cfg_uart[3]; - SBAUD1 = 256 - FREQ_SYS/16/uart1_buad; // SBAUD1 = 256 - Fsys / 16 / baud rate - IE_UART1 = 1; + *((uint8_t*) &uart1_buad) = cfg_uart[0]; + *((uint8_t*) &uart1_buad + 1) = cfg_uart[1]; + *((uint8_t*) &uart1_buad + 2) = cfg_uart[2]; + *((uint8_t*) &uart1_buad + 3) = cfg_uart[3]; + SBAUD1 = 256 - FREQ_SYS / 16 / uart1_buad; // 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 { + printStrSetup("Error: USB_DESC_TYPE_STRING\n"); + } + break; + case USB_DESC_TYPE_HID: + pDescr = HID_CfgDesc; + len = sizeof(HID_CfgDesc); + printStrSetup("HID_CfgDesc\n"); + break; + case USB_DESC_TYPE_REPORT: + pDescr = HID_ReportDesc; + len = sizeof(HID_ReportDesc); + printStrSetup("HID_ReportDesc\n"); + 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 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 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 -*******************************************************************************/ -void DeviceInterrupt(void) __interrupt (INT_NO_USB) //USB interrupt service routine, using register set 1 + * 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) //USB transfer complete flag - { - switch (USB_INT_ST & (MASK_UIS_TOKEN | MASK_UIS_ENDP)) - { - case UIS_TOKEN_IN | 1: //endpoint 1# Endpoint interrupts upload - UEP1_T_LEN = 0; - UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_NAK; //Default answer NAK + + 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 | 2: //endpoint 2# Endpoint bulk upload - { - UEP2_T_LEN = 0; //The pre-used sending length must be cleared - UEP2_CTRL = UEP2_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_NAK; //Default answer NAK - UpPoint2_Busy = 0; //clear busy flag - } - break; - case UIS_TOKEN_OUT | 2: //endpoint 3# Endpoint batch download - if ( U_TOG_OK ) // Out-of-sync packets will be dropped - { - USBByteCount = USB_RX_LEN; // Grads length of recieved 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_SETUP | 0: //SETUP routine - len = USB_RX_LEN; - 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; - if ( ( UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD )// non-standard request - { - switch( SetupReq ) - { - case GET_LINE_CODING: //0x21 currently configured - pDescr = LineCoding; - len = sizeof(LineCoding); - len = SetupLen >= DEFAULT_ENDP0_SIZE ? DEFAULT_ENDP0_SIZE : SetupLen; // The length of this transmission - memcpy(Ep0Buffer,pDescr,len); - SetupLen -= len; - pDescr += len; - break; - case SET_CONTROL_LINE_STATE: //0x22 generates RS-232/V.24 style control signals - break; - case SET_LINE_CODING: //0x20 Configure - break; - default: - len = 0xFF; /*Command not supported*/ - break; - } - } - else //Standard request - { - switch(SetupReq) //Request code - { - case USB_GET_DESCRIPTOR: - switch(UsbSetupBuf->wValueH) - { - case 1: // device descriptor - pDescr = DevDesc; //Send the device descriptor to the buffer to be sent - len = sizeof(DevDesc); - break; - case 2: //configuration descriptor - pDescr = CfgDesc; //Send the device descriptor to the buffer to be sent - len = sizeof(CfgDesc); - break; - case 3: - if(UsbSetupBuf->wValueL == 0) - { - pDescr = LangDes; - len = sizeof(LangDes); - } - else if(UsbSetupBuf->wValueL == 1) - { - pDescr = Manuf_Des; - len = sizeof(Manuf_Des); - } - else if(UsbSetupBuf->wValueL == 2) - { - pDescr = Prod_Des; - len = sizeof(Prod_Des); - } - else - { - pDescr = SerDes; - len = sizeof(SerDes); - } - break; - default: - len = 0xff; //Unsupported command or error - break; - } - if ( SetupLen > len ) - { - SetupLen = len; //Limit total length - } - len = SetupLen >= DEFAULT_ENDP0_SIZE ? DEFAULT_ENDP0_SIZE : SetupLen; //This transmission length - memcpy(Ep0Buffer,pDescr,len); //Load upload data - SetupLen -= len; - pDescr += len; - break; - case USB_SET_ADDRESS: - SetupLen = UsbSetupBuf->wValueL; //Temporary storage of USB device address - break; - case USB_GET_CONFIGURATION: - Ep0Buffer[0] = UsbConfig; - if ( SetupLen >= 1 ) - { - len = 1; - } - break; - case USB_SET_CONFIGURATION: - UsbConfig = UsbSetupBuf->wValueL; - break; - case USB_GET_INTERFACE: - break; - case USB_CLEAR_FEATURE: //Clear Feature - if( ( UsbSetupBuf->bRequestType & 0x1F ) == 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 */ - } - } - else - { - len = 0xFF; /* operation failed */ - } - } - else if ( ( UsbSetupBuf->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )// endpoint - { - switch( UsbSetupBuf->wIndexL ) - { - case 0x83: - UEP3_CTRL = UEP3_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK; - break; - case 0x03: - UEP3_CTRL = UEP3_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK; - break; - case 0x82: - UEP2_CTRL = UEP2_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK; - break; - case 0x02: - UEP2_CTRL = UEP2_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK; - break; - case 0x81: - UEP1_CTRL = UEP1_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK; - break; - case 0x01: - UEP1_CTRL = UEP1_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK; - break; - default: - len = 0xFF; // Unsupported endpoint - break; - } - } - else - { - len = 0xFF; // It's not that the endpoint doesn't support it - } - break; - case USB_SET_FEATURE: /* Set Feature */ - if( ( UsbSetupBuf->bRequestType & 0x1F ) == USB_REQ_RECIP_DEVICE ) /* Set up the device */ - { - if( ( ( ( uint16_t )UsbSetupBuf->wValueH << 8 ) | UsbSetupBuf->wValueL ) == 0x01 ) - { - if( CfgDesc[ 7 ] & 0x20 ) - { - /* hibernate */ -#ifdef DE_PRINTF - printf( "suspend\n" ); //sleep state -#endif - while ( XBUS_AUX & bUART0_TX ) - { - ; //等待发送完成 - } - 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->bRequestType & 0x1F ) == USB_REQ_RECIP_ENDP ) /* Set endpoint */ - { - if( ( ( ( uint16_t )UsbSetupBuf->wValueH << 8 ) | UsbSetupBuf->wValueL ) == 0x00 ) - { - switch( ( ( uint16_t )UsbSetupBuf->wIndexH << 8 ) | UsbSetupBuf->wIndexL ) - { - case 0x83: - UEP3_CTRL = UEP3_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;/* Set endpoint 3 IN STALL */ - break; - case 0x03: - UEP3_CTRL = UEP3_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;/* Set endpoint 3 OUT Stall */ - break; - case 0x82: - UEP2_CTRL = UEP2_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;/* Set endpoint 2 IN STALL */ - break; - case 0x02: - UEP2_CTRL = UEP2_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;/* Set endpoint 2 OUT Stall */ - break; - case 0x81: - UEP1_CTRL = UEP1_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;/* Set endpoint 1 IN STALL */ - break; - case 0x01: - UEP1_CTRL = UEP1_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;/* Set endpoint 1 OUT Stall */ - default: - len = 0xFF; /* operation failed */ - break; - } - } - else - { - len = 0xFF; /* operation failed */ - } - } - else - { - len = 0xFF; /* operation failed */ - } - break; - case USB_GET_STATUS: - Ep0Buffer[0] = 0x00; - Ep0Buffer[1] = 0x00; - if ( SetupLen >= 2 ) - { - len = 2; - } - else - { - len = SetupLen; - } - break; - default: - len = 0xff; //operation failed - break; - } - } - } - 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_ENDP0_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 - } - break; - case UIS_TOKEN_IN | 0: //endpoint0 IN - switch(SetupReq) - { + + case UIS_TOKEN_IN | 0: // Endpoint 0 IN (TX) + switch (SetupReq) { case USB_GET_DESCRIPTOR: - len = SetupLen >= DEFAULT_ENDP0_SIZE ? DEFAULT_ENDP0_SIZE : SetupLen; //The length of this transmission - memcpy( Ep0Buffer, pDescr, len ); //Load upload data + 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 + UEP0_CTRL ^= bUEP_T_TOG; // Sync flag flip break; case USB_SET_ADDRESS: - USB_DEV_AD = USB_DEV_AD & bUDA_GP_BIT | SetupLen; + 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_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_OUT | 0: // endpoint0 OUT - if(SetupReq ==SET_LINE_CODING) // Set serial port properties - { - if( U_TOG_OK ) - { - memcpy(LineCoding,UsbSetupBuf,USB_RX_LEN); - Config_Uart1(LineCoding); + + 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_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 + UEP0_CTRL |= UEP_R_RES_ACK | UEP_T_RES_ACK; // Prepare to upload 0 packages } - } - else - { + break; + default: UEP0_T_LEN = 0; - UEP0_CTRL |= UEP_R_RES_ACK | UEP_T_RES_NAK; // Status phase, responds to IN with NAK + 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; default: break; } - UIF_TRANSFER = 0; //Writing 0 clears the interrupt - } - if(UIF_BUS_RST) //Device mode USB bus reset interrupt - { -#ifdef DE_PRINTF - printf( "reset\n" ); //sleep state -#endif - UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; + + 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; USB_DEV_AD = 0x00; UIF_SUSPEND = 0; - UIF_TRANSFER = 0; - UIF_BUS_RST = 0; //clear interrupt flag - Uart_Input_Point = 0; //Circular buffer input pointer - Uart_Output_Point = 0; //Circular buffer read pointer - UartByteCount = 0; //The number of bytes remaining in the current buffer to be fetched - USBByteCount = 0; //USB endpoint received length - UsbConfig = 0; //Clear configuration values - UpPoint2_Busy = 0; - } - if (UIF_SUSPEND) //USB bus suspend/wake completed - { + 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 - { -#ifdef DE_PRINTF - printf( "suspend\n" ); //sleep state -#endif - while ( XBUS_AUX & bUART0_TX ) - { - ; //Wait for sending to complete + + 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 + 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 interruption, impossible situation - USB_INT_FG = 0xFF; //clear interrupt flag + } + } else { // Unexpected IRQ, should not happen + printStr("Unexpected IRQ\n"); + USB_INT_FG = 0xFF; // Clear interrupt flag } } + /******************************************************************************* -* Function Name : Uart1_ISR() -* Description : Serial port receiving interrupt function to realize circular buffer receiving -*******************************************************************************/ -void Uart1_ISR(void) __interrupt (INT_NO_UART1) + * 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 { - if(U1RI) //data received - { - Receive_Uart_Buf[Uart_Input_Point++] = SBUF1; - if(Uart_Input_Point>=UART_REV_LEN) { - Uart_Input_Point = 0; //Write pointer + // 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; + LastReceiveCounter = LoopCounter; // Update the counter when a byte is received + if (UartRxBufInputPointer == UartRxBufOutputPointer) { + UartRxBufOverflow = 1; + } + if (UartRxBufInputPointer >= UART_RX_BUF_SIZE) { + UartRxBufInputPointer = 0; // Reset write pointer } U1RI = 0; } - } -uint8_t uart_byte_count() { - uint8_t in = Uart_Input_Point; - uint8_t out = Uart_Output_Point; +uint8_t uart_byte_count() +{ + uint8_t in = UartRxBufInputPointer; + uint8_t out = UartRxBufOutputPointer; if (in < out) { - in = in + UART_REV_LEN; + in = in + UART_RX_BUF_SIZE; } - return in - out; } -//main function -main() -{ - uint8_t length; - uint8_t Uart_Timeout = 0; - uint8_t USB_output_buffer[64] = {0}; - uint8_t USB_output_buffer_remain = 0; - CfgFsys( ); // CH559 clock selection configuration - mDelaymS(5); // Modify the main frequency and wait for the internal crystal to stabilize, which must be added - mInitSTDIO( ); // Serial port 0, can be used for debugging - UART1Setup( ); // For CDC +// 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; +} + +void main() +{ + CfgFsys(); // CH559 clock selection configuration + mDelaymS(5); // Modify the main frequency and wait for the internal crystal to stabilize, which must be added + mInitSTDIO(); // Serial port 0, can be used for debugging + UART1Setup(); // For communication with FPGA + UART1Clean(); // Clean register from spurious data + + printStr("\n\nStartup...\n"); -#ifdef DE_PRINTF - printf("start ...\n"); -#endif USBDeviceCfg(); - USBDeviceEndPointCfg(); // Endpoint configuration - USBDeviceIntCfg(); //Interrupt initialization - UEP0_T_LEN = 0; - UEP1_T_LEN = 0; //Pre-use send length must be cleared - UEP2_T_LEN = 0; //Pre-use send length must be cleared + 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) // Enable GPIO debugging on p1.4 and p1.5 // gpio_init(); // gpio_unset(0x10); // gpio_unset(0x20); - while(1) - { - if(UsbConfig) - { - if(USBByteCount) // USB receiving endpoint has data - { - memcpy(USB_output_buffer, Ep2Buffer, USBByteCount); - USB_output_buffer_remain = USBByteCount; - USBBufOutPoint = 0; - USBByteCount = 0; + while (1) { + if (UsbConfig) { + + // Check if Endpoint 2 (CDC) has received data + if (UsbEp2ByteCount) { + byte_len = UsbEp2ByteCount; + memcpy(UartTxBuf, Ep2Buffer, byte_len); + + UsbEp2ByteCount = 0; + CH554UART1SendByte(MODE_CDC); // Send CDC mode header + CH554UART1SendByte(byte_len); // Send length + CH554UART1SendBuffer(UartTxBuf, byte_len); + UEP2_CTRL = (UEP2_CTRL & ~MASK_UEP_R_RES) | UEP_R_RES_ACK; // Enable Endpoint 2 to ACK again } - if(USB_output_buffer_remain) - { - CH554UART1SendByte(USB_output_buffer[USBBufOutPoint++]); - USB_output_buffer_remain--; + // Check if Endpoint 3 (HID) has received data + if (UsbEp3ByteCount) { + byte_len = UsbEp3ByteCount; + memcpy(UartTxBuf, Ep3Buffer, byte_len); - if(USB_output_buffer_remain==0) { - UEP2_CTRL = UEP2_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_ACK; - } + UsbEp3ByteCount = 0; + CH554UART1SendByte(MODE_HID); // Send HID mode header + CH554UART1SendByte(byte_len); // Send length (always 64 bytes) + CH554UART1SendBuffer(UartTxBuf, byte_len); + UEP3_CTRL = (UEP3_CTRL & ~MASK_UEP_R_RES) | UEP_R_RES_ACK; // Enable Endpoint 3 to ACK again } - UartByteCount = uart_byte_count(); - if(UartByteCount) { - Uart_Timeout++; - } + UartRxBufByteCount = uart_byte_count(); // Check amount of data in buffer - if(!UpPoint2_Busy) // The endpoint is not busy (the first packet of data after idle, only used to trigger upload) - { - length = UartByteCount; - if(length>0) - { - if(length>39 || Uart_Timeout>100) - { - - Uart_Timeout = 0; - // if we reach a wrap-around, just transmit from index to end of buffer. - // The rest goes in next packet, i.e., not handling wrap-around. - if(Uart_Output_Point+length>UART_REV_LEN) { - length = UART_REV_LEN-Uart_Output_Point; + if ((UartRxBufByteCount >= 2) && !FrameStarted) { // If we have data and the header in not yet validated + FrameMode = UartRxBuf[UartRxBufOutputPointer]; // Extract frame mode + if ((FrameMode == MODE_CDC) || + (FrameMode == MODE_HID)) { + FrameLength = UartRxBuf[UartRxBufOutputPointer + 1]; // Extract frame length + FrameStarted = 1; + } else { // Invalid mode + if (!Halted) { + printStr("Invalid header: 0x"); + printNumHex(FrameMode); + printStr(", len = "); + printNumU32(UartRxBuf[UartRxBufOutputPointer + 1]); + printStr("\n"); + uint16_t i; + uint8_t print_char_count_out = 0; + for (i=0; i= 16) { + printStr("\n"); + print_char_count_out = 0; + } } - // write upload endpoint - memcpy(Ep2Buffer+MAX_PACKET_SIZE,&Receive_Uart_Buf[Uart_Output_Point],length); - - Uart_Output_Point+=length; - - if (Uart_Output_Point>=UART_REV_LEN) { - Uart_Output_Point = 0; + if (print_char_count_out != 0) { + printStr("\n"); } - - UEP2_T_LEN = length; // Pre-use send length must be cleared - UEP2_CTRL = UEP2_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_ACK; // Answer ACK - UpPoint2_Busy = 1; - - // Should according to the USB-spec check if - // length == 64, if so we should send a - // zero-length USB packet. This is very - // unlikley to happen. + printStr("Halting!\n"); + Halted = 1; } } } - // Should have a timeout if the transfer for some reason - // fails to reset UpPoint2_Busy. But does not seem to - // happen. - } - } + + if (FrameStarted && (LoopCounter - LastReceiveCounter > FRAME_TIMEOUT)) { + // Timeout, reset frame reception + FrameMode = 0; + FrameLength = 0; + FrameStarted = 0; + printStr("Frame timeout, reset\n"); + if (FrameMode == MODE_CDC) { + CdcRxBufLength = 0; + CdcLoopCount = 0; + } + } + + if (FrameStarted) { + // Check if a complete frame has been received, include one mode byte and and one length byte + if (UartRxBufByteCount >= (FrameLength + 2)) { + UartRxBufOutputPointer+=2; // Start at valid data so skip the mode and length byte + if (FrameMode == MODE_CDC) { + circular_copy(CdcRxBuf + CdcRxBufLength, + UartRxBuf, + UART_RX_BUF_SIZE, + UartRxBufOutputPointer, + FrameLength); + CdcRxBufLength += FrameLength; + CdcDataAvailable = 1; + } else if (FrameMode == MODE_HID) { + circular_copy(HidRxBuf, + UartRxBuf, + UART_RX_BUF_SIZE, + UartRxBufOutputPointer, + FrameLength); + HidRxBufLength = MAX_PACKET_SIZE; + HidDataAvailable = 1; + } + // Update output pointer + UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer, FrameLength, UART_RX_BUF_SIZE); + + // Get next header and data + FrameStarted = 0; + } + } + + // Check if we should upload data to Endpoint 2 (CDC) + if (CdcDataAvailable && !Endpoint2UploadBusy && ((CdcLoopCount >= 100) || CdcRxBufLength >= MAX_CDC_FRAME_SIZE)) { + + // 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; + CdcLoopCount = 0; + } else { + CdcLoopCount++; + } + + // 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; + } + +#if 1 + 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; + 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("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) */ }