From 1b382a931d6f3db02fdc3bd1160ef25e9e221e99 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Fri, 19 Apr 2024 00:40:52 -0700 Subject: [PATCH 01/31] Working on making the x035 work. --- ch32v003fun/ch32v003fun.c | 100 +++++++++++-- ch32v003fun/ch32v003fun.h | 249 +++++++++++++++++++++++++++++--- ch32v003fun/ch32v003fun.ld | 7 + ch32v003fun/ch32v003fun.mk | 24 +++ examples_x035/blink/Makefile | 11 ++ examples_x035/blink/blink.c | 31 ++++ examples_x035/blink/funconfig.h | 5 + minichlink/pgm-wch-linke.c | 21 ++- 8 files changed, 415 insertions(+), 33 deletions(-) create mode 100644 examples_x035/blink/Makefile create mode 100644 examples_x035/blink/blink.c create mode 100644 examples_x035/blink/funconfig.h diff --git a/ch32v003fun/ch32v003fun.c b/ch32v003fun/ch32v003fun.c index d7d8f979..f8b435de 100644 --- a/ch32v003fun/ch32v003fun.c +++ b/ch32v003fun/ch32v003fun.c @@ -732,7 +732,7 @@ void RTC_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) #endif // defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) void FLASH_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); void RCC_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); -#ifdef CH32V003 +#if defined(CH32V003) || defined(CH32X03x) void EXTI7_0_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); void AWU_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); #elif defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) @@ -749,7 +749,7 @@ void DMA1_Channel4_IRQHandler( void ) __attribute__((section(".text.vector_ha void DMA1_Channel5_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); void DMA1_Channel6_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); void DMA1_Channel7_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); -#ifdef CH32V003 +#if defined( CH32V003 ) || defined(CH32X03x) void ADC1_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); #elif defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) void ADC1_2_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); @@ -774,7 +774,7 @@ void TIM4_IRQHandler( void ) __attribute__((section(".text.vector_handler")) #endif // defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) void I2C1_EV_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); void I2C1_ER_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); -#ifdef CH32V003 +#if defined( CH32V003 ) || defined( CH32X03x ) void USART1_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); void SPI1_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); #elif defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) @@ -840,7 +840,26 @@ void DMA2_Channel10_IRQHandler( void ) __attribute__((section(".text.vector_han void DMA2_Channel11_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); #endif -#ifdef CH32V003 +#if defined( CH32X03X ) +void USART2_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); +void EXTI15_8_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); +void EXTI25_16_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); +void USART3_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); +void USART4_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); +void DMA1_Channel8_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); +void USBFS_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); +void USBFS_WakeUp_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); +void PIOC_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); +void OPA_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); +void USBPD_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); +void USBPD_WKUP_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); +void TIM2_CC_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); +void TIM2_TRG_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); +void TIM2_BRK_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); +void TIM3_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); +#endif + +#if defined( CH32V003 ) || defined( CH32X03x ) void InterruptVector() __attribute__((naked)) __attribute((section(".init"))) __attribute((weak,alias("InterruptVectorDefault"))); void InterruptVectorDefault() __attribute__((naked)) __attribute((section(".init"))); @@ -852,18 +871,46 @@ void InterruptVectorDefault() .option push;\n\ .option norvc;\n\ j handle_reset\n" ); +#if 0 // What is this for? I don't see any reason to have it. +#ifdef CH32X03x + asm volatile( "\n\ + .word 0x00000013 \n\ + .word 0x00000013 \n\ + .word 0x00000013 \n\ + .word 0x00000013 \n\ + .word 0x00000013 \n\ + .word 0x00000013 \n\ + .word 0x00000013 \n\ + .word 0x00000013 \n\ + .word 0x00000013 \n\ + .word 0x00000013 \n\ + .word 0x00000013 \n\ + .word 0x00000013 \n\ + .word 0x00100073" ); +#endif +#endif + #if !defined(FUNCONF_TINYVECTOR) || !FUNCONF_TINYVECTOR asm volatile( "\n\ .word 0\n\ .word NMI_Handler /* NMI Handler */ \n\ .word HardFault_Handler /* Hard Fault Handler */ \n\ + .word 0\n" +#if !defined(CH32X03x) +" .word Ecall_M_Mode_Handler /* Ecall M Mode */ \n\ + .word 0 \n\ + .word 0 \n\ + .word Ecall_U_Mode_Handler /* Ecall U Mode */ \n\ + .word Break_Point_Handler /* Break Point */ \n\ +" +#else +" .word 0\n\ .word 0\n\ .word 0\n\ .word 0\n\ - .word 0\n\ - .word 0\n\ - .word 0\n\ - .word 0\n\ + .word 0\n" +#endif +" .word 0\n\ .word 0\n\ .word SysTick_Handler /* SysTick Handler */ \n\ .word 0\n\ @@ -892,8 +939,26 @@ void InterruptVectorDefault() .word TIM1_UP_IRQHandler /* TIM1 Update */ \n\ .word TIM1_TRG_COM_IRQHandler /* TIM1 Trigger and Commutation */ \n\ .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ \n\ - .word TIM2_IRQHandler /* TIM2 */ \n\ -"); + .word TIM2_IRQHandler /* TIM2 */ \n" +#if defined( CH32X03X ) +" .word USART2_IRQn = 39, /* UART2 Interrupt */ \n\ + .word EXTI15_8_IRQn = 40, /* External Line[8:15] Interrupt */ \n\ + .word EXTI25_16_IRQn = 41, /* External Line[25:16] Interrupt */ \n\ + .word USART3_IRQn = 42, /* UART2 Interrupt */ \n\ + .word USART4_IRQn = 43, /* UART2 Interrupt */ \n\ + .word DMA1_Channel8_IRQn = 44, /* DMA1 Channel 8 global Interrupt */ \n\ + .word USBFS_IRQn = 45, /* USB Full-Speed Interrupt */ \n\ + .word USBFS_WakeUp_IRQn = 46, /* USB Full-Speed Wake-Up Interrupt */ \n\ + .word PIOC_IRQn = 47, /* Programmable IO Controller Interrupt */ \n\ + .word OPA_IRQn = 48, /* Op Amp Interrupt */ \n\ + .word USBPD_IRQn = 49, /* USB Power Delivery Interrupt */ \n\ + .word USBPD_WKUP_IRQn = 50, /* USB Power Delivery Wake-Up Interrupt */ \n\ + .word TIM2_CC_IRQn = 51, /* Timer 2 Compare Global Interrupt */ \n\ + .word TIM2_TRG_IRQn = 52, /* Timer 2 Trigger Global Interrupt */ \n\ + .word TIM2_BRK_IRQn = 53, /* Timer 2 Brk Global Interrupt */ \n\ + .word TIM3_IRQn = 54, /* Timer 3 Global Interrupt */" +#endif + ); #endif asm volatile( ".option pop;\n"); } @@ -1137,7 +1202,8 @@ void InterruptVectorDefault() .word DMA2_Channel10_IRQHandler /* DMA2 Channel 10 */ \n\ .word DMA2_Channel11_IRQHandler /* DMA2 Channel 11 */ \n" #endif -#endif + +#endif // !defined(FUNCONF_TINYVECTOR) || !FUNCONF_TINYVECTOR " .option rvc; \n"); } @@ -1190,7 +1256,7 @@ void handle_reset( void ) asm volatile( " li t0, 0x1f\n\ csrw 0xbc0, t0\n" -#if defined(CH32V20x) +#if defined(CH32V20x) || defined(CH32X03x) // Enabled nested and hardware stack " li t0, 0x88\n\ csrs mstatus, t0\n" @@ -1232,6 +1298,12 @@ void SetupUART( int uartBRR ) // Push-Pull, 10MHz Output, GPIO D5, with AutoFunction GPIOD->CFGLR &= ~(0xf<<(4*5)); GPIOD->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF)<<(4*5); +#elif defined(CH32X03x) + RCC->APB2PCENR |= RCC_APB2Periph_GPIOB | RCC_APB2Periph_USART1; + + // Push-Pull, 10MHz Output, GPIO A9, with AutoFunction + GPIOB->CFGHR &= ~(0xf<<(4*2)); + GPIOB->CFGHR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF)<<(4*2); #else RCC->APB2PCENR |= RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1; @@ -1403,9 +1475,11 @@ void DelaySysTick( uint32_t n ) #elif defined(CH32V20x) || defined(CH32V30x) uint64_t targend = SysTick->CNT + n; while( ((int64_t)( SysTick->CNT - targend )) < 0 ); -#elif defined(CH32V10x) +#elif defined(CH32V10x) || defined(CH32X03x) uint32_t targend = SysTick->CNTL + n; while( ((int32_t)( SysTick->CNTL - targend )) < 0 ); +#else + #error DelaySysTick not defined. #endif } diff --git a/ch32v003fun/ch32v003fun.h b/ch32v003fun/ch32v003fun.h index 861fc5ff..3b4a530f 100644 --- a/ch32v003fun/ch32v003fun.h +++ b/ch32v003fun/ch32v003fun.h @@ -58,7 +58,7 @@ */ // Sanity check for when porting old code. -#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) +#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) || defined(CH32X03x) #if defined(CH32V003) #error Cannot define CH32V003 and another arch. #endif @@ -85,10 +85,23 @@ #define FUNCONF_USE_HSE 0 #endif +#if defined( CH32X03x ) && FUNCONF_USE_HSE + #error No HSE in CH32X03x +#endif + #if !defined( FUNCONF_USE_PLL ) - #define FUNCONF_USE_PLL 1 // Default to use PLL + #if defined( CH32X03x ) + #define FUNCONF_USE_PLL 0 // No PLL on X03x + #else + #define FUNCONF_USE_PLL 1 // Default to use PLL + #endif +#endif + +#if defined( CH32X03x ) && FUNCONF_USE_PLL + #error No PLL on the X03x #endif + #if !defined( FUNCONF_USE_CLK_SEC ) #define FUNCONF_USE_CLK_SEC 1// use clock security system by default #endif @@ -112,6 +125,8 @@ #ifndef HSI_VALUE #if defined(CH32V003) #define HSI_VALUE (24000000) // Value of the Internal oscillator in Hz, default. + #elif defined(CH32X03x) + #define HSI_VALUE (48000000) #elif defined(CH32V10x) #define HSI_VALUE (8000000) #elif defined(CH32V20x) @@ -208,7 +223,7 @@ typedef enum IRQn SysTicK_IRQn = 12, /* 12 System timer Interrupt */ Software_IRQn = 14, /* 14 software Interrupt */ -#ifdef CH32V003 +#if defined( CH32V003 ) || defined(CH32X03x) /****** RISC-V specific Interrupt Numbers *********************************************************/ WWDG_IRQn = 16, /* Window WatchDog Interrupt */ PVD_IRQn = 17, /* PVD through EXTI Line detection Interrupt */ @@ -233,6 +248,24 @@ typedef enum IRQn TIM1_TRG_COM_IRQn = 36, /* TIM1 Trigger and Commutation Interrupt */ TIM1_CC_IRQn = 37, /* TIM1 Capture Compare Interrupt */ TIM2_IRQn = 38, /* TIM2 global Interrupt */ +#if defined(CH32X03x) + USART2_IRQn = 39, /* UART2 Interrupt */ + EXTI15_8_IRQn = 40, /* External Line[8:15] Interrupt */ + EXTI25_16_IRQn = 41, /* External Line[25:16] Interrupt */ + USART3_IRQn = 42, /* UART2 Interrupt */ + USART4_IRQn = 43, /* UART2 Interrupt */ + DMA1_Channel8_IRQn = 44, /* DMA1 Channel 8 global Interrupt */ + USBFS_IRQn = 45, /* USB Full-Speed Interrupt */ + USBFS_WakeUp_IRQn = 46, /* USB Full-Speed Wake-Up Interrupt */ + PIOC_IRQn = 47, /* Programmable IO Controller Interrupt */ + OPA_IRQn = 48, /* Op Amp Interrupt */ + USBPD_IRQn = 49, /* USB Power Delivery Interrupt */ + USBPD_WKUP_IRQn = 50, /* USB Power Delivery Wake-Up Interrupt */ + TIM2_CC_IRQn = 51, /* Timer 2 Compare Global Interrupt */ + TIM2_TRG_IRQn = 52, /* Timer 2 Trigger Global Interrupt */ + TIM2_BRK_IRQn = 53, /* Timer 2 Brk Global Interrupt */ + TIM3_IRQn = 54, /* Timer 3 Global Interrupt */ +#endif #elif defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) /****** RISC-V specific Interrupt Numbers *********************************************************/ WWDG_IRQn = 16, /* Window WatchDog Interrupt */ @@ -411,7 +444,7 @@ typedef enum IRQn #define HardFault_IRQn EXC_IRQn -#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) +#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) || defined(CH32X03x) #define ADC1_2_IRQn ADC_IRQn #endif @@ -446,6 +479,11 @@ typedef struct __IO uint32_t RDATAR; #if defined(CH32V20x) __IO uint32_t DLYR; +#elif defined(CH32X03x) + __IO uint32_t CTLR3; + __IO uint32_t WDTR1; + __IO uint32_t WDTR2; + __IO uint32_t WDTR3; #endif } ADC_TypeDef; @@ -855,6 +893,10 @@ typedef struct __IO uint32_t BSHR; __IO uint32_t BCR; __IO uint32_t LCKR; +#ifdef CH32X03x + __IO uint32_t CFGXR; + __IO uint32_t BSXR; +#endif } GPIO_TypeDef; #define DYN_GPIO_READ(gpio, field) ((GPIO_##field##_t) { .__FULL = gpio->field }) @@ -868,6 +910,14 @@ typedef struct uint32_t RESERVED0; __IO uint32_t PCFR1; __IO uint32_t EXTICR; +#elif defined(CH32X03x) + uint32_t RESERVED0; + __IO uint32_t PCFR1; + __IO uint32_t EXTICR1; + __IO uint32_t EXTICR2; + uint32_t RESERVED1; + uint32_t RESERVED2; + __IO uint32_t CTLR; #elif defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) __IO uint32_t ECR; __IO uint32_t PCFR1; @@ -1073,6 +1123,19 @@ typedef struct uint16_t RESERVED14; __IO uint16_t DMAADR; uint16_t RESERVED15; +#elif defined( CH32X03x ) + __IO uint32_t CH1CVR; + __IO uint32_t CH2CVR; + __IO uint32_t CH3CVR; + __IO uint32_t CH4CVR; + __IO uint16_t BDTR; + uint16_t RESERVED13; + __IO uint16_t DMACFGR; + uint16_t RESERVED14; + __IO uint16_t DMAADR; + uint16_t RESERVED15; + __IO uint16_t SPEC; + uint16_t RESERVED16; #elif defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) __IO uint16_t CH1CVR; uint16_t RESERVED13; @@ -1608,6 +1671,112 @@ typedef struct #endif // #if defined(CH32V20x) || defined(CH32V30x) + +#if defined(CH32X03x) +/* Touch Sensor, Mirrors Analog to Digital Converter */ +typedef struct +{ + //XXX TODO: CHECK THIS + __IO uint32_t RESERVED0[3]; + __IO uint32_t CHARGE1; + __IO uint32_t CHARGE2; + __IO uint32_t RESERVED1[10]; + __IO uint32_t CHGOFFSET; + __IO uint32_t RESERVED2[3]; + __IO uint32_t DR_ACT_DCG; +} TKEY_TypeDef; + +/* Op amp / comparator */ +typedef struct +{ + //XXX TODO: CHECK THIS + __IO uint16_t CFGR1; + __IO uint16_t CFGR2; + __IO uint32_t CTLR1; + __IO uint32_t CTLR2; + __IO uint32_t OPA_KEY; + __IO uint32_t CMP_KEY; + __IO uint32_t POLL_KEY; +} OPACMP_TypeDef; + +typedef struct +{ + __IO uint8_t BASE_CTLR; + __IO uint8_t UDEV_CTLR; // or host ctlr + __IO uint8_t INT_EN; + __IO uint8_t DEV_ADDR; + __IO uint8_t RESERVED0; + __IO uint8_t MIS_ST; + __IO uint8_t INT_FG; + __IO uint8_t INT_ST; + __IO uint16_t RX_LEN; + __IO uint16_t RESERVED1; + __IO uint8_t UEP4_1_MOD; + __IO uint8_t UEP2_3_MOD; // Also HOST_EP_MOD + __IO uint8_t UEP567_MOD; + __IO uint8_t RESERVED2; + + __IO uint32_t UEP0_DMA; + __IO uint32_t UEP1_DMA; + __IO uint32_t UEP2_DMA; // Also HOST_RX_DMA + __IO uint32_t UEP3_DMA; // Also HOST_TX_DMA + + //__IO uint32_t UEP0_CTLR; + __IO uint16_t UEP0_TX_LEN; + __IO uint16_t UEP0_CTLR_H; + + //__IO uint32_t UEP1_CTLR; + __IO uint16_t UEP1_TX_LEN; + __IO uint16_t UEP1_CTLR_H; // Also HOST_SETUP + + //__IO uint32_t UEP2_CTLR; + __IO uint16_t UEP2_TX_LEN; // Also HOST_PID + __IO uint16_t UEP2_CTLR_H; // Also HOST_RX_CTL + + //__IO uint32_t UEP3_CTLR; + __IO uint16_t UEP3_TX_LEN; // Also HOST_TX_LEN + __IO uint16_t UEP3_CTLR_H; // Also HOST_TX_CTL + + //__IO uint32_t UEP4_CTLR; + __IO uint16_t UEP4_TX_LEN; + __IO uint16_t UEP4_CTLR_H; + + __IO uint32_t RESERVED3[8]; + + __IO uint32_t UEP5_DMA; + __IO uint32_t UEP6_DMA; + __IO uint32_t UEP7_DMA; + + //__IO uint32_t UEP5_CTLR; + __IO uint16_t UEP5_TX_LEN; + __IO uint16_t UEP5_CTLR_H; + + //__IO uint32_t UEP6_CTLR; + __IO uint16_t UEP6_TX_LEN; + __IO uint16_t UEP6_CTLR_H; + + //__IO uint32_t UEP7_CTLR; + __IO uint16_t UEP7_TX_LEN; + __IO uint16_t UEP7_CTLR_H; + + __IO uint32_t UEPX_MOD; +} USBFS_TypeDef; + +// TODO: Break host host-mode. + +/* USB Power Delivery */ +typedef struct +{ + __IO uint32_t CONFIG; + __IO uint32_t CONTROL; + __IO uint32_t STATUS; + __IO uint32_t PORT; + __IO uint32_t DMA; +} USBPD_TypeDef; + +#endif // #if defined(CH32X03x) + + #endif /* Peripheral memory map */ @@ -1636,10 +1805,12 @@ typedef struct #define AHBPERIPH_BASE (PERIPH_BASE + 0x20000) #define TIM2_BASE (APB1PERIPH_BASE + 0x0000) -#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) +#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) || defined(CH32X03x) #define TIM3_BASE (APB1PERIPH_BASE + 0x0400) +#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) #define TIM4_BASE (APB1PERIPH_BASE + 0x0800) #define TIM5_BASE (APB1PERIPH_BASE + 0x0C00) +#endif // CH32V10x, CH32V20x, CH32V30x #if defined(CH32V30x) // CH32V30x #define TIM6_BASE (APB1PERIPH_BASE + 0x1000) #define TIM7_BASE (APB1PERIPH_BASE + 0x1400) @@ -1654,8 +1825,10 @@ typedef struct #define TIM13_BASE (APB1PERIPH_BASE + 0x1C00) #define TIM14_BASE (APB1PERIPH_BASE + 0x2000) #endif // CH32V10x +#if defined(CH32V003) || defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) #define RTC_BASE (APB1PERIPH_BASE + 0x2800) #endif +#endif #define WWDG_BASE (APB1PERIPH_BASE + 0x2C00) #define IWDG_BASE (APB1PERIPH_BASE + 0x3000) #if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) @@ -1663,6 +1836,8 @@ typedef struct #if defined(CH32V10x) || defined(CH32V30x) #define SPI3_BASE (APB1PERIPH_BASE + 0x3C00) #endif // defined(CH32V30x) || defined(CH32V10x) +#endif +#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) || defined(CH32X03x) #define USART2_BASE (APB1PERIPH_BASE + 0x4400) #define USART3_BASE (APB1PERIPH_BASE + 0x4800) #define UART4_BASE (APB1PERIPH_BASE + 0x4C00) @@ -1691,7 +1866,7 @@ typedef struct #define AFIO_BASE (APB2PERIPH_BASE + 0x0000) #define EXTI_BASE (APB2PERIPH_BASE + 0x0400) #define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) -#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) +#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) || defined(CH32X03x) #define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00) #endif #define GPIOC_BASE (APB2PERIPH_BASE + 0x1000) @@ -1755,12 +1930,19 @@ typedef struct #define RCC_BASE (AHBPERIPH_BASE + 0x1000) #define FLASH_R_BASE (AHBPERIPH_BASE + 0x2000) /* Flash registers base address */ + #if defined(CH32V20x) #define CRC_BASE (AHBPERIPH_BASE + 0x3000) #define OPA_BASE (AHBPERIPH_BASE + 0x3804) #define ETH10M_BASE (AHBPERIPH_BASE + 0x8000) #define USBFS_BASE ((uint32_t)0x50000000) +#elif defined(CH32X03x) + +#define OPA_BASE (AHBPERIPH_BASE + 0x6000) +#define USBFS_BASE (AHBPERIPH_BASE + 0x3400) +#define USBPD_BASE (AHBPERIPH_BASE + 0x7000) + #elif defined(CH32V30x) #define CRC_BASE (AHBPERIPH_BASE + 0x3000) #define USBHS_BASE (AHBPERIPH_BASE + 0x3400) @@ -1859,7 +2041,7 @@ typedef struct #define AFIO ((AFIO_TypeDef *)AFIO_BASE) #define EXTI ((EXTI_TypeDef *)EXTI_BASE) #define GPIOA ((GPIO_TypeDef *)GPIOA_BASE) -#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) +#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) || defined(CH32X03x) #define GPIOB ((GPIO_TypeDef *)GPIOB_BASE) #endif #define GPIOC ((GPIO_TypeDef *)GPIOC_BASE) @@ -1872,6 +2054,13 @@ typedef struct #define ADC1 ((ADC_TypeDef *)ADC1_BASE) #if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) #define ADC2 ((ADC_TypeDef *)ADC2_BASE) +#endif +#ifdef CH32X03x +#define TKey ((TKEY_TypeDef *)ADC1_BASE) +#define OPA ((OPACMP_TypeDef *)OPA_BASE) +#define USBFS ((USBFS_TypeDef *)USBFS_BASE) +#define USBPD ((USBPD_TypeDef *)USBPD_BASE) + #endif #if defined(CH32V20x) || defined(CH32V30x) #define TKey1 ((ADC_TypeDef *)ADC1_BASE) @@ -1904,7 +2093,7 @@ typedef struct #define DMA1_Channel5 ((DMA_Channel_TypeDef *)DMA1_Channel5_BASE) #define DMA1_Channel6 ((DMA_Channel_TypeDef *)DMA1_Channel6_BASE) #define DMA1_Channel7 ((DMA_Channel_TypeDef *)DMA1_Channel7_BASE) -#if defined(CH32V20x) +#if defined(CH32V20x) || defined(CH32X03x) #define DMA1_Channel8 ((DMA_Channel_TypeDef *)DMA1_Channel8_BASE) #endif #if defined(CH32V10x) || defined(CH32V30x) @@ -5080,7 +5269,7 @@ typedef struct #define RCC_HPRE_2 ((uint32_t)0x00000040) /* Bit 2 */ #define RCC_HPRE_3 ((uint32_t)0x00000080) /* Bit 3 */ -#if defined(CH32V003) +#if defined(CH32V003) || defined(CH32X03x) #define RCC_HPRE_DIV1 ((uint32_t)0x00000000) /* SYSCLK not divided */ #define RCC_HPRE_DIV2 ((uint32_t)0x00000010) /* SYSCLK divided by 2 */ #define RCC_HPRE_DIV3 ((uint32_t)0x00000020) /* SYSCLK divided by 3 */ @@ -9131,7 +9320,9 @@ typedef enum #define GPIO_PortSourceGPIOA ((uint8_t)0x00) #define GPIO_PortSourceGPIOC ((uint8_t)0x02) #define GPIO_PortSourceGPIOD ((uint8_t)0x03) -#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) +#if defined(CH32X03x) +#define GPIO_PortSourceGPIOB ((uint8_t)0x01) +#elif defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) #define GPIO_PortSourceGPIOB ((uint8_t)0x01) #define GPIO_PortSourceGPIOD ((uint8_t)0x03) #define GPIO_PortSourceGPIOE ((uint8_t)0x04) @@ -9148,7 +9339,7 @@ typedef enum #define GPIO_PinSource5 ((uint8_t)0x05) #define GPIO_PinSource6 ((uint8_t)0x06) #define GPIO_PinSource7 ((uint8_t)0x07) -#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) +#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) || defined(CH32X03x) #define GPIO_PinSource8 ((uint8_t)0x08) #define GPIO_PinSource9 ((uint8_t)0x09) #define GPIO_PinSource10 ((uint8_t)0x0A) @@ -9883,7 +10074,7 @@ typedef struct #endif -#ifdef CH32V003 +#if defined(CH32V003) || defined(CH32X03x) /* AHB_peripheral */ #define RCC_AHBPeriph_DMA1 ((uint32_t)0x00000001) @@ -9892,6 +10083,9 @@ typedef struct /* APB2_peripheral */ #define RCC_APB2Periph_AFIO ((uint32_t)0x00000001) #define RCC_APB2Periph_GPIOA ((uint32_t)0x00000004) +#ifdef CH32X03x +#define RCC_APB2Periph_GPIOB ((uint32_t)0x00000008) +#endif #define RCC_APB2Periph_GPIOC ((uint32_t)0x00000010) #define RCC_APB2Periph_GPIOD ((uint32_t)0x00000020) #define RCC_APB2Periph_ADC1 ((uint32_t)0x00000200) @@ -9905,6 +10099,17 @@ typedef struct #define RCC_APB1Periph_I2C1 ((uint32_t)0x00200000) #define RCC_APB1Periph_PWR ((uint32_t)0x10000000) +#if defined(CH32X03x) + +/* APB2_peripheral */ +#define RCC_APB2Periph_GPIOB ((uint32_t)0x00000008) + +#define RCC_APB1Periph_USART2 ((uint32_t)0x00020000) +#define RCC_APB1Periph_USART3 ((uint32_t)0x00040000) +#define RCC_APB1Periph_UART4 ((uint32_t)0x00080000) + +#endif + #elif defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) /* AHB_peripheral */ @@ -11481,7 +11686,7 @@ typedef struct{ __IO uint32_t SCTLR; }PFIC_Type; -#ifdef CH32V003 +#if defined (CH32V003) /* memory mapped structure for SysTick */ typedef struct @@ -11505,7 +11710,7 @@ typedef struct __IO uint64_t CMP; } SysTick_Type; -#elif defined(CH32V10x) +#elif defined(CH32V10x) || defined(CH32X03x) /* memory mapped structure for SysTick */ typedef struct @@ -12310,8 +12515,7 @@ extern "C" { #define PD6 54 #define PD7 55 - -#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) +#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) || defined( CH32X03x ) #define PA0 0 #define PA3 3 #define PA4 4 @@ -12342,6 +12546,14 @@ extern "C" { #define PB13 29 #define PB14 30 #define PB15 31 +#define PC8 40 +#define PC9 41 +#define PC10 42 +#define PC11 43 +#define PC12 44 +#define PC13 45 +#define PC14 46 +#define PC15 47 #endif @@ -12350,7 +12562,10 @@ extern "C" { #define funDigitalWrite( pin, value ) { GpioOf( pin )->BSHR = 1<<((!(value))*16 + ((pin) & 0xf)); } -#if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) +#if defined(CH32X03x) +#define funGpioInitAll() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC ); } +#define funPinMode( pin, mode ) { *((&GpioOf(pin)->CFGLR)+((pin&0x8)>>3)) = ( (*((&GpioOf(pin)->CFGLR)+((pin&0x8)>>3))) & (~(0xf<<(4*((pin)&0x7))))) | ((mode)<<(4*((pin)&0x7))); } +#elif defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) #define funGpioInitAll() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD ); } #define funPinMode( pin, mode ) { *((&GpioOf(pin)->CFGLR)+((pin&0x8)>>3)) = ( (*((&GpioOf(pin)->CFGLR)+((pin&0x8)>>3))) & (~(0xf<<(4*((pin)&0x7))))) | ((mode)<<(4*((pin)&0x7))); } #define funGpioInitB() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB ); } diff --git a/ch32v003fun/ch32v003fun.ld b/ch32v003fun/ch32v003fun.ld index 4ad76b48..10096e47 100644 --- a/ch32v003fun/ch32v003fun.ld +++ b/ch32v003fun/ch32v003fun.ld @@ -38,6 +38,13 @@ MEMORY #else #error "Unknown MCU package" #endif +#elif TARGET_MCU_LD == 4 + #if MCU_PACKAGE == 1 + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 62K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K + #else + #error "Unknown MCU package" + #endif #else #error "Unknown MCU target" #endif diff --git a/ch32v003fun/ch32v003fun.mk b/ch32v003fun/ch32v003fun.mk index 664a861b..a4cbcb69 100644 --- a/ch32v003fun/ch32v003fun.mk +++ b/ch32v003fun/ch32v003fun.mk @@ -56,6 +56,30 @@ else endif TARGET_MCU_LD:=1 + else ifeq ($(findstring CH32X03,$(TARGET_MCU)),CH32X03) # CH32X033, X035 + TARGET_MCU_PACKAGE?=CH32X035F8U6 + CFLAGS_ARCH+= -march=rv32imac \ + -mabi=ilp32 \ + -DCH32X03x=1 + + # MCU Flash/RAM split + ifeq ($(findstring F8, $(TARGET_MCU_PACKAGE)), F8) + MCU_PACKAGE:=1 + else ifeq ($(findstring R8, $(TARGET_MCU_PACKAGE)), R8) + MCU_PACKAGE:=1 + else ifeq ($(findstring K8, $(TARGET_MCU_PACKAGE)), K8) + MCU_PACKAGE:=1 + else ifeq ($(findstring C8, $(TARGET_MCU_PACKAGE)), C8) + MCU_PACKAGE:=1 + else ifeq ($(findstring G8, $(TARGET_MCU_PACKAGE)), G8) + MCU_PACKAGE:=1 + else ifeq ($(findstring G6, $(TARGET_MCU_PACKAGE)), G6) + MCU_PACKAGE:=1 + else ifeq ($(findstring F7, $(TARGET_MCU_PACKAGE)), F7) + MCU_PACKAGE:=1 + endif + + TARGET_MCU_LD:=4 else ifeq ($(findstring CH32V20,$(TARGET_MCU)),CH32V20) # CH32V203 TARGET_MCU_PACKAGE?=CH32V203F8P6 CFLAGS_ARCH+= -march=rv32imac \ diff --git a/examples_x035/blink/Makefile b/examples_x035/blink/Makefile new file mode 100644 index 00000000..0290b25c --- /dev/null +++ b/examples_x035/blink/Makefile @@ -0,0 +1,11 @@ +all : flash + +TARGET:=blink +TARGET_MCU:=CH32X035 + +include ../../ch32v003fun/ch32v003fun.mk + +flash : cv_flash +clean : cv_clean + + diff --git a/examples_x035/blink/blink.c b/examples_x035/blink/blink.c new file mode 100644 index 00000000..61199a81 --- /dev/null +++ b/examples_x035/blink/blink.c @@ -0,0 +1,31 @@ +#include "ch32v003fun.h" +#include + +int main() +{ + //SystemInit(); + + funGpioInitAll(); + + funPinMode( PA0, GPIO_CFGLR_OUT_10Mhz_PP ); + + while(1) + { + funDigitalWrite( PA0, FUN_HIGH ); // Turn on GPIO + funDigitalWrite( PA0, FUN_HIGH ); // Turn on GPIO + funDigitalWrite( PA0, FUN_HIGH ); // Turn on GPIO + funDigitalWrite( PA0, FUN_HIGH ); // Turn on GPIO + funDigitalWrite( PA0, FUN_HIGH ); // Turn on GPIO + funDigitalWrite( PA0, FUN_HIGH ); // Turn on GPIO + //Delay_Ms( 1000 ); + funDigitalWrite( PA0, FUN_LOW ); // Turn off GPIO + funDigitalWrite( PA0, FUN_LOW ); // Turn off GPIO + funDigitalWrite( PA0, FUN_LOW ); // Turn off GPIO + funDigitalWrite( PA0, FUN_LOW ); // Turn off GPIO + funDigitalWrite( PA0, FUN_LOW ); // Turn off GPIO + funDigitalWrite( PA0, FUN_LOW ); // Turn off GPIO + funDigitalWrite( PA0, FUN_LOW ); // Turn off GPIO + funDigitalWrite( PA0, FUN_LOW ); // Turn off GPIO + //Delay_Ms( 1000 ); + } +} diff --git a/examples_x035/blink/funconfig.h b/examples_x035/blink/funconfig.h new file mode 100644 index 00000000..d9342aed --- /dev/null +++ b/examples_x035/blink/funconfig.h @@ -0,0 +1,5 @@ +#ifndef _FUNCONFIG_H +#define _FUNCONFIG_H + +#endif + diff --git a/minichlink/pgm-wch-linke.c b/minichlink/pgm-wch-linke.c index b37ae824..b7250bd9 100644 --- a/minichlink/pgm-wch-linke.c +++ b/minichlink/pgm-wch-linke.c @@ -322,15 +322,30 @@ static int LESetupInterface( void * d ) // This puts the processor on hold to allow the debugger to run. int already_tried_reset = 0; + int is_already_connected = 0; do { + // Read DMSTATUS - in case we are a ch32x035, or other chip that does not respond to \x81\x0d\x01\x02. + wch_link_command( dev, "\x81\x08\x06\x05\x11\x00\x00\x00\x00\x01", 11, (int*)&transferred, rbuff, 1024 ); // Reply: Ignored, 820d050900300500 + if( transferred == 9 && rbuff[8] != 0x02 && rbuff[8] != 0x03 ) + { + // Already connected. + if( is_already_connected ) + { + printf( "Already Connected\n" ); + break; + } + is_already_connected = 1; + } + + wch_link_command( dev, "\x81\x0d\x01\x02", 4, (int*)&transferred, rbuff, 1024 ); // Reply: Ignored, 820d050900300500 if (rbuff[0] == 0x81 && rbuff[1] == 0x55 && rbuff[2] == 0x01 ) // && rbuff[3] == 0x01 ) { // The following code may try to execute a few times to get the processor to actually reset. // This code could likely be much better. - - fprintf(stderr, "link error, nothing connected to linker (%d = [%02x %02x %02x %02x]). Trying to put processor in hold and retrying.\n", transferred, rbuff[0], rbuff[1], rbuff[2], rbuff[3]); + if( already_tried_reset > 1) + fprintf(stderr, "link error, nothing connected to linker (%d = [%02x %02x %02x %02x]). Trying to put processor in hold and retrying.\n", transferred, rbuff[0], rbuff[1], rbuff[2], rbuff[3]); // Give up if too long if( already_tried_reset > 10 ) @@ -360,7 +375,7 @@ static int LESetupInterface( void * d ) } while( 1 ); if(rbuff[3] == 0x08 || rbuff[3] > 0x09) { - fprintf( stderr, "Chip Type unknown. Aborting...\n" ); + fprintf( stderr, "Chip Type unknown [%02x]. Aborting...\n", rbuff[3] ); return -1; } From 094dc3377ee9f4aa38cfab5fbfa5e1db509d984a Mon Sep 17 00:00:00 2001 From: cnlohr Date: Fri, 19 Apr 2024 01:51:38 -0700 Subject: [PATCH 02/31] Working on 035, need to regression test on 003 and 203 --- examples_x035/blink/blink.c | 15 ++-------- minichlink/minichlink.h | 3 +- minichlink/pgm-wch-linke.c | 56 ++++++++++++++++++++++++++----------- 3 files changed, 44 insertions(+), 30 deletions(-) diff --git a/examples_x035/blink/blink.c b/examples_x035/blink/blink.c index 61199a81..234a8c5f 100644 --- a/examples_x035/blink/blink.c +++ b/examples_x035/blink/blink.c @@ -11,21 +11,12 @@ int main() while(1) { - funDigitalWrite( PA0, FUN_HIGH ); // Turn on GPIO - funDigitalWrite( PA0, FUN_HIGH ); // Turn on GPIO - funDigitalWrite( PA0, FUN_HIGH ); // Turn on GPIO - funDigitalWrite( PA0, FUN_HIGH ); // Turn on GPIO - funDigitalWrite( PA0, FUN_HIGH ); // Turn on GPIO funDigitalWrite( PA0, FUN_HIGH ); // Turn on GPIO //Delay_Ms( 1000 ); funDigitalWrite( PA0, FUN_LOW ); // Turn off GPIO - funDigitalWrite( PA0, FUN_LOW ); // Turn off GPIO - funDigitalWrite( PA0, FUN_LOW ); // Turn off GPIO - funDigitalWrite( PA0, FUN_LOW ); // Turn off GPIO - funDigitalWrite( PA0, FUN_LOW ); // Turn off GPIO - funDigitalWrite( PA0, FUN_LOW ); // Turn off GPIO - funDigitalWrite( PA0, FUN_LOW ); // Turn off GPIO - funDigitalWrite( PA0, FUN_LOW ); // Turn off GPIO //Delay_Ms( 1000 ); + funDigitalWrite( PA0, FUN_HIGH ); // Turn on GPIO + asm volatile( "c.nop" ); + funDigitalWrite( PA0, FUN_LOW ); // Turn off GPIO } } diff --git a/minichlink/minichlink.h b/minichlink/minichlink.h index 170667f9..6266cbb9 100644 --- a/minichlink/minichlink.h +++ b/minichlink/minichlink.h @@ -111,7 +111,8 @@ enum RiscVChip { CHIP_CH32V20x = 0x05, CHIP_CH32V30x = 0x06, CHIP_CH58x = 0x07, - CHIP_CH32V003 = 0x09 + CHIP_CH32V003 = 0x09, + CHIP_CH32X03x = 0x1000, // TODO: Figure out how to get the programmer to really tell us what this is. }; struct InternalState diff --git a/minichlink/pgm-wch-linke.c b/minichlink/pgm-wch-linke.c index b7250bd9..68352980 100644 --- a/minichlink/pgm-wch-linke.c +++ b/minichlink/pgm-wch-linke.c @@ -37,6 +37,9 @@ static void printChipInfo(enum RiscVChip chip) { case CHIP_CH58x: fprintf(stderr, "Detected: CH58x\n"); break; + case CHIP_CH32X03x: + fprintf(stderr, "Detected: CH32X03x\n"); + break; case CHIP_CH32V003: fprintf(stderr, "Detected: CH32V003\n"); break; @@ -46,6 +49,7 @@ static void printChipInfo(enum RiscVChip chip) { static int checkChip(enum RiscVChip chip) { switch(chip) { case CHIP_CH32V003: + case CHIP_CH32X03x: return 0; // Use direct mode case CHIP_CH32V10x: case CHIP_CH32V20x: @@ -333,12 +337,13 @@ static int LESetupInterface( void * d ) if( is_already_connected ) { printf( "Already Connected\n" ); + // Still need to read in the data so we can select the correct chip. + wch_link_command( dev, "\x81\x0d\x01\x02", 4, (int*)&transferred, rbuff, 1024 ); // ?? this seems to work? break; } is_already_connected = 1; } - wch_link_command( dev, "\x81\x0d\x01\x02", 4, (int*)&transferred, rbuff, 1024 ); // Reply: Ignored, 820d050900300500 if (rbuff[0] == 0x81 && rbuff[1] == 0x55 && rbuff[2] == 0x01 ) // && rbuff[3] == 0x01 ) { @@ -382,26 +387,13 @@ static int LESetupInterface( void * d ) enum RiscVChip chip = (enum RiscVChip)rbuff[3]; printChipInfo(chip); - int result = checkChip(chip); - if( result == 1 ) // Using blob write - { - fprintf( stderr, "Using binary blob write for operation.\n" ); - MCF.WriteBinaryBlob = LEWriteBinaryBlob; - - iss->sector_size = 256; - - wch_link_command( dev, "\x81\x0d\x01\x03", 4, (int*)&transferred, rbuff, 1024 ); // Reply: Ignored, 820d050900300500 - } else if( result < 0 ) { - fprintf( stderr, "Chip type not supported. Aborting...\n" ); - return -1; - } - iss->target_chip_type = chip; // For some reason, if we don't do this sometimes the programmer starts in a hosey mode. MCF.WriteReg32( d, DMCONTROL, 0x80000001 ); // Make the debug module work properly. MCF.WriteReg32( d, DMCONTROL, 0x80000001 ); // Initiate a halt request. - MCF.WriteReg32( d, DMCONTROL, 0x80000001 ); // No, really make sure. + MCF.WriteReg32( d, DMCONTROL, 0x80000003 ); // No, really make sure, and also super halt processor. + MCF.WriteReg32( d, DMCONTROL, 0x80000001 ); // Un-super-halt processor. MCF.WriteReg32( d, DMABSTRACTCS, 0x00000700 ); // Ignore any pending errors. MCF.WriteReg32( d, DMABSTRACTAUTO, 0 ); MCF.WriteReg32( d, DMCOMMAND, 0x00221000 ); // Read x0 (Null command) with nopostexec (to fix v307 read issues) @@ -428,11 +420,34 @@ static int LESetupInterface( void * d ) fprintf( stderr, "Error: could not get part status\n" ); return -1; } - fprintf( stderr, "Flash Storage: %d kB\n", (rbuff[2]<<8) | rbuff[3] ); // Is this Flash size? + int flash_size = (rbuff[2]<<8) | rbuff[3]; + fprintf( stderr, "Flash Storage: %d kB\n", flash_size ); // Is this Flash size? fprintf( stderr, "Part UUID : %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", rbuff[4], rbuff[5], rbuff[6], rbuff[7], rbuff[8], rbuff[9], rbuff[10], rbuff[11] ); fprintf( stderr, "PFlags : %02x-%02x-%02x-%02x\n", rbuff[12], rbuff[13], rbuff[14], rbuff[15] ); fprintf( stderr, "Part Type (B): %02x-%02x-%02x-%02x\n", rbuff[16], rbuff[17], rbuff[18], rbuff[19] ); + if( iss->target_chip_type == CHIP_CH32V10x && flash_size == 62 ) + { + fprintf( stderr, "While the debugger reports this as a CH32V10x, it's probably a CH32X03x\n" ); + chip = iss->target_chip_type = CHIP_CH32X03x; + iss->sector_size = 256; + } + + int result = checkChip(chip); + if( result == 1 ) // Using blob write + { + fprintf( stderr, "Using binary blob write for operation.\n" ); + MCF.WriteBinaryBlob = LEWriteBinaryBlob; + + iss->sector_size = 256; + + wch_link_command( dev, "\x81\x0d\x01\x03", 4, (int*)&transferred, rbuff, 1024 ); // Reply: Ignored, 820d050900300500 + } else if( result < 0 ) { + fprintf( stderr, "Chip type not supported. Aborting...\n" ); + return -1; + } + + // Check for read protection wch_link_command( dev, "\x81\x06\x01\x01", 4, (int*)&transferred, rbuff, 1024 ); if(transferred != 4) { @@ -790,6 +805,13 @@ static int LEWriteBinaryBlob( void * d, uint32_t address_to_write, uint32_t len, WCHCHECK( libusb_bulk_transfer( (libusb_device_handle *)dev, 0x02, blob+pplace, iss->sector_size, &transferred, WCHTIMEOUT ) ); } } + + uint32_t rr; + int r = MCF.ReadReg32( d, DMABSTRACTCS, &rr ); + printf( "PLX HALT %08x %d\n", rr, r ); + + r = MCF.ReadReg32( d, DMSTATUS, &rr ); + printf( "PLX HALT %08x %d\n", rr, r ); return 0; } From cd36df3431f1c718ac89c07b3145dbcb09bbad00 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Fri, 19 Apr 2024 01:57:50 -0700 Subject: [PATCH 03/31] Fix bootup code for 035 --- ch32v003fun/ch32v003fun.c | 22 ++++++++++++---------- ch32v003fun/ch32v003fun.h | 2 +- examples_x035/blink/blink.c | 2 +- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/ch32v003fun/ch32v003fun.c b/ch32v003fun/ch32v003fun.c index f8b435de..4af6ef54 100644 --- a/ch32v003fun/ch32v003fun.c +++ b/ch32v003fun/ch32v003fun.c @@ -1504,7 +1504,7 @@ void SystemInit() #define BASE_CFGR0 RCC_HPRE_DIV1 | RCC_PPRE2_DIV1 | RCC_PPRE1_DIV2 | PLL_MULTIPLICATION #endif #else - #if defined(CH32V003) + #if defined(CH32V003) || defined(CH32X03x) #define BASE_CFGR0 RCC_HPRE_DIV1 // HCLK = SYSCLK = APB1 And, no pll. #else #define BASE_CFGR0 RCC_HPRE_DIV1 | RCC_PPRE2_DIV1 | RCC_PPRE1_DIV1 @@ -1515,6 +1515,17 @@ void SystemInit() #define BASE_CTLR (((FUNCONF_HSITRIM) << 3) | RCC_HSION | HSEBYP | RCC_CSS) //#define BASE_CTLR (((FUNCONF_HSITRIM) << 3) | HSEBYP | RCC_CSS) // disable HSI in HSE modes + // CH32V003 flash latency +#if defined(CH32X03x) + FLASH->ACTLR = FLASH_ACTLR_LATENCY_2; // +2 Cycle Latency (Recommended per TRM) +#elif defined(CH32V003) + #if FUNCONF_SYSTEM_CORE_CLOCK > 25000000 + FLASH->ACTLR = FLASH_ACTLR_LATENCY_1; // +1 Cycle Latency + #else + FLASH->ACTLR = FLASH_ACTLR_LATENCY_0; // +0 Cycle Latency + #endif +#endif + #if defined(FUNCONF_USE_HSI) && FUNCONF_USE_HSI #if defined(CH32V30x) || defined(CH32V20x) || defined(CH32V10x) EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE; @@ -1557,15 +1568,6 @@ void SystemInit() FLASH->ACTLR |= FLASH_ACTLR_PRFTBE; #endif - // CH32V003 flash latency -#if defined(CH32V003) - #if FUNCONF_SYSTEM_CORE_CLOCK > 25000000 - FLASH->ACTLR = FLASH_ACTLR_LATENCY_1; // +1 Cycle Latency - #else - FLASH->ACTLR = FLASH_ACTLR_LATENCY_0; // +0 Cycle Latency - #endif -#endif - // CH32V10x flash latency #if defined(CH32V10x) #if defined(FUNCONF_USE_HSE) && FUNCONF_USE_HSE diff --git a/ch32v003fun/ch32v003fun.h b/ch32v003fun/ch32v003fun.h index 3b4a530f..572f5c7a 100644 --- a/ch32v003fun/ch32v003fun.h +++ b/ch32v003fun/ch32v003fun.h @@ -4466,7 +4466,7 @@ typedef struct /* FLASH and Option Bytes Registers */ /******************************************************************************/ -#if defined(CH32V003) || defined(CH32V10x) +#if defined(CH32V003) || defined(CH32V10x) || defined(CH32X03x) /******************* Bit definition for FLASH_ACTLR register ******************/ #define FLASH_ACTLR_LATENCY ((uint8_t)0x03) /* LATENCY[2:0] bits (Latency) */ #define FLASH_ACTLR_LATENCY_0 ((uint8_t)0x00) /* Bit 0 */ diff --git a/examples_x035/blink/blink.c b/examples_x035/blink/blink.c index 234a8c5f..0a57d204 100644 --- a/examples_x035/blink/blink.c +++ b/examples_x035/blink/blink.c @@ -3,7 +3,7 @@ int main() { - //SystemInit(); + SystemInit(); funGpioInitAll(); From 526d9c5af29c8a6aedf7ff33c71c2991489fc46a Mon Sep 17 00:00:00 2001 From: cnlohr Date: Fri, 19 Apr 2024 02:10:48 -0700 Subject: [PATCH 04/31] Get systick up and running + debug printf + input. --- ch32v003fun/ch32v003fun.c | 1 - ch32v003fun/ch32v003fun.h | 15 +++++++- examples_x035/debugprintfdemo/Makefile | 10 +++++ .../debugprintfdemo/debugprintfdemo.c | 37 +++++++++++++++++++ examples_x035/debugprintfdemo/funconfig.h | 9 +++++ 5 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 examples_x035/debugprintfdemo/Makefile create mode 100644 examples_x035/debugprintfdemo/debugprintfdemo.c create mode 100644 examples_x035/debugprintfdemo/funconfig.h diff --git a/ch32v003fun/ch32v003fun.c b/ch32v003fun/ch32v003fun.c index 4af6ef54..252899ea 100644 --- a/ch32v003fun/ch32v003fun.c +++ b/ch32v003fun/ch32v003fun.c @@ -1015,7 +1015,6 @@ asm volatile( #endif ); - #if defined( FUNCONF_SYSTICK_USE_HCLK ) && FUNCONF_SYSTICK_USE_HCLK SysTick->CTLR = 5; #else diff --git a/ch32v003fun/ch32v003fun.h b/ch32v003fun/ch32v003fun.h index 572f5c7a..f7823c2f 100644 --- a/ch32v003fun/ch32v003fun.h +++ b/ch32v003fun/ch32v003fun.h @@ -11710,7 +11710,20 @@ typedef struct __IO uint64_t CMP; } SysTick_Type; -#elif defined(CH32V10x) || defined(CH32X03x) +#elif defined(CH32X03x) + +/* memory mapped structure for SysTick */ +typedef struct +{ + __IO uint32_t CTLR; + __IO uint32_t SR; + __IO uint32_t CNTL; + __IO uint32_t CNTH; + __IO uint32_t CMPL; + __IO uint32_t CMPH; +} SysTick_Type; + +#elif defined(CH32V10x) /* memory mapped structure for SysTick */ typedef struct diff --git a/examples_x035/debugprintfdemo/Makefile b/examples_x035/debugprintfdemo/Makefile new file mode 100644 index 00000000..8a29f56f --- /dev/null +++ b/examples_x035/debugprintfdemo/Makefile @@ -0,0 +1,10 @@ +all : flash + +TARGET:=debugprintfdemo +TARGET_MCU:=CH32X035 + +include ../../ch32v003fun/ch32v003fun.mk + +flash : cv_flash +clean : cv_clean + diff --git a/examples_x035/debugprintfdemo/debugprintfdemo.c b/examples_x035/debugprintfdemo/debugprintfdemo.c new file mode 100644 index 00000000..3c65c329 --- /dev/null +++ b/examples_x035/debugprintfdemo/debugprintfdemo.c @@ -0,0 +1,37 @@ +/* Small example showing how to use the SWIO programming pin to + do printf through the debug interface */ + +#include "ch32v003fun.h" +#include + +uint32_t count; + +int last = 0; +void handle_debug_input( int numbytes, uint8_t * data ) +{ + last = data[0]; + count += numbytes; +} + +int main() +{ + SystemInit(); + + funGpioInitAll(); + + funPinMode( PA0, GPIO_CFGLR_OUT_10Mhz_PP ); + + while(1) + { + GPIOA->BSHR = 1; // Turn on GPIOs + printf( "+%lu %lu\n", count++ ); + Delay_Ms(100); + int i; + for( i = 0; i < 10000; i++ ) + poll_input(); + GPIOA->BSHR = (1<<16); // Turn off GPIODs + printf( "-%lu[%c]\n", count++, last ); + Delay_Ms(100); + } +} + diff --git a/examples_x035/debugprintfdemo/funconfig.h b/examples_x035/debugprintfdemo/funconfig.h new file mode 100644 index 00000000..a8a70b30 --- /dev/null +++ b/examples_x035/debugprintfdemo/funconfig.h @@ -0,0 +1,9 @@ +#ifndef _FUNCONFIG_H +#define _FUNCONFIG_H + +// Though this should be on by default we can extra force it on. +#define FUNCONF_USE_DEBUGPRINTF 1 +#define FUNCONF_DEBUGPRINTF_TIMEOUT (1<<31) // Wait for a very very long time. + +#endif + From df3cdc828cb04f8bcfa5a3cafb9ae5b90f1c7f15 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Fri, 19 Apr 2024 02:30:28 -0700 Subject: [PATCH 05/31] Fixed up register addresses --- ch32v003fun/ch32v003fun.h | 64 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/ch32v003fun/ch32v003fun.h b/ch32v003fun/ch32v003fun.h index f7823c2f..931cfee4 100644 --- a/ch32v003fun/ch32v003fun.h +++ b/ch32v003fun/ch32v003fun.h @@ -1676,7 +1676,6 @@ typedef struct /* Touch Sensor, Mirrors Analog to Digital Converter */ typedef struct { - //XXX TODO: CHECK THIS __IO uint32_t RESERVED0[3]; __IO uint32_t CHARGE1; __IO uint32_t CHARGE2; @@ -1689,7 +1688,6 @@ typedef struct /* Op amp / comparator */ typedef struct { - //XXX TODO: CHECK THIS __IO uint16_t CFGR1; __IO uint16_t CFGR2; __IO uint32_t CTLR1; @@ -1699,6 +1697,7 @@ typedef struct __IO uint32_t POLL_KEY; } OPACMP_TypeDef; +/* USB Full Speed Device Mode */ typedef struct { __IO uint8_t BASE_CTLR; @@ -1747,6 +1746,8 @@ typedef struct __IO uint32_t UEP6_DMA; __IO uint32_t UEP7_DMA; + __IO uint32_t RESERVED4; + //__IO uint32_t UEP5_CTLR; __IO uint16_t UEP5_TX_LEN; __IO uint16_t UEP5_CTLR_H; @@ -1762,7 +1763,63 @@ typedef struct __IO uint32_t UEPX_MOD; } USBFS_TypeDef; -// TODO: Break host host-mode. +/* USB Host Mode */ + +typedef struct +{ + __IO uint8_t RESERVED0; + __IO uint8_t HOST_CTLR; // or host ctlr + __IO uint8_t RESERVED1; + __IO uint8_t RESERVED2; + __IO uint8_t RESERVED3; + __IO uint8_t RESERVED4; + __IO uint8_t RESERVED5; + __IO uint8_t RESERVED6; + __IO uint16_t RESERVED7; + __IO uint16_t RESERVED8; + __IO uint8_t RESERVED9; + __IO uint8_t HOST_EP_MOD; // Also HOST_EP_MOD + __IO uint8_t RESERVED10; + __IO uint8_t RESERVED11; + + __IO uint32_t RESERVED12; + __IO uint32_t RESERVED13; + __IO uint32_t HOST_RX_DMA; // Also HOST_RX_DMA + __IO uint32_t HOST_TX_DMA; // Also HOST_TX_DMA + + __IO uint16_t RESERVED14; + __IO uint16_t RESERVED15; + __IO uint16_t RESERVED16; + + __IO uint16_t HOST_SETUP; + __IO uint16_t HOST_EP_PID; + __IO uint16_t HOST_RX_CTL; + __IO uint16_t HOST_TX_LEN; + __IO uint16_t HOST_TX_CTL; + + __IO uint16_t RESERVED20; + __IO uint16_t RESERVED21; + + __IO uint32_t RESERVED22[8]; + + __IO uint32_t RESERVED23; + __IO uint32_t RESERVED24; + __IO uint32_t RESERVED25; + + __IO uint32_t RESERVED26; + + __IO uint16_t RESERVED27; + __IO uint16_t RESERVED28; + + __IO uint16_t RESERVED29; + __IO uint16_t RESERVED30; + + __IO uint16_t RESERVED31; + __IO uint16_t RESERVED32; + + __IO uint32_t RESERVED33; +} USBDH_TypeDef; + /* USB Power Delivery */ typedef struct @@ -2060,6 +2117,7 @@ typedef struct #define OPA ((OPACMP_TypeDef *)OPA_BASE) #define USBFS ((USBFS_TypeDef *)USBFS_BASE) #define USBPD ((USBPD_TypeDef *)USBPD_BASE) +#define USBDH ((USBDH_TypeDef *)USBFS_BASE) #endif #if defined(CH32V20x) || defined(CH32V30x) From 5f0474c8475fbd6c19023a2c28cb600e3db4db01 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Fri, 19 Apr 2024 05:05:17 -0700 Subject: [PATCH 06/31] Update 035 work, getting close to USB --- ch32v003fun/ch32v003fun.c | 36 ++--- ch32v003fun/ch32v003fun.h | 61 +++++---- ch32v003fun/ch32v003fun.mk | 2 +- examples_x035/sandbox/Makefile | 10 ++ examples_x035/sandbox/funconfig.h | 9 ++ examples_x035/sandbox/sandbox.c | 43 ++++++ examples_x035/usbdevice.incomplete/Makefile | 11 ++ examples_x035/usbdevice.incomplete/fsusb.c | 127 ++++++++++++++++++ examples_x035/usbdevice.incomplete/fsusb.h | 12 ++ .../usbdevice.incomplete/funconfig.h | 9 ++ .../usbdevice.incomplete/usbdevice.c | 51 +++++++ minichlink/pgm-wch-linke.c | 8 +- 12 files changed, 330 insertions(+), 49 deletions(-) create mode 100644 examples_x035/sandbox/Makefile create mode 100644 examples_x035/sandbox/funconfig.h create mode 100644 examples_x035/sandbox/sandbox.c create mode 100644 examples_x035/usbdevice.incomplete/Makefile create mode 100644 examples_x035/usbdevice.incomplete/fsusb.c create mode 100644 examples_x035/usbdevice.incomplete/fsusb.h create mode 100644 examples_x035/usbdevice.incomplete/funconfig.h create mode 100644 examples_x035/usbdevice.incomplete/usbdevice.c diff --git a/ch32v003fun/ch32v003fun.c b/ch32v003fun/ch32v003fun.c index 252899ea..5e59a986 100644 --- a/ch32v003fun/ch32v003fun.c +++ b/ch32v003fun/ch32v003fun.c @@ -840,7 +840,7 @@ void DMA2_Channel10_IRQHandler( void ) __attribute__((section(".text.vector_han void DMA2_Channel11_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); #endif -#if defined( CH32X03X ) +#if defined( CH32X03x) void USART2_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); void EXTI15_8_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); void EXTI25_16_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); @@ -940,23 +940,23 @@ void InterruptVectorDefault() .word TIM1_TRG_COM_IRQHandler /* TIM1 Trigger and Commutation */ \n\ .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ \n\ .word TIM2_IRQHandler /* TIM2 */ \n" -#if defined( CH32X03X ) -" .word USART2_IRQn = 39, /* UART2 Interrupt */ \n\ - .word EXTI15_8_IRQn = 40, /* External Line[8:15] Interrupt */ \n\ - .word EXTI25_16_IRQn = 41, /* External Line[25:16] Interrupt */ \n\ - .word USART3_IRQn = 42, /* UART2 Interrupt */ \n\ - .word USART4_IRQn = 43, /* UART2 Interrupt */ \n\ - .word DMA1_Channel8_IRQn = 44, /* DMA1 Channel 8 global Interrupt */ \n\ - .word USBFS_IRQn = 45, /* USB Full-Speed Interrupt */ \n\ - .word USBFS_WakeUp_IRQn = 46, /* USB Full-Speed Wake-Up Interrupt */ \n\ - .word PIOC_IRQn = 47, /* Programmable IO Controller Interrupt */ \n\ - .word OPA_IRQn = 48, /* Op Amp Interrupt */ \n\ - .word USBPD_IRQn = 49, /* USB Power Delivery Interrupt */ \n\ - .word USBPD_WKUP_IRQn = 50, /* USB Power Delivery Wake-Up Interrupt */ \n\ - .word TIM2_CC_IRQn = 51, /* Timer 2 Compare Global Interrupt */ \n\ - .word TIM2_TRG_IRQn = 52, /* Timer 2 Trigger Global Interrupt */ \n\ - .word TIM2_BRK_IRQn = 53, /* Timer 2 Brk Global Interrupt */ \n\ - .word TIM3_IRQn = 54, /* Timer 3 Global Interrupt */" +#if defined( CH32X03x ) +" .word USART2_IRQHandler /* UART2 Interrupt */ \n\ + .word EXTI15_8_IRQHandler /* External Line[8:15] Interrupt */ \n\ + .word EXTI25_16_IRQHandler /* External Line[25:16] Interrupt */ \n\ + .word USART3_IRQHandler /* UART2 Interrupt */ \n\ + .word USART4_IRQHandler /* UART2 Interrupt */ \n\ + .word DMA1_Channel8_IRQHandler /* DMA1 Channel 8 global Interrupt */ \n\ + .word USBFS_IRQHandler /* USB Full-Speed Interrupt */ \n\ + .word USBFS_WakeUp_IRQHandler /* USB Full-Speed Wake-Up Interrupt */ \n\ + .word PIOC_IRQHandler /* Programmable IO Controller Interrupt */ \n\ + .word OPA_IRQHandler /* Op Amp Interrupt */ \n\ + .word USBPD_IRQHandler /* USB Power Delivery Interrupt */ \n\ + .word USBPD_WKUP_IRQHandler /* USB Power Delivery Wake-Up Interrupt */ \n\ + .word TIM2_CC_IRQHandler /* Timer 2 Compare Global Interrupt */ \n\ + .word TIM2_TRG_IRQHandler /* Timer 2 Trigger Global Interrupt */ \n\ + .word TIM2_BRK_IRQHandler /* Timer 2 Brk Global Interrupt */ \n\ + .word TIM3_IRQHandler /* Timer 3 Global Interrupt */" #endif ); #endif diff --git a/ch32v003fun/ch32v003fun.h b/ch32v003fun/ch32v003fun.h index 931cfee4..d836f673 100644 --- a/ch32v003fun/ch32v003fun.h +++ b/ch32v003fun/ch32v003fun.h @@ -1700,8 +1700,8 @@ typedef struct /* USB Full Speed Device Mode */ typedef struct { - __IO uint8_t BASE_CTLR; - __IO uint8_t UDEV_CTLR; // or host ctlr + __IO uint8_t BASE_CTRL; //XXX (spelling) + __IO uint8_t UDEV_CTRL; // or host ctlr __IO uint8_t INT_EN; __IO uint8_t DEV_ADDR; __IO uint8_t RESERVED0; @@ -1720,25 +1720,25 @@ typedef struct __IO uint32_t UEP2_DMA; // Also HOST_RX_DMA __IO uint32_t UEP3_DMA; // Also HOST_TX_DMA - //__IO uint32_t UEP0_CTLR; + //__IO uint32_t UEP0_CTRL; __IO uint16_t UEP0_TX_LEN; - __IO uint16_t UEP0_CTLR_H; + __IO uint16_t UEP0_CTRL_H; - //__IO uint32_t UEP1_CTLR; + //__IO uint32_t UEP1_CTRL; __IO uint16_t UEP1_TX_LEN; - __IO uint16_t UEP1_CTLR_H; // Also HOST_SETUP + __IO uint16_t UEP1_CTRL_H; // Also HOST_SETUP - //__IO uint32_t UEP2_CTLR; + //__IO uint32_t UEP2_CTRL; __IO uint16_t UEP2_TX_LEN; // Also HOST_PID - __IO uint16_t UEP2_CTLR_H; // Also HOST_RX_CTL + __IO uint16_t UEP2_CTRL_H; // Also HOST_RX_CTL - //__IO uint32_t UEP3_CTLR; + //__IO uint32_t UEP3_CTRL; __IO uint16_t UEP3_TX_LEN; // Also HOST_TX_LEN - __IO uint16_t UEP3_CTLR_H; // Also HOST_TX_CTL + __IO uint16_t UEP3_CTRL_H; // Also HOST_TX_CTL - //__IO uint32_t UEP4_CTLR; + //__IO uint32_t UEP4_CTRL; __IO uint16_t UEP4_TX_LEN; - __IO uint16_t UEP4_CTLR_H; + __IO uint16_t UEP4_CTRL_H; __IO uint32_t RESERVED3[8]; @@ -1748,27 +1748,39 @@ typedef struct __IO uint32_t RESERVED4; - //__IO uint32_t UEP5_CTLR; + //__IO uint32_t UEP5_CTRL; __IO uint16_t UEP5_TX_LEN; - __IO uint16_t UEP5_CTLR_H; + __IO uint16_t UEP5_CTRL_H; - //__IO uint32_t UEP6_CTLR; + //__IO uint32_t UEP6_CTRL; __IO uint16_t UEP6_TX_LEN; - __IO uint16_t UEP6_CTLR_H; + __IO uint16_t UEP6_CTRL_H; - //__IO uint32_t UEP7_CTLR; + //__IO uint32_t UEP7_CTRL; __IO uint16_t UEP7_TX_LEN; - __IO uint16_t UEP7_CTLR_H; + __IO uint16_t UEP7_CTRL_H; __IO uint32_t UEPX_MOD; } USBFS_TypeDef; +#define USB_PHY_V33 (1<<6) +#define USB_IOEN (1<<7) + +#define UDP_PUE_00 (0b00<<2) +#define UDP_PUE_01 (0b01<<2) +#define UDP_PUE_10 (0b10<<2) +#define UDP_PUE_11 (0b11<<2) +#define UDM_PUE_00 (0b00<<0) +#define UDM_PUE_01 (0b01<<0) +#define UDM_PUE_10 (0b10<<0) +#define UDM_PUE_11 (0b11<<0) + /* USB Host Mode */ typedef struct { __IO uint8_t RESERVED0; - __IO uint8_t HOST_CTLR; // or host ctlr + __IO uint8_t HOST_CTRL; __IO uint8_t RESERVED1; __IO uint8_t RESERVED2; __IO uint8_t RESERVED3; @@ -1778,14 +1790,14 @@ typedef struct __IO uint16_t RESERVED7; __IO uint16_t RESERVED8; __IO uint8_t RESERVED9; - __IO uint8_t HOST_EP_MOD; // Also HOST_EP_MOD + __IO uint8_t HOST_EP_MOD; __IO uint8_t RESERVED10; __IO uint8_t RESERVED11; __IO uint32_t RESERVED12; __IO uint32_t RESERVED13; - __IO uint32_t HOST_RX_DMA; // Also HOST_RX_DMA - __IO uint32_t HOST_TX_DMA; // Also HOST_TX_DMA + __IO uint32_t HOST_RX_DMA; + __IO uint32_t HOST_TX_DMA; __IO uint16_t RESERVED14; __IO uint16_t RESERVED15; @@ -5517,6 +5529,8 @@ typedef struct #define RCC_FLITFEN ((uint16_t)0x0010) /* FLITF clock enable */ #define RCC_CRCEN ((uint16_t)0x0040) /* CRC clock enable */ #define RCC_USBHD ((uint16_t)0x1000) +#define RCC_USBFS ((uint16_t)0x1000) +#define RCC_USBPD ((uint16_t)0x20000) /****************** Bit definition for RCC_APB2PCENR register *****************/ #define RCC_AFIOEN ((uint32_t)0x00000001) /* Alternate Function I/O clock enable */ @@ -11077,7 +11091,8 @@ typedef struct #define USART_FLAG_FE ((uint16_t)0x0002) #define USART_FLAG_PE ((uint16_t)0x0001) -#if defined(CH32V10x) +// While not truly CH32X035, we can re-use some of the USB register defs. +#if defined(CH32V10x) | defined(CH32X03x) /* ch32v10x_usb.h ------------------------------------------------------------*/ #ifndef NULL diff --git a/ch32v003fun/ch32v003fun.mk b/ch32v003fun/ch32v003fun.mk index a4cbcb69..750c2850 100644 --- a/ch32v003fun/ch32v003fun.mk +++ b/ch32v003fun/ch32v003fun.mk @@ -58,7 +58,7 @@ else TARGET_MCU_LD:=1 else ifeq ($(findstring CH32X03,$(TARGET_MCU)),CH32X03) # CH32X033, X035 TARGET_MCU_PACKAGE?=CH32X035F8U6 - CFLAGS_ARCH+= -march=rv32imac \ + CFLAGS_ARCH+=-march=rv32imac \ -mabi=ilp32 \ -DCH32X03x=1 diff --git a/examples_x035/sandbox/Makefile b/examples_x035/sandbox/Makefile new file mode 100644 index 00000000..2b907ec5 --- /dev/null +++ b/examples_x035/sandbox/Makefile @@ -0,0 +1,10 @@ +all : flash + +TARGET:=sandbox +TARGET_MCU:=CH32X035 + +include ../../ch32v003fun/ch32v003fun.mk + +flash : cv_flash +clean : cv_clean + diff --git a/examples_x035/sandbox/funconfig.h b/examples_x035/sandbox/funconfig.h new file mode 100644 index 00000000..a8a70b30 --- /dev/null +++ b/examples_x035/sandbox/funconfig.h @@ -0,0 +1,9 @@ +#ifndef _FUNCONFIG_H +#define _FUNCONFIG_H + +// Though this should be on by default we can extra force it on. +#define FUNCONF_USE_DEBUGPRINTF 1 +#define FUNCONF_DEBUGPRINTF_TIMEOUT (1<<31) // Wait for a very very long time. + +#endif + diff --git a/examples_x035/sandbox/sandbox.c b/examples_x035/sandbox/sandbox.c new file mode 100644 index 00000000..c341d2fd --- /dev/null +++ b/examples_x035/sandbox/sandbox.c @@ -0,0 +1,43 @@ +/* Small example showing how to use the SWIO programming pin to + do printf through the debug interface */ + +#include "ch32v003fun.h" +#include + +uint32_t count; + +int last = 0; +void handle_debug_input( int numbytes, uint8_t * data ) +{ + last = data[0]; + count += numbytes; +} + +int main() +{ + SystemInit(); + + funGpioInitAll(); + + funPinMode( PA0, GPIO_CFGLR_OUT_10Mhz_PP ); + + printf( "%08x\n", &USBPD->DMA ); + + while(1); + +#if 0 + while(1) + { + GPIOA->BSHR = 1; // Turn on GPIOs + printf( "+%lu %lu\n", count++ ); + Delay_Ms(100); + int i; + for( i = 0; i < 10000; i++ ) + poll_input(); + GPIOA->BSHR = (1<<16); // Turn off GPIODs + printf( "-%lu[%c]\n", count++, last ); + Delay_Ms(100); + } +#endif +} + diff --git a/examples_x035/usbdevice.incomplete/Makefile b/examples_x035/usbdevice.incomplete/Makefile new file mode 100644 index 00000000..e28de11d --- /dev/null +++ b/examples_x035/usbdevice.incomplete/Makefile @@ -0,0 +1,11 @@ +all : flash + +TARGET:=usbdevice +TARGET_MCU:=CH32X035 +ADDITIONAL_C_FILES:=fsusb.c + +include ../../ch32v003fun/ch32v003fun.mk + +flash : cv_flash +clean : cv_clean + diff --git a/examples_x035/usbdevice.incomplete/fsusb.c b/examples_x035/usbdevice.incomplete/fsusb.c new file mode 100644 index 00000000..e522dd6d --- /dev/null +++ b/examples_x035/usbdevice.incomplete/fsusb.c @@ -0,0 +1,127 @@ +#include "fsusb.h" +#include "ch32v003fun.h" + +uint32_t USBDEBUG0, USBDEBUG1, USBDEBUG2; +uint8_t EP0_DATA[64] __attribute__((aligned(32))); + +void USBFS_IRQHandler() __attribute__((section(".text.vector_handler"))) __attribute__((interrupt)); + +#define CRB_U_IS_NAK (1<<7) +#define CTOG_MATCH_SYNC (1<<6) +#define CRB_U_SIE_FREE (1<<5) +#define CRB_UIF_FIFO_OV (1<<4) +#define CRB_UIF_HST_SOF (1<<3) +#define CRB_UIF_SUSPEND (1<<2) +#define CRB_UIF_TRANSFER (1<<1) +#define CRB_UIF_BUS_RST (1<<0) +#define CSETUP_ACT (1<<15) +#define CRB_UIS_TOG_OK (1<<14) +#define CMASK_UIS_TOKEN (3<<12) +#define CMASK_UIS_ENDP (0xf<<8) + +#define CUIS_TOKEN_OUT 0x0 +#define CUIS_TOKEN_SOF 0x1 +#define CUIS_TOKEN_IN 0x2 +#define CUIS_TOKEN_SETUP 0x3 + +void USBFS_IRQHandler() +{ + // Combined FG + ST flag. + uint16_t intfgst = *(uint16_t*)(&USBFSD->INT_FG); + + GPIOA->BSHR = 1; + + // TODO: Check if needs to be do-while to re-check. + + + if( intfgst & CRB_UIF_TRANSFER ) + { + switch ( ( intfgst & CMASK_UIS_TOKEN) >> 12) + { + case CUIS_TOKEN_IN: + switch ( intst & ( USBFS_UIS_TOKEN_M + +/* while( ( flags = USBFS->INT_FG & 0x9f ) ) + { + if( flags & RB_UIF_TRANSFER ) + { + // Handle transfer. + USBDEBUG0++; + } + if( flags & RB_UIF_BUS_RST ) + { + // Handle transfer. + USBDEBUG0+=1000; + } + //USBDEBUG0 = USBFS->INT_FG; + USBFS->INT_FG = flags; + } +*/ + + *(uint16_t*)(&USBFSD->INT_FG) = intfgst; + //intfgst = *(uint16_t*)(&USBFSD->INT_FG); + GPIOA->BSHR = 1<<16; +} + +void USBFS_Poll() +{ + USBDEBUG2 = USBFS->INT_ST;//EP0_DATA[1]; + USBDEBUG1 = USBFS->MIS_ST; +} + +int FSUSBSetup() +{ + RCC->APB2PCENR |= RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOC; + RCC->AHBPCENR |= RCC_USBFS; + + NVIC_EnableIRQ( USBFS_IRQn ); + + AFIO->CTLR |= USB_PHY_V33; + + USBFS->BASE_CTRL = RB_UC_RESET_SIE | RB_UC_CLR_ALL; + USBFS->BASE_CTRL = RB_UC_DEV_PU_EN | RB_UC_INT_BUSY | RB_UC_DMA_EN; + + // Enter device mode. + USBFS->INT_EN = RB_UIE_SUSPEND | RB_UIE_TRANSFER | RB_UIE_BUS_RST; + USBFS->UEP4_1_MOD = 0; + USBFS->UEP2_3_MOD = 0; + USBFS->UEP567_MOD = 0; + USBFS->UEP0_DMA = ((intptr_t)EP0_DATA) & 0x7fff; + USBFS->DEV_ADDR = 0x00; + USBFS->UDEV_CTRL = RB_UD_PD_DIS | RB_UD_PORT_EN; + + // Go on-bus. + + // From the TRM: + // + // USB multiplexing IO pins enable: + // + // Enabling USB requires, in addition to USB_IOEN set to + // 1, the setting of: MODE=0 in GPIO configuration register + // GPIOC_CFGXR corresponding to PC16 and PC17 to + // select the input mode. + // + // for USB device, CNF=10 corresponding to PC17 to select + // the input mode with up and down For USB devices, PC17 + // corresponding to CNF=10 selects the input mode with up + // and down pull, PC17 corresponding to bit 1 in + // GPIOC_OUTDR selects the up pull, and PC16 + // corresponding to CNF=01 selects the floating input. + + + AFIO->CTLR = (AFIO->CTLR & ~(UDP_PUE_11 | UDM_PUE_11 )) | USB_PHY_V33 | USB_IOEN | UDP_PUE_11; //1.5k pullup + + // Enable PC16/17 Alternate Function (USB) + // According to EVT, GPIO16 = GPIO_Mode_IN_FLOATING, GPIO17 = GPIO_Mode_IPU + GPIOC->CFGXR &= ~(0xf<<(4*0)); + GPIOC->CFGXR |= (GPIO_CFGLR_IN_FLOAT)<<(4*0); // MSBs are CNF, LSBs are MODE + GPIOC->CFGXR &= ~(0xf<<(4*1)); + GPIOC->CFGXR |= (GPIO_CFGLR_IN_PUPD)<<(4*1); + GPIOC->BSXR = 1<<1; // PC17 on. + + USBFS->UDEV_CTRL = RB_UD_PORT_EN; + + // Go on-bus. + return 0; +} + diff --git a/examples_x035/usbdevice.incomplete/fsusb.h b/examples_x035/usbdevice.incomplete/fsusb.h new file mode 100644 index 00000000..76f794e4 --- /dev/null +++ b/examples_x035/usbdevice.incomplete/fsusb.h @@ -0,0 +1,12 @@ +#ifndef _FSUSB_H +#define _FSUSB_H + +#include + +extern uint32_t USBDEBUG0, USBDEBUG1, USBDEBUG2; + +int FSUSBSetup(); +void USBFS_Poll(); + +#endif + diff --git a/examples_x035/usbdevice.incomplete/funconfig.h b/examples_x035/usbdevice.incomplete/funconfig.h new file mode 100644 index 00000000..a8a70b30 --- /dev/null +++ b/examples_x035/usbdevice.incomplete/funconfig.h @@ -0,0 +1,9 @@ +#ifndef _FUNCONFIG_H +#define _FUNCONFIG_H + +// Though this should be on by default we can extra force it on. +#define FUNCONF_USE_DEBUGPRINTF 1 +#define FUNCONF_DEBUGPRINTF_TIMEOUT (1<<31) // Wait for a very very long time. + +#endif + diff --git a/examples_x035/usbdevice.incomplete/usbdevice.c b/examples_x035/usbdevice.incomplete/usbdevice.c new file mode 100644 index 00000000..2dbd754c --- /dev/null +++ b/examples_x035/usbdevice.incomplete/usbdevice.c @@ -0,0 +1,51 @@ +/* Small example showing how to use the SWIO programming pin to + do printf through the debug interface */ + +#include "ch32v003fun.h" +#include +#include "fsusb.h" + +uint32_t count; + +int last = 0; +void handle_debug_input( int numbytes, uint8_t * data ) +{ + last = data[0]; + count += numbytes; +} + +int main() +{ + SystemInit(); + + funGpioInitAll(); + + funPinMode( PA0, GPIO_CFGLR_OUT_10Mhz_PP ); + + FSUSBSetup(); + + +void USBFS_IRQHandler(); +//extern int USBFS_IRQHandler; + while(1) + { + printf( "%lu %lu %lu\n", USBDEBUG0, USBDEBUG1, USBDEBUG2 ); + USBFS_Poll(); + } + +#if 0 + while(1) + { + GPIOA->BSHR = 1; // Turn on GPIOs + printf( "+%lu %lu\n", count++ ); + Delay_Ms(100); + int i; + for( i = 0; i < 10000; i++ ) + poll_input(); + GPIOA->BSHR = (1<<16); // Turn off GPIODs + printf( "-%lu[%c]\n", count++, last ); + Delay_Ms(100); + } +#endif +} + diff --git a/minichlink/pgm-wch-linke.c b/minichlink/pgm-wch-linke.c index 68352980..f674f0f7 100644 --- a/minichlink/pgm-wch-linke.c +++ b/minichlink/pgm-wch-linke.c @@ -421,7 +421,7 @@ static int LESetupInterface( void * d ) return -1; } int flash_size = (rbuff[2]<<8) | rbuff[3]; - fprintf( stderr, "Flash Storage: %d kB\n", flash_size ); // Is this Flash size? + fprintf( stderr, "Flash Storage: %d kB\n", flash_size ); fprintf( stderr, "Part UUID : %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n", rbuff[4], rbuff[5], rbuff[6], rbuff[7], rbuff[8], rbuff[9], rbuff[10], rbuff[11] ); fprintf( stderr, "PFlags : %02x-%02x-%02x-%02x\n", rbuff[12], rbuff[13], rbuff[14], rbuff[15] ); fprintf( stderr, "Part Type (B): %02x-%02x-%02x-%02x\n", rbuff[16], rbuff[17], rbuff[18], rbuff[19] ); @@ -806,12 +806,6 @@ static int LEWriteBinaryBlob( void * d, uint32_t address_to_write, uint32_t len, } } - uint32_t rr; - int r = MCF.ReadReg32( d, DMABSTRACTCS, &rr ); - printf( "PLX HALT %08x %d\n", rr, r ); - - r = MCF.ReadReg32( d, DMSTATUS, &rr ); - printf( "PLX HALT %08x %d\n", rr, r ); return 0; } From 76c99a6a6c64456dfa4cbf176cc0b9b1c60ecf29 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sat, 20 Apr 2024 05:54:40 -0400 Subject: [PATCH 07/31] Progress but still no go --- examples_x035/usbdevice.incomplete/Makefile | 2 +- .../usbdevice.incomplete/descriptor.c | 266 +++++++ .../usbdevice.incomplete/descriptor.h | 92 +++ examples_x035/usbdevice.incomplete/fsusb.c | 717 +++++++++++++++++- examples_x035/usbdevice.incomplete/fsusb.h | 369 +++++++++ 5 files changed, 1413 insertions(+), 33 deletions(-) create mode 100644 examples_x035/usbdevice.incomplete/descriptor.c create mode 100644 examples_x035/usbdevice.incomplete/descriptor.h diff --git a/examples_x035/usbdevice.incomplete/Makefile b/examples_x035/usbdevice.incomplete/Makefile index e28de11d..adabf99a 100644 --- a/examples_x035/usbdevice.incomplete/Makefile +++ b/examples_x035/usbdevice.incomplete/Makefile @@ -2,7 +2,7 @@ all : flash TARGET:=usbdevice TARGET_MCU:=CH32X035 -ADDITIONAL_C_FILES:=fsusb.c +ADDITIONAL_C_FILES:=fsusb.c descriptor.c include ../../ch32v003fun/ch32v003fun.mk diff --git a/examples_x035/usbdevice.incomplete/descriptor.c b/examples_x035/usbdevice.incomplete/descriptor.c new file mode 100644 index 00000000..2d1b2f6d --- /dev/null +++ b/examples_x035/usbdevice.incomplete/descriptor.c @@ -0,0 +1,266 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : composite_km_desc.h + * Author : WCH + * Version : V1.0.0 + * Date : 2023/04/06 + * Description : All descriptors for the keyboard and mouse composite device. +********************************************************************************* +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* Attention: This software (modified or not) and binary are used for +* microcontroller manufactured by Nanjing Qinheng Microelectronics. +*******************************************************************************/ + + +/*******************************************************************************/ +/* Header File */ +#include "descriptor.h" + +/*******************************************************************************/ +/* Device Descriptor */ +const uint8_t MyDevDescr[ ] = +{ + 0x12, // bLength + 0x01, // bDescriptorType + 0x00, 0x02, // bcdUSB + 0x00, // bDeviceClass + 0x00, // bDeviceSubClass + 0x00, // bDeviceProtocol + DEF_USBD_UEP0_SIZE, // bMaxPacketSize0 + (uint8_t)DEF_USB_VID, (uint8_t)( DEF_USB_VID >> 8 ), // idVendor + (uint8_t)DEF_USB_PID, (uint8_t)( DEF_USB_PID >> 8 ), // idProduct + 0x00, DEF_IC_PRG_VER, // bcdDevice + 0x01, // iManufacturer + 0x02, // iProduct + 0x03, // iSerialNumber + 0x01, // bNumConfigurations +}; + +/* Configuration Descriptor Set */ +const uint8_t MyCfgDescr[ ] = +{ + /* Configuration Descriptor */ + 0x09, // bLength + 0x02, // bDescriptorType + 0x3B, 0x00, // wTotalLength + 0x02, // bNumInterfaces + 0x01, // bConfigurationValue + 0x00, // iConfiguration + 0xA0, // bmAttributes: Bus Powered; Remote Wakeup + 0x32, // MaxPower: 100mA + + /* Interface Descriptor (Keyboard) */ + 0x09, // bLength + 0x04, // bDescriptorType + 0x00, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x01, // bNumEndpoints + 0x03, // bInterfaceClass + 0x01, // bInterfaceSubClass + 0x01, // bInterfaceProtocol: Keyboard + 0x00, // iInterface + + /* HID Descriptor (Keyboard) */ + 0x09, // bLength + 0x21, // bDescriptorType + 0x11, 0x01, // bcdHID + 0x00, // bCountryCode + 0x01, // bNumDescriptors + 0x22, // bDescriptorType + 0x3E, 0x00, // wDescriptorLength + + /* Endpoint Descriptor (Keyboard) */ + 0x07, // bLength + 0x05, // bDescriptorType + 0x81, // bEndpointAddress: IN Endpoint 1 + 0x03, // bmAttributes + 0x08, 0x00, // wMaxPacketSize + 0x0A, // bInterval: 10mS + + /* Interface Descriptor (Mouse) */ + 0x09, // bLength + 0x04, // bDescriptorType + 0x01, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x01, // bNumEndpoints + 0x03, // bInterfaceClass + 0x01, // bInterfaceSubClass + 0x02, // bInterfaceProtocol: Mouse + 0x00, // iInterface + + /* HID Descriptor (Mouse) */ + 0x09, // bLength + 0x21, // bDescriptorType + 0x10, 0x01, // bcdHID + 0x00, // bCountryCode + 0x01, // bNumDescriptors + 0x22, // bDescriptorType + 0x34, 0x00, // wDescriptorLength + + /* Endpoint Descriptor (Mouse) */ + 0x07, // bLength + 0x05, // bDescriptorType + 0x82, // bEndpointAddress: IN Endpoint 2 + 0x03, // bmAttributes + 0x08, 0x00, // wMaxPacketSize + 0x01 // bInterval: 1mS +}; + +/* Keyboard Report Descriptor */ +const uint8_t KeyRepDesc[ ] = +{ + 0x05, 0x01, // Usage Page (Generic Desktop) + 0x09, 0x06, // Usage (Keyboard) + 0xA1, 0x01, // Collection (Application) + 0x05, 0x07, // Usage Page (Key Codes) + 0x19, 0xE0, // Usage Minimum (224) + 0x29, 0xE7, // Usage Maximum (231) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x08, // Report Count (8) + 0x81, 0x02, // Input (Data,Variable,Absolute) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x01, // Input (Constant) + 0x95, 0x03, // Report Count (3) + 0x75, 0x01, // Report Size (1) + 0x05, 0x08, // Usage Page (LEDs) + 0x19, 0x01, // Usage Minimum (1) + 0x29, 0x03, // Usage Maximum (3) + 0x91, 0x02, // Output (Data,Variable,Absolute) + 0x95, 0x05, // Report Count (5) + 0x75, 0x01, // Report Size (1) + 0x91, 0x01, // Output (Constant,Array,Absolute) + 0x95, 0x06, // Report Count (6) + 0x75, 0x08, // Report Size (8) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x05, 0x07, // Usage Page (Key Codes) + 0x19, 0x00, // Usage Minimum (0) + 0x29, 0x91, // Usage Maximum (145) + 0x81, 0x00, // Input(Data,Array,Absolute) + 0xC0 // End Collection +}; + +/* Mouse Report Descriptor */ +const uint8_t MouseRepDesc[ ] = +{ + 0x05, 0x01, // Usage Page (Generic Desktop) + 0x09, 0x02, // Usage (Mouse) + 0xA1, 0x01, // Collection (Application) + 0x09, 0x01, // Usage (Pointer) + 0xA1, 0x00, // Collection (Physical) + 0x05, 0x09, // Usage Page (Button) + 0x19, 0x01, // Usage Minimum (Button 1) + 0x29, 0x03, // Usage Maximum (Button 3) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x03, // Report Count (3) + 0x81, 0x02, // Input (Data,Variable,Absolute) + 0x75, 0x05, // Report Size (5) + 0x95, 0x01, // Report Count (1) + 0x81, 0x01, // Input (Constant,Array,Absolute) + 0x05, 0x01, // Usage Page (Generic Desktop) + 0x09, 0x30, // Usage (X) + 0x09, 0x31, // Usage (Y) + 0x09, 0x38, // Usage (Wheel) + 0x15, 0x81, // Logical Minimum (-127) + 0x25, 0x7F, // Logical Maximum (127) + 0x75, 0x08, // Report Size (8) + 0x95, 0x03, // Report Count (3) + 0x81, 0x06, // Input (Data,Variable,Relative) + 0xC0, // End Collection + 0xC0 // End Collection +}; + +/* Qualifier Descriptor */ +const uint8_t MyQuaDesc[ ] = +{ + 0x0A, // bLength + 0x06, // bDescriptorType + 0x00, 0x02, // bcdUSB + 0x00, // bDeviceClass + 0x00, // bDeviceSubClass + 0x00, // bDeviceProtocol + 0x40, // bMaxPacketSize0 + 0x00, // bNumConfigurations + 0x00 // bReserved +}; + +/* Language Descriptor */ +const uint8_t MyLangDescr[ ] = +{ + 0x04, + 0x03, + 0x09, + 0x04 +}; + +/* Manufacturer Descriptor */ +const uint8_t MyManuInfo[ ] = +{ + 0x0E, + 0x03, + 'w', + 0, + 'c', + 0, + 'h', + 0, + '.', + 0, + 'c', + 0, + 'n', + 0 +}; + +/* Product Information */ +const uint8_t MyProdInfo[ ] = +{ + 0x12, + 0x03, + 'C', + 0, + 'H', + 0, + '3', + 0, + '2', + 0, + 'x', + 0, + '0', + 0, + '3', + 0, + '5', + 0 +}; + +/* Serial Number Information */ +const uint8_t MySerNumInfo[ ] = +{ + 0x16, + 0x03, + '0', + 0, + '1', + 0, + '2', + 0, + '3', + 0, + '4', + 0, + '5', + 0, + '6', + 0, + '7', + 0, + '8', + 0, + '9', + 0 +}; diff --git a/examples_x035/usbdevice.incomplete/descriptor.h b/examples_x035/usbdevice.incomplete/descriptor.h new file mode 100644 index 00000000..b746eecf --- /dev/null +++ b/examples_x035/usbdevice.incomplete/descriptor.h @@ -0,0 +1,92 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : usbd_descriptor.h + * Author : WCH + * Version : V1.0.0 + * Date : 2023/04/06 + * Description : All descriptors for the keyboard and mouse composite device. +********************************************************************************* +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* Attention: This software (modified or not) and binary are used for +* microcontroller manufactured by Nanjing Qinheng Microelectronics. +*******************************************************************************/ + + +#ifndef __USBD_DESC_H +#define __USBD_DESC_H + +/*******************************************************************************/ +/* Header File */ +#include "stdint.h" + +/*******************************************************************************/ +/* Macro Definition */ + +/* File Version */ +#define DEF_FILE_VERSION 0x01 + +/* USB Device Info */ +#define DEF_USB_VID 0x1A86 +#define DEF_USB_PID 0xFE00 + +/* USB Device Descriptor, Device Serial Number(bcdDevice) */ +#define DEF_IC_PRG_VER DEF_FILE_VERSION + +/* USB Device Endpoint Size */ +#define DEF_USBD_UEP0_SIZE 64 /* usb hs/fs device end-point 0 size */ +/* HS */ +#define DEF_USBD_HS_PACK_SIZE 512 /* usb hs device max bluk/int pack size */ +#define DEF_USBD_HS_ISO_PACK_SIZE 1024 /* usb hs device max iso pack size */ +/* FS */ +#define DEF_USBD_FS_PACK_SIZE 64 /* usb fs device max bluk/int pack size */ +#define DEF_USBD_FS_ISO_PACK_SIZE 1023 /* usb fs device max iso pack size */ +/* LS */ +#define DEf_USBD_LS_UEP0_SIZE 8 /* usb ls device end-point 0 size */ +#define DEF_USBD_LS_PACK_SIZE 64 /* usb ls device max int pack size */ + +/* USB Device Endpoint1-6 Size */ +/* HS */ +#define DEF_USB_EP1_HS_SIZE DEF_USBD_HS_PACK_SIZE +#define DEF_USB_EP2_HS_SIZE DEF_USBD_HS_PACK_SIZE +#define DEF_USB_EP3_HS_SIZE DEF_USBD_HS_PACK_SIZE +#define DEF_USB_EP4_HS_SIZE DEF_USBD_HS_PACK_SIZE +#define DEF_USB_EP5_HS_SIZE DEF_USBD_HS_PACK_SIZE +#define DEF_USB_EP6_HS_SIZE DEF_USBD_HS_PACK_SIZE +/* FS */ +#define DEF_USB_EP1_FS_SIZE DEF_USBD_FS_PACK_SIZE +#define DEF_USB_EP2_FS_SIZE DEF_USBD_FS_PACK_SIZE +#define DEF_USB_EP3_FS_SIZE DEF_USBD_FS_PACK_SIZE +#define DEF_USB_EP4_FS_SIZE DEF_USBD_FS_PACK_SIZE +#define DEF_USB_EP5_FS_SIZE DEF_USBD_FS_PACK_SIZE +#define DEF_USB_EP6_FS_SIZE DEF_USBD_FS_PACK_SIZE +/* LS */ +/* ... */ + +/* USB Device Descriptor Length */ +/* Note: If a descriptor does not exist, set the length to 0. */ +#define DEF_USBD_DEVICE_DESC_LEN ( (uint16_t)MyDevDescr[ 0 ] ) +#define DEF_USBD_CONFIG_DESC_LEN ( (uint16_t)MyCfgDescr[ 2 ] + ( (uint16_t)MyCfgDescr[ 3 ] << 8 ) ) +#define DEF_USBD_REPORT_DESC_LEN_KB 0x3E +#define DEF_USBD_REPORT_DESC_LEN_MS 0x34 +#define DEF_USBD_LANG_DESC_LEN ( (uint16_t)MyLangDescr[ 0 ] ) +#define DEF_USBD_MANU_DESC_LEN ( (uint16_t)MyManuInfo[ 0 ] ) +#define DEF_USBD_PROD_DESC_LEN ( (uint16_t)MyProdInfo[ 0 ] ) +#define DEF_USBD_SN_DESC_LEN ( (uint16_t)MySerNumInfo[ 0 ] ) +#define DEF_USBD_QUALFY_DESC_LEN ( (uint16_t)MyQuaDesc[ 0 ]) +#define DEF_USBD_BOS_DESC_LEN 0 +#define DEF_USBD_FS_OTH_DESC_LEN 0 +#define DEF_USBD_HS_OTH_DESC_LEN 0 + + +/*******************************************************************************/ +/* Descriptor Declaration */ +extern const uint8_t MyDevDescr[ ]; +extern const uint8_t MyCfgDescr[ ]; +extern const uint8_t KeyRepDesc[ ]; +extern const uint8_t MouseRepDesc[ ]; +extern const uint8_t MyQuaDesc[ ]; +extern const uint8_t MyLangDescr[ ]; +extern const uint8_t MyManuInfo[ ]; +extern const uint8_t MyProdInfo[ ]; +extern const uint8_t MySerNumInfo[ ]; + +#endif diff --git a/examples_x035/usbdevice.incomplete/fsusb.c b/examples_x035/usbdevice.incomplete/fsusb.c index e522dd6d..b135c163 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.c +++ b/examples_x035/usbdevice.incomplete/fsusb.c @@ -1,12 +1,29 @@ #include "fsusb.h" #include "ch32v003fun.h" +#include uint32_t USBDEBUG0, USBDEBUG1, USBDEBUG2; -uint8_t EP0_DATA[64] __attribute__((aligned(32))); -void USBFS_IRQHandler() __attribute__((section(".text.vector_handler"))) __attribute__((interrupt)); -#define CRB_U_IS_NAK (1<<7) +// based on https://github.com/openwch/ch32x035/tree/main/EVT/EXAM/USB/USBFS/DEVICE/CompositeKM/User + +#define DEF_USBD_UEP0_SIZE 64 /* usb hs/fs device end-point 0 size */ +#define EP_SIZE 64 + +#define DEF_UEP_IN 0x80 +#define DEF_UEP_OUT 0x00 + +#define DEF_UEP0 0 +#define DEF_UEP1 1 +#define DEF_UEP2 2 +#define DEF_UEP3 3 +#define DEF_UEP4 4 +#define DEF_UEP5 5 +#define DEF_UEP6 6 +#define DEF_UEP7 7 +#define NUM_EP 8 + +#define CRB_U_IS_NAK (1<<7) #define CTOG_MATCH_SYNC (1<<6) #define CRB_U_SIE_FREE (1<<5) #define CRB_UIF_FIFO_OV (1<<4) @@ -14,55 +31,692 @@ void USBFS_IRQHandler() __attribute__((section(".text.vector_handler"))) __attr #define CRB_UIF_SUSPEND (1<<2) #define CRB_UIF_TRANSFER (1<<1) #define CRB_UIF_BUS_RST (1<<0) -#define CSETUP_ACT (1<<15) +#define CSETUP_ACT (1<<15) #define CRB_UIS_TOG_OK (1<<14) #define CMASK_UIS_TOKEN (3<<12) #define CMASK_UIS_ENDP (0xf<<8) -#define CUIS_TOKEN_OUT 0x0 -#define CUIS_TOKEN_SOF 0x1 -#define CUIS_TOKEN_IN 0x2 -#define CUIS_TOKEN_SETUP 0x3 +#define CUSBFS_UIS_ENDP_MASK 0x0 + +#define CUIS_TOKEN_OUT 0x0 +#define CUIS_TOKEN_SOF 0x1 +#define CUIS_TOKEN_IN 0x2 +#define CUIS_TOKEN_SETUP 0x3 + + +// Hardware specific + +/* R8_USB_CTRL */ +#define USBFS_UC_HOST_MODE 0x80 +#define USBFS_UC_LOW_SPEED 0x40 +#define USBFS_UC_DEV_PU_EN 0x20 +#define USBFS_UC_SYS_CTRL_MASK 0x30 +#define USBFS_UC_SYS_CTRL0 0x00 +#define USBFS_UC_SYS_CTRL1 0x10 +#define USBFS_UC_SYS_CTRL2 0x20 +#define USBFS_UC_SYS_CTRL3 0x30 +#define USBFS_UC_INT_BUSY 0x08 +#define USBFS_UC_RESET_SIE 0x04 +#define USBFS_UC_CLR_ALL 0x02 +#define USBFS_UC_DMA_EN 0x01 + +/* R8_USB_INT_EN */ +#define USBFS_UIE_DEV_SOF 0x80 +#define USBFS_UIE_DEV_NAK 0x40 +#define USBFS_UIE_FIFO_OV 0x10 +#define USBFS_UIE_HST_SOF 0x08 +#define USBFS_UIE_SUSPEND 0x04 +#define USBFS_UIE_TRANSFER 0x02 +#define USBFS_UIE_DETECT 0x01 +#define USBFS_UIE_BUS_RST 0x01 + +/* R8_USB_DEV_AD */ +#define USBFS_UDA_GP_BIT 0x80 +#define USBFS_USB_ADDR_MASK 0x7F + +/* R8_USB_MIS_ST */ +#define USBFS_UMS_SOF_PRES 0x80 +#define USBFS_UMS_SOF_ACT 0x40 +#define USBFS_UMS_SIE_FREE 0x20 +#define USBFS_UMS_R_FIFO_RDY 0x10 +#define USBFS_UMS_BUS_RESET 0x08 +#define USBFS_UMS_SUSPEND 0x04 +#define USBFS_UMS_DM_LEVEL 0x02 +#define USBFS_UMS_DEV_ATTACH 0x01 + +// XXX TODO: Put these in a struct. + +/* Setup Request */ +volatile uint8_t USBFS_SetupReqCode; +volatile uint8_t USBFS_SetupReqType; +volatile uint16_t USBFS_SetupReqValue; +volatile uint16_t USBFS_SetupReqIndex; +volatile uint16_t USBFS_SetupReqLen; + +/* USB Device Status */ +volatile uint8_t USBFS_DevConfig; +volatile uint8_t USBFS_DevAddr; +volatile uint8_t USBFS_DevSleepStatus; +volatile uint8_t USBFS_DevEnumStatus; + +/* Endpoint Buffer */ +__attribute__ ((aligned(4))) uint8_t USBFS_EP0_Buf[64]; +__attribute__ ((aligned(4))) uint8_t USBFS_EP1_Buf[64]; +__attribute__ ((aligned(4))) uint8_t USBFS_EP2_Buf[64]; +__attribute__ ((aligned(4))) uint8_t USBFS_EP0_4Buf[ DEF_USBD_UEP0_SIZE*2 ]; //ep0_4(64) + +int USBFS_HidIdle[2]; +int USBFS_HidProtocol[2]; + +const uint8_t *pUSBFS_Descr; + +/* USB IN Endpoint Busy Flag */ +volatile uint8_t USBFS_Endp_Busy[NUM_EP]; + + + + +void USBFS_IRQHandler() __attribute__((section(".text.vector_handler"))) __attribute__((interrupt)); + + void USBFS_IRQHandler() { + // Based on https://github.com/openwch/ch32x035/blob/main/EVT/EXAM/USB/USBFS/DEVICE/CompositeKM/User/ch32x035_usbfs_device.c + // Combined FG + ST flag. - uint16_t intfgst = *(uint16_t*)(&USBFSD->INT_FG); + uint16_t intfgst = *(uint16_t*)(&USBFS->INT_FG); + int len = 0, errflag = 0; GPIOA->BSHR = 1; // TODO: Check if needs to be do-while to re-check. + if( intfgst & CRB_UIF_TRANSFER ) + { + int token = ( intfgst & CMASK_UIS_TOKEN) >> 12; + int ep = intfgst & CUSBFS_UIS_ENDP_MASK; + switch ( token ) + { + case CUIS_TOKEN_IN: + switch( ep ) + { + /* end-point 0 data in interrupt */ + case DEF_UEP0: + if( USBFS_SetupReqLen == 0 ) + { + USBFS->UEP0_CTRL_H = USBFS_UEP_R_TOG | USBFS_UEP_R_RES_ACK; + } + if ( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) + { + /* Non-standard request endpoint 0 Data upload */ + } + else + { + switch( USBFS_SetupReqCode ) + { + case USB_GET_DESCRIPTOR: + len = USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen; + memcpy( USBFS_EP0_Buf, pUSBFS_Descr, len ); + USBFS_SetupReqLen -= len; + pUSBFS_Descr += len; + USBFS->UEP0_TX_LEN = len; + USBFS->UEP0_CTRL_H ^= USBFS_UEP_T_TOG; + break; - if( intfgst & CRB_UIF_TRANSFER ) - { - switch ( ( intfgst & CMASK_UIS_TOKEN) >> 12) - { - case CUIS_TOKEN_IN: - switch ( intst & ( USBFS_UIS_TOKEN_M + case USB_SET_ADDRESS: + USBFS->DEV_ADDR = ( USBFS->DEV_ADDR & USBFS_UDA_GP_BIT ) | USBFS_DevAddr; + break; + + default: + break; + } + } + break; + + /* end-point 1 data in interrupt */ + case DEF_UEP1: + USBFS->UEP1_CTRL_H = ( USBFS->UEP1_CTRL_H & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_NAK; + USBFS->UEP1_CTRL_H ^= USBFS_UEP_T_TOG; + USBFS_Endp_Busy[ DEF_UEP1 ] = 0; + break; + + /* end-point 2 data in interrupt */ + case DEF_UEP2: + USBFS->UEP2_CTRL_H = ( USBFS->UEP2_CTRL_H & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_NAK; + USBFS->UEP2_CTRL_H ^= USBFS_UEP_T_TOG; + USBFS_Endp_Busy[ DEF_UEP2 ] = 0; + break; + + default : + break; + } + break; + + /* data-out stage processing */ + case CUIS_TOKEN_OUT: + switch( ep ) + { + /* end-point 0 data out interrupt */ + case DEF_UEP0: + if( intfgst & CRB_UIS_TOG_OK ) + { + if( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) + { + if( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) == USB_REQ_TYP_CLASS ) + { + switch( USBFS_SetupReqCode ) + { + case HID_SET_REPORT: + //KB_LED_Cur_Status = USBFS_EP0_Buf[ 0 ]; + // Do stuff... + USBFS_SetupReqLen = 0; + break; + default: + break; + } + } + } + else + { + /* Standard request end-point 0 Data download */ + /* Add your code here */ + } + } + if( USBFS_SetupReqLen == 0 ) + { + USBFS->UEP0_TX_LEN = 0; + USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK; + } + break; + + default: + break; + } + break; + + /* Setup stage processing */ + case CUIS_TOKEN_SETUP: + USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG|USBFS_UEP_T_RES_NAK|USBFS_UEP_R_TOG|USBFS_UEP_R_RES_NAK; + + + /* Store All Setup Values */ + USBFS_SetupReqType = pUSBFS_SetupReqPak->bRequestType; + USBFS_SetupReqCode = pUSBFS_SetupReqPak->bRequest; + USBFS_SetupReqLen = pUSBFS_SetupReqPak->wLength; + USBFS_SetupReqValue = pUSBFS_SetupReqPak->wValue; + USBFS_SetupReqIndex = pUSBFS_SetupReqPak->wIndex; + len = 0; + errflag = 0; + + if( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) + { + if( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) == USB_REQ_TYP_CLASS ) + { + /* Class Request */ + switch( USBFS_SetupReqCode ) + { + case HID_SET_REPORT: + break; + + case HID_SET_IDLE: + if( USBFS_SetupReqIndex == 0x00 ) + { + USBFS_HidIdle[ 0 ] = (uint8_t)( USBFS_SetupReqValue >> 8 ); + } + else if( USBFS_SetupReqIndex == 0x01 ) + { + USBFS_HidIdle[ 1 ] = (uint8_t)( USBFS_SetupReqValue >> 8 ); + } + else + { + errflag = 0xFF; + } + break; + + case HID_SET_PROTOCOL: + if( USBFS_SetupReqIndex == 0x00 ) + { + USBFS_HidProtocol[ 0 ] = (uint8_t)USBFS_SetupReqValue; + } + else if( USBFS_SetupReqIndex == 0x01 ) + { + USBFS_HidProtocol[ 1 ] = (uint8_t)USBFS_SetupReqValue; + } + else + { + errflag = 0xFF; + } + break; + + case HID_GET_IDLE: + if( USBFS_SetupReqIndex == 0x00 ) + { + USBFS_EP0_Buf[ 0 ] = USBFS_HidIdle[ 0 ]; + len = 1; + } + else if( USBFS_SetupReqIndex == 0x01 ) + { + USBFS_EP0_Buf[ 0 ] = USBFS_HidIdle[ 1 ]; + len = 1; + } + else + { + errflag = 0xFF; + } + break; + + case HID_GET_PROTOCOL: + if( USBFS_SetupReqIndex == 0x00 ) + { + USBFS_EP0_Buf[ 0 ] = USBFS_HidProtocol[ 0 ]; + len = 1; + } + else if( USBFS_SetupReqIndex == 0x01 ) + { + USBFS_EP0_Buf[ 0 ] = USBFS_HidProtocol[ 1 ]; + len = 1; + } + else + { + errflag = 0xFF; + } + break; -/* while( ( flags = USBFS->INT_FG & 0x9f ) ) + default: + errflag = 0xFF; + break; + } + } + } + else + { + /* usb standard request processing */ + switch( USBFS_SetupReqCode ) + { + /* get device/configuration/string/report/... descriptors */ + case USB_GET_DESCRIPTOR: + switch( (uint8_t)( USBFS_SetupReqValue >> 8 ) ) + { + /* get usb device descriptor */ + case USB_DESCR_TYP_DEVICE: + pUSBFS_Descr = MyDevDescr; + len = DEF_USBD_DEVICE_DESC_LEN; + break; + + /* get usb configuration descriptor */ + case USB_DESCR_TYP_CONFIG: + pUSBFS_Descr = MyCfgDescr; + len = DEF_USBD_CONFIG_DESC_LEN; + break; + + /* get usb hid descriptor */ + case USB_DESCR_TYP_HID: + if( USBFS_SetupReqIndex == 0x00 ) + { + pUSBFS_Descr = &MyCfgDescr[ 18 ]; + len = 9; + } + else if( USBFS_SetupReqIndex == 0x01 ) + { + pUSBFS_Descr = &MyCfgDescr[ 43 ]; + len = 9; + } + else + { + errflag = 0xFF; + } + break; + + /* get usb report descriptor */ + case USB_DESCR_TYP_REPORT: + if( USBFS_SetupReqIndex == 0x00 ) + { + pUSBFS_Descr = KeyRepDesc; + len = DEF_USBD_REPORT_DESC_LEN_KB; + } + else if( USBFS_SetupReqIndex == 0x01 ) + { + pUSBFS_Descr = MouseRepDesc; + len = DEF_USBD_REPORT_DESC_LEN_MS; + } + else + { + errflag = 0xFF; + } + break; + + /* get usb string descriptor */ + case USB_DESCR_TYP_STRING: + switch( (uint8_t)( USBFS_SetupReqValue & 0xFF ) ) + { + /* Descriptor 0, Language descriptor */ + case DEF_STRING_DESC_LANG: + pUSBFS_Descr = MyLangDescr; + len = DEF_USBD_LANG_DESC_LEN; + break; + + /* Descriptor 1, Manufacturers String descriptor */ + case DEF_STRING_DESC_MANU: + pUSBFS_Descr = MyManuInfo; + len = DEF_USBD_MANU_DESC_LEN; + break; + + /* Descriptor 2, Product String descriptor */ + case DEF_STRING_DESC_PROD: + pUSBFS_Descr = MyProdInfo; + len = DEF_USBD_PROD_DESC_LEN; + break; + + /* Descriptor 3, Serial-number String descriptor */ + case DEF_STRING_DESC_SERN: + pUSBFS_Descr = MySerNumInfo; + len = DEF_USBD_SN_DESC_LEN; + break; + + default: + errflag = 0xFF; + break; + } + break; + + default : + errflag = 0xFF; + break; + } + + /* Copy Descriptors to Endp0 DMA buffer */ + if( USBFS_SetupReqLen > len ) + { + USBFS_SetupReqLen = len; + } + len = ( USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ) ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen; + memcpy( USBFS_EP0_Buf, pUSBFS_Descr, len ); + pUSBFS_Descr += len; + break; + + /* Set usb address */ + case USB_SET_ADDRESS: + USBFS_DevAddr = (uint8_t)( USBFS_SetupReqValue & 0xFF ); + break; + + /* Get usb configuration now set */ + case USB_GET_CONFIGURATION: + USBFS_EP0_Buf[ 0 ] = USBFS_DevConfig; + if( USBFS_SetupReqLen > 1 ) + { + USBFS_SetupReqLen = 1; + } + break; + + /* Set usb configuration to use */ + case USB_SET_CONFIGURATION: + USBFS_DevConfig = (uint8_t)( USBFS_SetupReqValue & 0xFF ); + USBFS_DevEnumStatus = 0x01; + break; + + /* Clear or disable one usb feature */ + case USB_CLEAR_FEATURE: + if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE ) + { + /* clear one device feature */ + if( (uint8_t)( USBFS_SetupReqValue & 0xFF ) == USB_REQ_FEAT_REMOTE_WAKEUP ) + { + /* clear usb sleep status, device not prepare to sleep */ + USBFS_DevSleepStatus &= ~0x01; + } + else + { + errflag = 0xFF; + } + } + else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) + { + if( (uint8_t)( USBFS_SetupReqValue & 0xFF ) == USB_REQ_FEAT_ENDP_HALT ) + { + /* Clear End-point Feature */ + switch( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) ) + { + case ( DEF_UEP_IN | DEF_UEP1 ): + /* Set End-point 1 OUT ACK */ + USBFS->UEP1_CTRL_H = USBFS_UEP_T_RES_NAK; + break; + + case ( DEF_UEP_IN | DEF_UEP2 ): + /* Set End-point 2 IN NAK */ + USBFS->UEP2_CTRL_H = USBFS_UEP_T_RES_NAK; + break; + + default: + errflag = 0xFF; + break; + } + } + else + { + errflag = 0xFF; + } + } + else + { + errflag = 0xFF; + } + break; + + /* set or enable one usb feature */ + case USB_SET_FEATURE: + if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE ) + { + /* Set Device Feature */ + if( (uint8_t)( USBFS_SetupReqValue & 0xFF ) == USB_REQ_FEAT_REMOTE_WAKEUP ) + { + if( MyCfgDescr[ 7 ] & 0x20 ) + { + /* Set Wake-up flag, device prepare to sleep */ + USBFS_DevSleepStatus |= 0x01; + } + else + { + errflag = 0xFF; + } + } + else + { + errflag = 0xFF; + } + } + else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) + { + /* Set Endpoint Feature */ + if( (uint8_t)( USBFS_SetupReqValue & 0xFF ) == USB_REQ_FEAT_ENDP_HALT ) + { + switch( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) ) + { + case ( DEF_UEP_IN | DEF_UEP1 ): + USBFS->UEP1_CTRL_H = ( USBFS->UEP1_CTRL_H & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_STALL; + break; + + case ( DEF_UEP_IN | DEF_UEP2 ): + USBFS->UEP2_CTRL_H = ( USBFS->UEP2_CTRL_H & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_STALL; + break; + + default: + errflag = 0xFF; + break; + } + } + else + { + errflag = 0xFF; + } + } + else + { + errflag = 0xFF; + } + break; + + /* This request allows the host to select another setting for the specified interface */ + case USB_GET_INTERFACE: + USBFS_EP0_Buf[ 0 ] = 0x00; + if( USBFS_SetupReqLen > 1 ) + { + USBFS_SetupReqLen = 1; + } + break; + + case USB_SET_INTERFACE: + break; + + /* host get status of specified device/interface/end-points */ + case USB_GET_STATUS: + USBFS_EP0_Buf[ 0 ] = 0x00; + USBFS_EP0_Buf[ 1 ] = 0x00; + if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE ) + { + if( USBFS_DevSleepStatus & 0x01 ) + { + USBFS_EP0_Buf[ 0 ] = 0x02; + } + else + { + USBFS_EP0_Buf[ 0 ] = 0x00; + } + } + else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) + { + if( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) == ( DEF_UEP_IN | DEF_UEP1 ) ) + { + if( ( USBFS->UEP1_CTRL_H & USBFS_UEP_T_RES_MASK ) == USBFS_UEP_T_RES_STALL ) + { + USBFS_EP0_Buf[ 0 ] = 0x01; + } + } + else if( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) == ( DEF_UEP_IN | DEF_UEP2 ) ) + { + if( ( USBFS->UEP2_CTRL_H & USBFS_UEP_T_RES_MASK ) == USBFS_UEP_T_RES_STALL ) + { + USBFS_EP0_Buf[ 0 ] = 0x01; + } + } + else + { + errflag = 0xFF; + } + } + else + { + errflag = 0xFF; + } + if( USBFS_SetupReqLen > 2 ) + { + USBFS_SetupReqLen = 2; + } + break; + + default: + errflag = 0xFF; + break; + } + } + + /* errflag = 0xFF means a request not support or some errors occurred, else correct */ + if( errflag == 0xFF ) + { + /* if one request not support, return stall */ + USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_STALL|USBFS_UEP_R_TOG | USBFS_UEP_R_RES_STALL; + } + else + { + /* end-point 0 data Tx/Rx */ + if( USBFS_SetupReqType & DEF_UEP_IN ) + { + len = ( USBFS_SetupReqLen > DEF_USBD_UEP0_SIZE )? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen; + USBFS_SetupReqLen -= len; + USBFS->UEP0_TX_LEN = len; + USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK; + } + else + { + if( USBFS_SetupReqLen == 0 ) + { + USBFS->UEP0_TX_LEN = 0; + USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK; + } + else + { + USBFS->UEP0_CTRL_H = USBFS_UEP_R_TOG | USBFS_UEP_R_RES_ACK; + } + } + } + break; + + /* Sof pack processing */ + case CUIS_TOKEN_SOF: + break; + + default : + break; + } + } + else if( intfgst & CRB_UIF_BUS_RST ) { - if( flags & RB_UIF_TRANSFER ) + /* usb reset interrupt processing */ + USBFS_DevConfig = 0; + USBFS_DevAddr = 0; + USBFS_DevSleepStatus = 0; + USBFS_DevEnumStatus = 0; + + USBFS->DEV_ADDR = 0; + USBFS_Device_Endp_Init( ); + } + else if( intfgst & CRB_UIF_SUSPEND ) + { + /* usb suspend interrupt processing */ + if( USBFS->MIS_ST & USBFS_UMS_SUSPEND ) { - // Handle transfer. - USBDEBUG0++; + USBFS_DevSleepStatus |= 0x02; + if( USBFS_DevSleepStatus == 0x03 ) + { + /* Handling usb sleep here */ + //TODO: MCU_Sleep_Wakeup_Operate( ); + } } - if( flags & RB_UIF_BUS_RST ) + else { - // Handle transfer. - USBDEBUG0+=1000; + USBFS_DevSleepStatus &= ~0x02; } - //USBDEBUG0 = USBFS->INT_FG; - USBFS->INT_FG = flags; } -*/ - *(uint16_t*)(&USBFSD->INT_FG) = intfgst; - //intfgst = *(uint16_t*)(&USBFSD->INT_FG); + // Handle any other interrupts and just clear them out. + *(uint16_t*)(&USBFS->INT_FG) = intfgst; + + //intfgst = *(uint16_t*)(&USBFS->INT_FG); GPIOA->BSHR = 1<<16; } +void USBFS_Device_Endp_Init() +{ + USBFS->UEP4_1_MOD = EP_SIZE; + USBFS->UEP2_3_MOD = EP_SIZE; + USBFS->UEP567_MOD = 0; + + USBFS->UEP0_DMA = (intptr_t)USBFS_EP0_Buf; + USBFS->UEP1_DMA = (intptr_t)USBFS_EP1_Buf; + USBFS->UEP2_DMA = (intptr_t)USBFS_EP2_Buf; + + USBFS->UEP0_CTRL_H = USBFS_UEP_R_RES_ACK | USBFS_UEP_T_RES_NAK; + USBFS->UEP1_CTRL_H = USBFS_UEP_T_RES_NAK; + USBFS->UEP2_CTRL_H = USBFS_UEP_T_RES_NAK; + + /* Clear End-points Busy Status */ + for(uint8_t i=0; i< sizeof(USBFS_Endp_Busy)/sizeof(USBFS_Endp_Busy[0]); i++ ) + { + USBFS_Endp_Busy[ i ] = 0; + } +} + + void USBFS_Poll() { USBDEBUG2 = USBFS->INT_ST;//EP0_DATA[1]; @@ -83,13 +737,12 @@ int FSUSBSetup() // Enter device mode. USBFS->INT_EN = RB_UIE_SUSPEND | RB_UIE_TRANSFER | RB_UIE_BUS_RST; - USBFS->UEP4_1_MOD = 0; - USBFS->UEP2_3_MOD = 0; - USBFS->UEP567_MOD = 0; - USBFS->UEP0_DMA = ((intptr_t)EP0_DATA) & 0x7fff; - USBFS->DEV_ADDR = 0x00; + USBFS->DEV_ADDR = 0x00; USBFS->UDEV_CTRL = RB_UD_PD_DIS | RB_UD_PORT_EN; + USBFS_Device_Endp_Init(); + + // Go on-bus. // From the TRM: diff --git a/examples_x035/usbdevice.incomplete/fsusb.h b/examples_x035/usbdevice.incomplete/fsusb.h index 76f794e4..064985f9 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.h +++ b/examples_x035/usbdevice.incomplete/fsusb.h @@ -3,10 +3,379 @@ #include +#include "descriptor.h" + extern uint32_t USBDEBUG0, USBDEBUG1, USBDEBUG2; int FSUSBSetup(); void USBFS_Poll(); + +// XXX TODO: Put the below in an object. + +/*******************************************************************************/ +/* Variable Definition */ +/* Global */ +extern const uint8_t *pUSBFS_Descr; + +/* Setup Request */ +extern volatile uint8_t USBFS_SetupReqCode; +extern volatile uint8_t USBFS_SetupReqType; +extern volatile uint16_t USBFS_SetupReqValue; +extern volatile uint16_t USBFS_SetupReqIndex; +extern volatile uint16_t USBFS_SetupReqLen; + +/* USB Device Status */ +extern volatile uint8_t USBFS_DevConfig; +extern volatile uint8_t USBFS_DevAddr; +extern volatile uint8_t USBFS_DevSleepStatus; +extern volatile uint8_t USBFS_DevEnumStatus; + +/* Endpoint Buffer */ +extern __attribute__ ((aligned(4))) uint8_t USBFS_EP0_Buf[]; +extern __attribute__ ((aligned(4))) uint8_t USBFS_EP2_Buf[]; + + +/* USB IN Endpoint Busy Flag */ +extern volatile uint8_t USBFS_Endp_Busy[ ]; + + +// ABOVE: TOOD: REWRITE! + +// Copied from x035 documentation. + +#define USBFSD_UEP_MOD_BASE 0x5000000C +#define USBFSD_UEP_DMA_BASE 0x50000010 +#define USBFSD_UEP_LEN_BASE 0x50000030 +#define USBFSD_UEP_CTL_BASE 0x50000032 +#define USBFSD_UEP_RX_EN 0x08 +#define USBFSD_UEP_TX_EN 0x04 +#define USBFSD_UEP_BUF_MOD 0x01 +#define DEF_UEP_DMA_LOAD 0 /* Direct the DMA address to the data to be processed */ +#define DEF_UEP_CPY_LOAD 1 /* Use memcpy to move data to a buffer */ +#define USBFSD_UEP_MOD( N ) (*((volatile uint8_t *)( USBFSD_UEP_MOD_BASE + N ))) +#define USBFSD_UEP_TX_CTRL( N ) (*((volatile uint8_t *)( USBFSD_UEP_CTL_BASE + N * 0x04 ))) +#define USBFSD_UEP_RX_CTRL( N ) (*((volatile uint8_t *)( USBFSD_UEP_CTL_BASE + N * 0x04 + 1 ))) +#define USBFSD_UEP_DMA( N ) (*((volatile uint32_t *)( USBFSD_UEP_DMA_BASE + N * 0x04 ))) +#define USBFSD_UEP_BUF( N ) ((uint8_t *)(*((volatile uint32_t *)( USBFSD_UEP_DMA_BASE + N * 0x04 ))) + 0x20000000) +#define USBFSD_UEP_TLEN( N ) (*((volatile uint16_t *)( USBFSD_UEP_LEN_BASE + N * 0x04 ))) + +#define pUSBFS_SetupReqPak ((PUSB_SETUP_REQ)USBFS_EP0_4Buf) + + +/* R8_UEPn_TX_CTRL */ +#define USBFS_UEP_T_AUTO_TOG (1<<4) // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle +#define USBFS_UEP_T_TOG (1<<6) // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1 +#define USBFS_UEP_T_RES_MASK (3<<0) // bit mask of handshake response type for USB endpoint X transmittal (IN) +#define USBFS_UEP_T_RES_ACK (0<<1) +#define USBFS_UEP_T_RES_NONE (1<<0) +#define USBFS_UEP_T_RES_NAK (1<<1) +#define USBFS_UEP_T_RES_STALL (3<<0) +// bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmittal (IN) +// 00: DATA0 or DATA1 then expecting ACK (ready) +// 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions +// 10: NAK (busy) +// 11: STALL (error) +// host aux setup + +/* R8_UEPn_RX_CTRL, n=0-7 */ +#define USBFS_UEP_R_AUTO_TOG (1<<4) // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle +#define USBFS_UEP_R_TOG (1<<7) // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1 +#define USBFS_UEP_R_RES_MASK (3<<2) // bit mask of handshake response type for USB endpoint X receiving (OUT) +#define USBFS_UEP_R_RES_ACK (0<<3) +#define USBFS_UEP_R_RES_NONE (1<<2) +#define USBFS_UEP_R_RES_NAK (1<<3) +#define USBFS_UEP_R_RES_STALL (3<<2) + + +/* R8_USB_DEV_AD */ +#define USBFS_UDA_GP_BIT 0x80 +#define USBFS_USB_ADDR_MASK 0x7F + + +/* USB Setup Request */ +typedef struct __attribute__((packed)) _USB_SETUP_REQ +{ + uint8_t bRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} USB_SETUP_REQ, *PUSB_SETUP_REQ; + +/* USB Device Descriptor */ +typedef struct __attribute__((packed)) _USB_DEVICE_DESCR +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; +} USB_DEV_DESCR, *PUSB_DEV_DESCR; + +/* USB Configuration Descriptor */ +typedef struct __attribute__((packed)) _USB_CONFIG_DESCR +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t MaxPower; +} USB_CFG_DESCR, *PUSB_CFG_DESCR; + +/* USB Interface Descriptor */ +typedef struct __attribute__((packed)) _USB_INTERF_DESCR +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; +} USB_ITF_DESCR, *PUSB_ITF_DESCR; + +/* USB Endpoint Descriptor */ +typedef struct __attribute__((packed)) _USB_ENDPOINT_DESCR +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint8_t wMaxPacketSizeL; + uint8_t wMaxPacketSizeH; + uint8_t bInterval; +} USB_ENDP_DESCR, *PUSB_ENDP_DESCR; + +/* USB Configuration Descriptor Set */ +typedef struct __attribute__((packed)) _USB_CONFIG_DESCR_LONG +{ + USB_CFG_DESCR cfg_descr; + USB_ITF_DESCR itf_descr; + USB_ENDP_DESCR endp_descr[ 1 ]; +} USB_CFG_DESCR_LONG, *PUSB_CFG_DESCR_LONG; + +/* USB HUB Descriptor */ +typedef struct __attribute__((packed)) _USB_HUB_DESCR +{ + uint8_t bDescLength; + uint8_t bDescriptorType; + uint8_t bNbrPorts; + uint8_t wHubCharacteristicsL; + uint8_t wHubCharacteristicsH; + uint8_t bPwrOn2PwrGood; + uint8_t bHubContrCurrent; + uint8_t DeviceRemovable; + uint8_t PortPwrCtrlMask; +} USB_HUB_DESCR, *PUSB_HUB_DESCR; + +/* USB HID Descriptor */ +typedef struct __attribute__((packed)) _USB_HID_DESCR +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdHID; + uint8_t bCountryCode; + uint8_t bNumDescriptors; + uint8_t bDescriptorTypeX; + uint8_t wDescriptorLengthL; + uint8_t wDescriptorLengthH; +} USB_HID_DESCR, *PUSB_HID_DESCR; + + +/*******************************************************************************/ +/* USB Communication Related Macro Definition */ + +/* USB PID */ +#ifndef USB_PID_SETUP +#define USB_PID_NULL 0x00 +#define USB_PID_SOF 0x05 +#define USB_PID_SETUP 0x0D +#define USB_PID_IN 0x09 +#define USB_PID_OUT 0x01 +#define USB_PID_NYET 0x06 +#define USB_PID_ACK 0x02 +#define USB_PID_NAK 0x0A +#define USB_PID_STALL 0x0E +#define USB_PID_DATA0 0x03 +#define USB_PID_DATA1 0x0B +#define USB_PID_PRE 0x0C +#endif + +/* USB standard device request code */ +#ifndef USB_GET_DESCRIPTOR +#define USB_GET_STATUS 0x00 +#define USB_CLEAR_FEATURE 0x01 +#define USB_SET_FEATURE 0x03 +#define USB_SET_ADDRESS 0x05 +#define USB_GET_DESCRIPTOR 0x06 +#define USB_SET_DESCRIPTOR 0x07 +#define USB_GET_CONFIGURATION 0x08 +#define USB_SET_CONFIGURATION 0x09 +#define USB_GET_INTERFACE 0x0A +#define USB_SET_INTERFACE 0x0B +#define USB_SYNCH_FRAME 0x0C +#endif + +#define DEF_STRING_DESC_LANG 0x00 +#define DEF_STRING_DESC_MANU 0x01 +#define DEF_STRING_DESC_PROD 0x02 +#define DEF_STRING_DESC_SERN 0x03 + +/* USB hub class request code */ +#ifndef HUB_GET_DESCRIPTOR +#define HUB_GET_STATUS 0x00 +#define HUB_CLEAR_FEATURE 0x01 +#define HUB_GET_STATE 0x02 +#define HUB_SET_FEATURE 0x03 +#define HUB_GET_DESCRIPTOR 0x06 +#define HUB_SET_DESCRIPTOR 0x07 +#endif + +/* USB HID class request code */ +#ifndef HID_GET_REPORT +#define HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0A +#define HID_SET_PROTOCOL 0x0B +#endif + +/* Bit Define for USB Request Type */ +#ifndef USB_REQ_TYP_MASK +#define USB_REQ_TYP_IN 0x80 +#define USB_REQ_TYP_OUT 0x00 +#define USB_REQ_TYP_READ 0x80 +#define USB_REQ_TYP_WRITE 0x00 +#define USB_REQ_TYP_MASK 0x60 +#define USB_REQ_TYP_STANDARD 0x00 +#define USB_REQ_TYP_CLASS 0x20 +#define USB_REQ_TYP_VENDOR 0x40 +#define USB_REQ_TYP_RESERVED 0x60 +#define USB_REQ_RECIP_MASK 0x1F +#define USB_REQ_RECIP_DEVICE 0x00 +#define USB_REQ_RECIP_INTERF 0x01 +#define USB_REQ_RECIP_ENDP 0x02 +#define USB_REQ_RECIP_OTHER 0x03 +#define USB_REQ_FEAT_REMOTE_WAKEUP 0x01 +#define USB_REQ_FEAT_ENDP_HALT 0x00 +#endif + +/* USB Descriptor Type */ +#ifndef USB_DESCR_TYP_DEVICE +#define USB_DESCR_TYP_DEVICE 0x01 +#define USB_DESCR_TYP_CONFIG 0x02 +#define USB_DESCR_TYP_STRING 0x03 +#define USB_DESCR_TYP_INTERF 0x04 +#define USB_DESCR_TYP_ENDP 0x05 +#define USB_DESCR_TYP_QUALIF 0x06 +#define USB_DESCR_TYP_SPEED 0x07 +#define USB_DESCR_TYP_OTG 0x09 +#define USB_DESCR_TYP_BOS 0X0F +#define USB_DESCR_TYP_HID 0x21 +#define USB_DESCR_TYP_REPORT 0x22 +#define USB_DESCR_TYP_PHYSIC 0x23 +#define USB_DESCR_TYP_CS_INTF 0x24 +#define USB_DESCR_TYP_CS_ENDP 0x25 +#define USB_DESCR_TYP_HUB 0x29 +#endif + +/* USB Device Class */ +#ifndef USB_DEV_CLASS_HUB +#define USB_DEV_CLASS_RESERVED 0x00 +#define USB_DEV_CLASS_AUDIO 0x01 +#define USB_DEV_CLASS_COMMUNIC 0x02 +#define USB_DEV_CLASS_HID 0x03 +#define USB_DEV_CLASS_MONITOR 0x04 +#define USB_DEV_CLASS_PHYSIC_IF 0x05 +#define USB_DEV_CLASS_POWER 0x06 +#define USB_DEV_CLASS_PRINTER 0x07 +#define USB_DEV_CLASS_STORAGE 0x08 +#define USB_DEV_CLASS_HUB 0x09 +#define USB_DEV_CLASS_VEN_SPEC 0xFF +#endif + +/* USB Hub Class Request */ +#ifndef HUB_GET_HUB_DESCRIPTOR +#define HUB_CLEAR_HUB_FEATURE 0x20 +#define HUB_CLEAR_PORT_FEATURE 0x23 +#define HUB_GET_BUS_STATE 0xA3 +#define HUB_GET_HUB_DESCRIPTOR 0xA0 +#define HUB_GET_HUB_STATUS 0xA0 +#define HUB_GET_PORT_STATUS 0xA3 +#define HUB_SET_HUB_DESCRIPTOR 0x20 +#define HUB_SET_HUB_FEATURE 0x20 +#define HUB_SET_PORT_FEATURE 0x23 +#endif + +/* Hub Class Feature Selectors */ +#ifndef HUB_PORT_RESET +#define HUB_C_HUB_LOCAL_POWER 0 +#define HUB_C_HUB_OVER_CURRENT 1 +#define HUB_PORT_CONNECTION 0 +#define HUB_PORT_ENABLE 1 +#define HUB_PORT_SUSPEND 2 +#define HUB_PORT_OVER_CURRENT 3 +#define HUB_PORT_RESET 4 +#define HUB_PORT_POWER 8 +#define HUB_PORT_LOW_SPEED 9 +#define HUB_C_PORT_CONNECTION 16 +#define HUB_C_PORT_ENABLE 17 +#define HUB_C_PORT_SUSPEND 18 +#define HUB_C_PORT_OVER_CURRENT 19 +#define HUB_C_PORT_RESET 20 +#endif + +/* USB HID Class Request Code */ +#ifndef HID_GET_REPORT +#define HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0A +#define HID_SET_PROTOCOL 0x0B +#endif + +/* USB UDisk */ +#ifndef USB_BO_CBW_SIZE +#define USB_BO_CBW_SIZE 0x1F +#define USB_BO_CSW_SIZE 0x0D +#endif +#ifndef USB_BO_CBW_SIG0 +#define USB_BO_CBW_SIG0 0x55 +#define USB_BO_CBW_SIG1 0x53 +#define USB_BO_CBW_SIG2 0x42 +#define USB_BO_CBW_SIG3 0x43 +#define USB_BO_CSW_SIG0 0x55 +#define USB_BO_CSW_SIG1 0x53 +#define USB_BO_CSW_SIG2 0x42 +#define USB_BO_CSW_SIG3 0x53 +#endif + +/* USB CDC Class request code */ +#ifndef CDC_GET_LINE_CODING +#define CDC_GET_LINE_CODING 0X21 /* This request allows the host to find out the currently configured line coding */ +#define CDC_SET_LINE_CODING 0x20 /* Configures DTE rate, stop-bits, parity, and number-of-character */ +#define CDC_SET_LINE_CTLSTE 0X22 /* This request generates RS-232/V.24 style control signals */ +#define CDC_SEND_BREAK 0X23 /* Sends special carrier modulation used to specify RS-232 style break */ +#endif +/*******************************************************************************/ + + #endif From 63e8327494c8debdb2cb9f64eb19e81a2943920e Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sat, 20 Apr 2024 06:08:51 -0400 Subject: [PATCH 08/31] Well, it enumerates. --- examples_x035/usbdevice.incomplete/fsusb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples_x035/usbdevice.incomplete/fsusb.c b/examples_x035/usbdevice.incomplete/fsusb.c index b135c163..05f8f204 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.c +++ b/examples_x035/usbdevice.incomplete/fsusb.c @@ -103,7 +103,8 @@ volatile uint8_t USBFS_DevEnumStatus; __attribute__ ((aligned(4))) uint8_t USBFS_EP0_Buf[64]; __attribute__ ((aligned(4))) uint8_t USBFS_EP1_Buf[64]; __attribute__ ((aligned(4))) uint8_t USBFS_EP2_Buf[64]; -__attribute__ ((aligned(4))) uint8_t USBFS_EP0_4Buf[ DEF_USBD_UEP0_SIZE*2 ]; //ep0_4(64) +#define pUSBFS_SetupReqPak ((PUSB_SETUP_REQ)USBFS_EP0_Buf) + int USBFS_HidIdle[2]; int USBFS_HidProtocol[2]; @@ -239,7 +240,6 @@ void USBFS_IRQHandler() case CUIS_TOKEN_SETUP: USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG|USBFS_UEP_T_RES_NAK|USBFS_UEP_R_TOG|USBFS_UEP_R_RES_NAK; - /* Store All Setup Values */ USBFS_SetupReqType = pUSBFS_SetupReqPak->bRequestType; USBFS_SetupReqCode = pUSBFS_SetupReqPak->bRequest; @@ -432,6 +432,7 @@ void USBFS_IRQHandler() } len = ( USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ) ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen; memcpy( USBFS_EP0_Buf, pUSBFS_Descr, len ); +USBDEBUG0 = USBFS_EP0_Buf[3]; pUSBFS_Descr += len; break; From 9294351a9924bc33598c0c429a1f90a1ef028c8b Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sat, 20 Apr 2024 06:11:31 -0400 Subject: [PATCH 09/31] Oops forgot to commit file --- examples_x035/usbdevice.incomplete/fsusb.h | 1 - 1 file changed, 1 deletion(-) diff --git a/examples_x035/usbdevice.incomplete/fsusb.h b/examples_x035/usbdevice.incomplete/fsusb.h index 064985f9..31f589e0 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.h +++ b/examples_x035/usbdevice.incomplete/fsusb.h @@ -60,7 +60,6 @@ extern volatile uint8_t USBFS_Endp_Busy[ ]; #define USBFSD_UEP_BUF( N ) ((uint8_t *)(*((volatile uint32_t *)( USBFSD_UEP_DMA_BASE + N * 0x04 ))) + 0x20000000) #define USBFSD_UEP_TLEN( N ) (*((volatile uint16_t *)( USBFSD_UEP_LEN_BASE + N * 0x04 ))) -#define pUSBFS_SetupReqPak ((PUSB_SETUP_REQ)USBFS_EP0_4Buf) /* R8_UEPn_TX_CTRL */ From 9732a81555388a9aa8368da3c7220a62f4adafc9 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sat, 20 Apr 2024 18:40:59 -0700 Subject: [PATCH 10/31] Tweak setupp ins --- examples_x035/usbdevice.incomplete/fsusb.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples_x035/usbdevice.incomplete/fsusb.c b/examples_x035/usbdevice.incomplete/fsusb.c index e522dd6d..67b225e5 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.c +++ b/examples_x035/usbdevice.incomplete/fsusb.c @@ -6,6 +6,7 @@ uint8_t EP0_DATA[64] __attribute__((aligned(32))); void USBFS_IRQHandler() __attribute__((section(".text.vector_handler"))) __attribute__((interrupt)); +// Mask for the combined USBFSD->INT_FG + USBFSD->INT_ST #define CRB_U_IS_NAK (1<<7) #define CTOG_MATCH_SYNC (1<<6) #define CRB_U_SIE_FREE (1<<5) @@ -113,10 +114,8 @@ int FSUSBSetup() // Enable PC16/17 Alternate Function (USB) // According to EVT, GPIO16 = GPIO_Mode_IN_FLOATING, GPIO17 = GPIO_Mode_IPU - GPIOC->CFGXR &= ~(0xf<<(4*0)); - GPIOC->CFGXR |= (GPIO_CFGLR_IN_FLOAT)<<(4*0); // MSBs are CNF, LSBs are MODE - GPIOC->CFGXR &= ~(0xf<<(4*1)); - GPIOC->CFGXR |= (GPIO_CFGLR_IN_PUPD)<<(4*1); + GPIOC->CFGXR = ( GPIOC->CFGXR & ~( (0xf<<(4*0)) | (0xf<<(4*1)) ) ) | + (((GPIO_CFGLR_IN_FLOAT)<<(4*0)) | ((GPIO_CFGLR_IN_PUPD)<<(4*1)); // MSBs are CNF, LSBs are MODE GPIOC->BSXR = 1<<1; // PC17 on. USBFS->UDEV_CTRL = RB_UD_PORT_EN; From aeef7b7be74e3180b11335b000f82af28225b12e Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sun, 21 Apr 2024 01:58:06 -0700 Subject: [PATCH 11/31] One of the endpoints works, but not the other? --- examples_x035/usbdevice.incomplete/fsusb.c | 311 +++++++++++------- examples_x035/usbdevice.incomplete/fsusb.h | 90 ++++- .../usbdevice.incomplete/usbdevice.c | 22 +- 3 files changed, 292 insertions(+), 131 deletions(-) diff --git a/examples_x035/usbdevice.incomplete/fsusb.c b/examples_x035/usbdevice.incomplete/fsusb.c index f29487bb..ea8d03ba 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.c +++ b/examples_x035/usbdevice.incomplete/fsusb.c @@ -7,22 +7,6 @@ uint32_t USBDEBUG0, USBDEBUG1, USBDEBUG2; // based on https://github.com/openwch/ch32x035/tree/main/EVT/EXAM/USB/USBFS/DEVICE/CompositeKM/User -#define DEF_USBD_UEP0_SIZE 64 /* usb hs/fs device end-point 0 size */ -#define EP_SIZE 64 - -#define DEF_UEP_IN 0x80 -#define DEF_UEP_OUT 0x00 - -#define DEF_UEP0 0 -#define DEF_UEP1 1 -#define DEF_UEP2 2 -#define DEF_UEP3 3 -#define DEF_UEP4 4 -#define DEF_UEP5 5 -#define DEF_UEP6 6 -#define DEF_UEP7 7 -#define NUM_EP 8 - // Mask for the combined USBFSD->INT_FG + USBFSD->INT_ST #define CRB_U_IS_NAK (1<<7) #define CTOG_MATCH_SYNC (1<<6) @@ -37,8 +21,6 @@ uint32_t USBDEBUG0, USBDEBUG1, USBDEBUG2; #define CMASK_UIS_TOKEN (3<<12) #define CMASK_UIS_ENDP (0xf<<8) -#define CUSBFS_UIS_ENDP_MASK 0x0 - #define CUIS_TOKEN_OUT 0x0 #define CUIS_TOKEN_SOF 0x1 #define CUIS_TOKEN_IN 0x2 @@ -136,62 +118,68 @@ void USBFS_IRQHandler() if( intfgst & CRB_UIF_TRANSFER ) { int token = ( intfgst & CMASK_UIS_TOKEN) >> 12; - int ep = intfgst & CUSBFS_UIS_ENDP_MASK; + int ep = ( intfgst & CMASK_UIS_ENDP ) >> 8; + + if( ep == 2 ) + USBDEBUG1++; + switch ( token ) { case CUIS_TOKEN_IN: switch( ep ) { - /* end-point 0 data in interrupt */ - case DEF_UEP0: - if( USBFS_SetupReqLen == 0 ) - { - USBFS->UEP0_CTRL_H = USBFS_UEP_R_TOG | USBFS_UEP_R_RES_ACK; - } + /* end-point 0 data in interrupt */ + case DEF_UEP0: + if( USBFS_SetupReqLen == 0 ) + { + USBFS->UEP0_CTRL_H = USBFS_UEP_R_TOG | USBFS_UEP_R_RES_ACK; + } - if ( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) - { - /* Non-standard request endpoint 0 Data upload */ - } - else + if ( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) + { + /* Non-standard request endpoint 0 Data upload, noted by official docs, but I don't think this would ever really be used. */ + } + else + { + switch( USBFS_SetupReqCode ) { - switch( USBFS_SetupReqCode ) - { - case USB_GET_DESCRIPTOR: - len = USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen; - memcpy( USBFS_EP0_Buf, pUSBFS_Descr, len ); - USBFS_SetupReqLen -= len; - pUSBFS_Descr += len; - USBFS->UEP0_TX_LEN = len; - USBFS->UEP0_CTRL_H ^= USBFS_UEP_T_TOG; - break; + case USB_GET_DESCRIPTOR: + len = USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen; + memcpy( USBFS_EP0_Buf, pUSBFS_Descr, len ); + USBFS_SetupReqLen -= len; + pUSBFS_Descr += len; + USBFS->UEP0_TX_LEN = len; + USBFS->UEP0_CTRL_H ^= USBFS_UEP_T_TOG; + break; - case USB_SET_ADDRESS: - USBFS->DEV_ADDR = ( USBFS->DEV_ADDR & USBFS_UDA_GP_BIT ) | USBFS_DevAddr; - break; + case USB_SET_ADDRESS: + USBFS->DEV_ADDR = ( USBFS->DEV_ADDR & USBFS_UDA_GP_BIT ) | USBFS_DevAddr; + break; - default: - break; - } + default: + break; } - break; - - /* end-point 1 data in interrupt */ - case DEF_UEP1: - USBFS->UEP1_CTRL_H = ( USBFS->UEP1_CTRL_H & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_NAK; - USBFS->UEP1_CTRL_H ^= USBFS_UEP_T_TOG; - USBFS_Endp_Busy[ DEF_UEP1 ] = 0; - break; - - /* end-point 2 data in interrupt */ - case DEF_UEP2: - USBFS->UEP2_CTRL_H = ( USBFS->UEP2_CTRL_H & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_NAK; - USBFS->UEP2_CTRL_H ^= USBFS_UEP_T_TOG; - USBFS_Endp_Busy[ DEF_UEP2 ] = 0; - break; - - default : - break; + } + break; + + /* end-point 1 data in interrupt */ + case DEF_UEP1: + USBFS->UEP1_CTRL_H = ( USBFS->UEP1_CTRL_H & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_NAK; + USBFS->UEP1_CTRL_H ^= USBFS_UEP_T_TOG; + USBFS_Endp_Busy[ DEF_UEP1 ] = 0; + USBDEBUG0++; + break; + + /* end-point 2 data in interrupt */ + case DEF_UEP2: + USBFS->UEP2_CTRL_H = ( USBFS->UEP2_CTRL_H & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_NAK; + USBFS->UEP2_CTRL_H ^= USBFS_UEP_T_TOG; + USBFS_Endp_Busy[ DEF_UEP2 ] = 0; + USBDEBUG0++; + break; + + default : + break; } break; @@ -261,67 +249,36 @@ void USBFS_IRQHandler() break; case HID_SET_IDLE: - if( USBFS_SetupReqIndex == 0x00 ) - { - USBFS_HidIdle[ 0 ] = (uint8_t)( USBFS_SetupReqValue >> 8 ); - } - else if( USBFS_SetupReqIndex == 0x01 ) - { - USBFS_HidIdle[ 1 ] = (uint8_t)( USBFS_SetupReqValue >> 8 ); - } + if( USBFS_SetupReqIndex < 0x02 ) + USBFS_HidIdle[ USBFS_SetupReqIndex ] = (uint8_t)( USBFS_SetupReqValue >> 8 ); else - { errflag = 0xFF; - } break; - case HID_SET_PROTOCOL: - if( USBFS_SetupReqIndex == 0x00 ) - { - USBFS_HidProtocol[ 0 ] = (uint8_t)USBFS_SetupReqValue; - } - else if( USBFS_SetupReqIndex == 0x01 ) - { - USBFS_HidProtocol[ 1 ] = (uint8_t)USBFS_SetupReqValue; - } + if ( USBFS_SetupReqIndex < 0x02 ) + USBFS_HidProtocol[USBFS_SetupReqIndex] = (uint8_t)USBFS_SetupReqValue; else - { errflag = 0xFF; - } break; case HID_GET_IDLE: - if( USBFS_SetupReqIndex == 0x00 ) - { - USBFS_EP0_Buf[ 0 ] = USBFS_HidIdle[ 0 ]; - len = 1; - } - else if( USBFS_SetupReqIndex == 0x01 ) + if( USBFS_SetupReqIndex < 0x02 ) { - USBFS_EP0_Buf[ 0 ] = USBFS_HidIdle[ 1 ]; + USBFS_EP0_Buf[ 0 ] = USBFS_HidIdle[ USBFS_SetupReqIndex ]; len = 1; } else - { errflag = 0xFF; - } break; case HID_GET_PROTOCOL: - if( USBFS_SetupReqIndex == 0x00 ) - { - USBFS_EP0_Buf[ 0 ] = USBFS_HidProtocol[ 0 ]; - len = 1; - } - else if( USBFS_SetupReqIndex == 0x01 ) + if( USBFS_SetupReqIndex < 0x02 ) { - USBFS_EP0_Buf[ 0 ] = USBFS_HidProtocol[ 1 ]; + USBFS_EP0_Buf[ 0 ] = USBFS_HidProtocol[ USBFS_SetupReqIndex ]; len = 1; } else - { errflag = 0xFF; - } break; default: @@ -433,7 +390,6 @@ void USBFS_IRQHandler() } len = ( USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ) ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen; memcpy( USBFS_EP0_Buf, pUSBFS_Descr, len ); -USBDEBUG0 = USBFS_EP0_Buf[3]; pUSBFS_Descr += len; break; @@ -699,8 +655,8 @@ USBDEBUG0 = USBFS_EP0_Buf[3]; void USBFS_Device_Endp_Init() { - USBFS->UEP4_1_MOD = EP_SIZE; - USBFS->UEP2_3_MOD = EP_SIZE; + USBFS->UEP4_1_MOD = RB_UEP1_TX_EN; + USBFS->UEP2_3_MOD = RB_UEP2_TX_EN; USBFS->UEP567_MOD = 0; USBFS->UEP0_DMA = (intptr_t)USBFS_EP0_Buf; @@ -721,8 +677,8 @@ void USBFS_Device_Endp_Init() void USBFS_Poll() { - USBDEBUG2 = USBFS->INT_ST;//EP0_DATA[1]; - USBDEBUG1 = USBFS->MIS_ST; + //USBDEBUG2 = USBFS->INT_ST;//EP0_DATA[1]; + //USBDEBUG1 = USBFS->MIS_ST; } int FSUSBSetup() @@ -735,16 +691,17 @@ int FSUSBSetup() AFIO->CTLR |= USB_PHY_V33; USBFS->BASE_CTRL = RB_UC_RESET_SIE | RB_UC_CLR_ALL; - USBFS->BASE_CTRL = RB_UC_DEV_PU_EN | RB_UC_INT_BUSY | RB_UC_DMA_EN; + USBFS->BASE_CTRL = 0x00; + + USBFS_Device_Endp_Init(); // Enter device mode. USBFS->INT_EN = RB_UIE_SUSPEND | RB_UIE_TRANSFER | RB_UIE_BUS_RST; USBFS->DEV_ADDR = 0x00; + USBFS->BASE_CTRL = RB_UC_DEV_PU_EN | RB_UC_INT_BUSY | RB_UC_DMA_EN; + USBFS->INT_FG = 0xff; USBFS->UDEV_CTRL = RB_UD_PD_DIS | RB_UD_PORT_EN; - USBFS_Device_Endp_Init(); - - // Go on-bus. // From the TRM: @@ -763,18 +720,142 @@ int FSUSBSetup() // GPIOC_OUTDR selects the up pull, and PC16 // corresponding to CNF=01 selects the floating input. + // XXX TODO: Handle for 5V VDD. AFIO->CTLR = (AFIO->CTLR & ~(UDP_PUE_11 | UDM_PUE_11 )) | USB_PHY_V33 | USB_IOEN | UDP_PUE_11; //1.5k pullup // Enable PC16/17 Alternate Function (USB) // According to EVT, GPIO16 = GPIO_Mode_IN_FLOATING, GPIO17 = GPIO_Mode_IPU GPIOC->CFGXR = ( GPIOC->CFGXR & ~( (0xf<<(4*0)) | (0xf<<(4*1)) ) ) | - (((GPIO_CFGLR_IN_FLOAT)<<(4*0)) | ((GPIO_CFGLR_IN_PUPD)<<(4*1)); // MSBs are CNF, LSBs are MODE + (((GPIO_CFGLR_IN_FLOAT)<<(4*0)) | (((GPIO_CFGLR_IN_PUPD)<<(4*1)))); // MSBs are CNF, LSBs are MODE GPIOC->BSXR = 1<<1; // PC17 on. - USBFS->UDEV_CTRL = RB_UD_PORT_EN; - // Go on-bus. return 0; } + + + + +uint8_t USBFS_Endp_DataUp(uint8_t endp, uint8_t *pbuf, uint16_t len, uint8_t mod) +{ + uint8_t endp_mode; + uint8_t buf_load_offset; + + /* DMA config, endp_ctrl config, endp_len config */ + if( ( endp >= DEF_UEP1 ) && ( endp <= DEF_UEP7 ) ) + { + if( USBFS_Endp_Busy[ endp ] == 0 ) + { + if( (endp == DEF_UEP1) || (endp == DEF_UEP4) ) + { + /* endp1/endp4 */ + endp_mode = USBFSD_UEP_MOD( 0 ); + if( endp == DEF_UEP1 ) + { + endp_mode = (uint8_t)( endp_mode >> 4 ); + } + } + else if( ( endp == DEF_UEP2 ) || ( endp == DEF_UEP3 ) ) + { + /* endp2/endp3 */ + endp_mode = USBFSD_UEP_MOD( 1 ); + if( endp == DEF_UEP3 ) + { + endp_mode = (uint8_t)( endp_mode >> 4 ); + } + } + else if( ( endp == DEF_UEP5 ) || ( endp == DEF_UEP6 ) ) + { + /* endp5/endp6 */ + endp_mode = USBFSD_UEP_MOD( 2 ); + if( endp == DEF_UEP6 ) + { + endp_mode = (uint8_t)( endp_mode >> 4 ); + } + } + else + { + /* endp7 */ + endp_mode = USBFSD_UEP_MOD( 3 ); + } + + if( endp_mode & USBFSD_UEP_TX_EN ) + { + if( endp_mode & USBFSD_UEP_RX_EN ) + { + if( endp_mode & USBFSD_UEP_BUF_MOD ) + { + if( USBFSD_UEP_TX_CTRL(endp) & USBFS_UEP_T_TOG ) + { + buf_load_offset = 192; + } + else + { + buf_load_offset = 128; + } + } + else + { + buf_load_offset = 64; + } + } + else + { + if( endp_mode & USBFSD_UEP_BUF_MOD ) + { + /* double tx buffer */ + if( USBFSD_UEP_TX_CTRL( endp ) & USBFS_UEP_T_TOG ) + { + buf_load_offset = 64; + } + else + { + buf_load_offset = 0; + } + } + else + { + buf_load_offset = 0; + } + } + if( buf_load_offset == 0 ) + { + if( mod == DEF_UEP_DMA_LOAD ) + { + /* DMA mode */ + USBFSD_UEP_DMA( endp ) = (uint16_t)(uint32_t)pbuf; + } + else + { + /* copy mode */ + memcpy( USBFSD_UEP_BUF( endp ), pbuf, len ); + } + } + else + { + memcpy( USBFSD_UEP_BUF( endp ) + buf_load_offset, pbuf, len ); + } + + /* tx length */ + USBFSD_UEP_TLEN( endp ) = len; + /* response ack */ + USBFSD_UEP_TX_CTRL( endp ) = ( USBFSD_UEP_TX_CTRL( endp ) & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_ACK; + /* Set end-point busy */ + USBFS_Endp_Busy[ endp ] = 0x01; + } + } + else + { + return 1; + } + } + else + { + return 1; + } + return 0; +} + + diff --git a/examples_x035/usbdevice.incomplete/fsusb.h b/examples_x035/usbdevice.incomplete/fsusb.h index 31f589e0..f34f9f54 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.h +++ b/examples_x035/usbdevice.incomplete/fsusb.h @@ -9,7 +9,7 @@ extern uint32_t USBDEBUG0, USBDEBUG1, USBDEBUG2; int FSUSBSetup(); void USBFS_Poll(); - +uint8_t USBFS_Endp_DataUp(uint8_t endp, uint8_t *pbuf, uint16_t len, uint8_t mod); // XXX TODO: Put the below in an object. @@ -18,12 +18,6 @@ void USBFS_Poll(); /* Global */ extern const uint8_t *pUSBFS_Descr; -/* Setup Request */ -extern volatile uint8_t USBFS_SetupReqCode; -extern volatile uint8_t USBFS_SetupReqType; -extern volatile uint16_t USBFS_SetupReqValue; -extern volatile uint16_t USBFS_SetupReqIndex; -extern volatile uint16_t USBFS_SetupReqLen; /* USB Device Status */ extern volatile uint8_t USBFS_DevConfig; @@ -43,11 +37,10 @@ extern volatile uint8_t USBFS_Endp_Busy[ ]; // ABOVE: TOOD: REWRITE! // Copied from x035 documentation. - -#define USBFSD_UEP_MOD_BASE 0x5000000C -#define USBFSD_UEP_DMA_BASE 0x50000010 -#define USBFSD_UEP_LEN_BASE 0x50000030 -#define USBFSD_UEP_CTL_BASE 0x50000032 +#define USBFSD_UEP_MOD_BASE 0x4002340C +#define USBFSD_UEP_DMA_BASE 0x40023410 +#define USBFSD_UEP_LEN_BASE 0x40023420 +#define USBFSD_UEP_CTL_BASE 0x40023422 #define USBFSD_UEP_RX_EN 0x08 #define USBFSD_UEP_TX_EN 0x04 #define USBFSD_UEP_BUF_MOD 0x01 @@ -55,13 +48,11 @@ extern volatile uint8_t USBFS_Endp_Busy[ ]; #define DEF_UEP_CPY_LOAD 1 /* Use memcpy to move data to a buffer */ #define USBFSD_UEP_MOD( N ) (*((volatile uint8_t *)( USBFSD_UEP_MOD_BASE + N ))) #define USBFSD_UEP_TX_CTRL( N ) (*((volatile uint8_t *)( USBFSD_UEP_CTL_BASE + N * 0x04 ))) -#define USBFSD_UEP_RX_CTRL( N ) (*((volatile uint8_t *)( USBFSD_UEP_CTL_BASE + N * 0x04 + 1 ))) +#define USBFSD_UEP_RX_CTRL( N ) (*((volatile uint8_t *)( USBFSD_UEP_CTL_BASE + N * 0x04 ))) #define USBFSD_UEP_DMA( N ) (*((volatile uint32_t *)( USBFSD_UEP_DMA_BASE + N * 0x04 ))) #define USBFSD_UEP_BUF( N ) ((uint8_t *)(*((volatile uint32_t *)( USBFSD_UEP_DMA_BASE + N * 0x04 ))) + 0x20000000) #define USBFSD_UEP_TLEN( N ) (*((volatile uint16_t *)( USBFSD_UEP_LEN_BASE + N * 0x04 ))) - - /* R8_UEPn_TX_CTRL */ #define USBFS_UEP_T_AUTO_TOG (1<<4) // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle #define USBFS_UEP_T_TOG (1<<6) // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1 @@ -92,6 +83,75 @@ extern volatile uint8_t USBFS_Endp_Busy[ ]; #define USBFS_USB_ADDR_MASK 0x7F + +#define DEF_USBD_UEP0_SIZE 64 /* usb hs/fs device end-point 0 size */ +#define EP_SIZE 64 + +#define DEF_UEP_IN 0x80 +#define DEF_UEP_OUT 0x00 +#define DEF_UEP_BUSY 0x01 +#define DEF_UEP_FREE 0x00 + +#define DEF_UEP0 0 +#define DEF_UEP1 1 +#define DEF_UEP2 2 +#define DEF_UEP3 3 +#define DEF_UEP4 4 +#define DEF_UEP5 5 +#define DEF_UEP6 6 +#define DEF_UEP7 7 +#define NUM_EP 8 + +// Hardware specific + +#define EP1_T_EN (1<<6) +#define EP2_T_EN (1<<2) +#define EP3_T_EN (1<<6) +#define EP4_T_EN (1<<2) +#define EP1_R_EN (1<<7) +#define EP2_R_EN (1<<3) +#define EP3_R_EN (1<<7) +#define EP4_R_EN (1<<3) + + +/* R8_USB_CTRL */ +#define USBFS_UC_HOST_MODE 0x80 +#define USBFS_UC_LOW_SPEED 0x40 +#define USBFS_UC_DEV_PU_EN 0x20 +#define USBFS_UC_SYS_CTRL_MASK 0x30 +#define USBFS_UC_SYS_CTRL0 0x00 +#define USBFS_UC_SYS_CTRL1 0x10 +#define USBFS_UC_SYS_CTRL2 0x20 +#define USBFS_UC_SYS_CTRL3 0x30 +#define USBFS_UC_INT_BUSY 0x08 +#define USBFS_UC_RESET_SIE 0x04 +#define USBFS_UC_CLR_ALL 0x02 +#define USBFS_UC_DMA_EN 0x01 + +/* R8_USB_INT_EN */ +#define USBFS_UIE_DEV_SOF 0x80 +#define USBFS_UIE_DEV_NAK 0x40 +#define USBFS_UIE_FIFO_OV 0x10 +#define USBFS_UIE_HST_SOF 0x08 +#define USBFS_UIE_SUSPEND 0x04 +#define USBFS_UIE_TRANSFER 0x02 +#define USBFS_UIE_DETECT 0x01 +#define USBFS_UIE_BUS_RST 0x01 + +/* R8_USB_DEV_AD */ +#define USBFS_UDA_GP_BIT 0x80 +#define USBFS_USB_ADDR_MASK 0x7F + +/* R8_USB_MIS_ST */ +#define USBFS_UMS_SOF_PRES 0x80 +#define USBFS_UMS_SOF_ACT 0x40 +#define USBFS_UMS_SIE_FREE 0x20 +#define USBFS_UMS_R_FIFO_RDY 0x10 +#define USBFS_UMS_BUS_RESET 0x08 +#define USBFS_UMS_SUSPEND 0x04 +#define USBFS_UMS_DM_LEVEL 0x02 +#define USBFS_UMS_DEV_ATTACH 0x01 + /* USB Setup Request */ typedef struct __attribute__((packed)) _USB_SETUP_REQ { diff --git a/examples_x035/usbdevice.incomplete/usbdevice.c b/examples_x035/usbdevice.incomplete/usbdevice.c index 2dbd754c..aa107175 100644 --- a/examples_x035/usbdevice.incomplete/usbdevice.c +++ b/examples_x035/usbdevice.incomplete/usbdevice.c @@ -29,8 +29,28 @@ void USBFS_IRQHandler(); //extern int USBFS_IRQHandler; while(1) { - printf( "%lu %lu %lu\n", USBDEBUG0, USBDEBUG1, USBDEBUG2 ); + printf( "%lu %lu %lu %d %d\n", USBDEBUG0, USBDEBUG1, USBDEBUG2, USBFS_Endp_Busy[0], USBFS_Endp_Busy[1] ); USBFS_Poll(); + int i; + //printf( "!! %d %d %d\n", NUM_EP, USBFS_Endp_Busy[0], USBFS_Endp_Busy[1] ); + for( i = 1; i < 3; i++ ) + { + if( !USBFS_Endp_Busy[i] ) + { + +/* +USBDEBUG0+= 100; + /* tx length */ + //memset( USBFSD_UEP_BUF( i ), 0xaa, 16 ); +// USBFSD_UEP_TLEN( i ) = 16; + // USBFSD_UEP_TX_CTRL( i ) = ( USBFSD_UEP_TX_CTRL( i ) & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_ACK; + // USBFS_Endp_Busy[i] = 1; + + char pbuf[16] = { 0 }; + uint8_t r = USBFS_Endp_DataUp( i, pbuf, 8, DEF_UEP_CPY_LOAD); +//USBDEBUG1+=r; + } + } } #if 0 From 6d49c00091bc90c4a30a9d27a2175aaeba053ca4 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sun, 21 Apr 2024 02:16:44 -0700 Subject: [PATCH 12/31] Working device. --- examples_x035/usbdevice.incomplete/usbdevice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_x035/usbdevice.incomplete/usbdevice.c b/examples_x035/usbdevice.incomplete/usbdevice.c index aa107175..2220c2b8 100644 --- a/examples_x035/usbdevice.incomplete/usbdevice.c +++ b/examples_x035/usbdevice.incomplete/usbdevice.c @@ -47,7 +47,7 @@ USBDEBUG0+= 100; // USBFS_Endp_Busy[i] = 1; char pbuf[16] = { 0 }; - uint8_t r = USBFS_Endp_DataUp( i, pbuf, 8, DEF_UEP_CPY_LOAD); + uint8_t r = USBFS_Endp_DataUp( i, pbuf, (i==1)?8:4, DEF_UEP_CPY_LOAD); //USBDEBUG1+=r; } } From 15f614969f072b9b80f82be8f1821c5318429060 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sun, 21 Apr 2024 06:38:56 -0400 Subject: [PATCH 13/31] Stage 1 of cleanup complete. --- ch32v003fun/ch32v003fun.h | 128 +++++ examples_x035/usbdevice.incomplete/Makefile | 2 +- .../usbdevice.incomplete/descriptor.c | 266 ----------- .../usbdevice.incomplete/descriptor.h | 92 ---- examples_x035/usbdevice.incomplete/fsusb.c | 332 ++++--------- examples_x035/usbdevice.incomplete/fsusb.h | 442 ++---------------- .../usbdevice.incomplete/usbdevice.c | 6 +- 7 files changed, 262 insertions(+), 1006 deletions(-) delete mode 100644 examples_x035/usbdevice.incomplete/descriptor.c delete mode 100644 examples_x035/usbdevice.incomplete/descriptor.h diff --git a/ch32v003fun/ch32v003fun.h b/ch32v003fun/ch32v003fun.h index d836f673..844b74ed 100644 --- a/ch32v003fun/ch32v003fun.h +++ b/ch32v003fun/ch32v003fun.h @@ -1435,6 +1435,7 @@ typedef struct __attribute__((packed)) __IO uint8_t RESERVED52; __IO uint16_t HOST_SPLIT_DATA; } USBHSH_TypeDef; + #endif // #if defined(CH32V30x) /* USBFS Registers */ @@ -1775,6 +1776,133 @@ typedef struct #define UDM_PUE_10 (0b10<<0) #define UDM_PUE_11 (0b11<<0) + +#define USBFSD_UEP_MOD_BASE 0x4002340C +#define USBFSD_UEP_DMA_BASE 0x40023410 +#define USBFSD_UEP_LEN_BASE 0x40023420 +#define USBFSD_UEP_CTL_BASE 0x40023422 +#define USBFSD_UEP_RX_EN 0x08 +#define USBFSD_UEP_TX_EN 0x04 +#define USBFSD_UEP_BUF_MOD 0x01 +#define DEF_UEP_DMA_LOAD 0 /* Direct the DMA address to the data to be processed */ +#define DEF_UEP_CPY_LOAD 1 /* Use memcpy to move data to a buffer */ +#define USBFSD_UEP_MOD( N ) (*((volatile uint8_t *)( USBFSD_UEP_MOD_BASE + N ))) +#define USBFSD_UEP_TX_CTRL( N ) (*((volatile uint8_t *)( USBFSD_UEP_CTL_BASE + N * 0x04 ))) +#define USBFSD_UEP_RX_CTRL( N ) (*((volatile uint8_t *)( USBFSD_UEP_CTL_BASE + N * 0x04 ))) +#define USBFSD_UEP_DMA( N ) (*((volatile uint32_t *)( USBFSD_UEP_DMA_BASE + N * 0x04 ))) +#define USBFSD_UEP_BUF( N ) ((uint8_t *)(*((volatile uint32_t *)( USBFSD_UEP_DMA_BASE + N * 0x04 ))) + 0x20000000) +#define USBFSD_UEP_TLEN( N ) (*((volatile uint16_t *)( USBFSD_UEP_LEN_BASE + N * 0x04 ))) + +/* R8_UEPn_TX_CTRL */ +#define USBFS_UEP_T_AUTO_TOG (1<<4) // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle +#define USBFS_UEP_T_TOG (1<<6) // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1 +#define USBFS_UEP_T_RES_MASK (3<<0) // bit mask of handshake response type for USB endpoint X transmittal (IN) +#define USBFS_UEP_T_RES_ACK (0<<1) +#define USBFS_UEP_T_RES_NONE (1<<0) +#define USBFS_UEP_T_RES_NAK (1<<1) +#define USBFS_UEP_T_RES_STALL (3<<0) +// bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmittal (IN) +// 00: DATA0 or DATA1 then expecting ACK (ready) +// 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions +// 10: NAK (busy) +// 11: STALL (error) +// host aux setup + +/* R8_UEPn_RX_CTRL, n=0-7 */ +#define USBFS_UEP_R_AUTO_TOG (1<<4) // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle +#define USBFS_UEP_R_TOG (1<<7) // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1 +#define USBFS_UEP_R_RES_MASK (3<<2) // bit mask of handshake response type for USB endpoint X receiving (OUT) +#define USBFS_UEP_R_RES_ACK (0<<3) +#define USBFS_UEP_R_RES_NONE (1<<2) +#define USBFS_UEP_R_RES_NAK (1<<3) +#define USBFS_UEP_R_RES_STALL (3<<2) + + +#define EP1_T_EN (1<<6) +#define EP2_T_EN (1<<2) +#define EP3_T_EN (1<<6) +#define EP4_T_EN (1<<2) +#define EP1_R_EN (1<<7) +#define EP2_R_EN (1<<3) +#define EP3_R_EN (1<<7) +#define EP4_R_EN (1<<3) + + +/* R8_USB_CTRL */ +#define USBFS_UC_HOST_MODE 0x80 +#define USBFS_UC_LOW_SPEED 0x40 +#define USBFS_UC_DEV_PU_EN 0x20 +#define USBFS_UC_SYS_CTRL_MASK 0x30 +#define USBFS_UC_SYS_CTRL0 0x00 +#define USBFS_UC_SYS_CTRL1 0x10 +#define USBFS_UC_SYS_CTRL2 0x20 +#define USBFS_UC_SYS_CTRL3 0x30 +#define USBFS_UC_INT_BUSY 0x08 +#define USBFS_UC_RESET_SIE 0x04 +#define USBFS_UC_CLR_ALL 0x02 +#define USBFS_UC_DMA_EN 0x01 + +/* R8_USB_INT_EN */ +#define USBFS_UIE_DEV_SOF 0x80 +#define USBFS_UIE_DEV_NAK 0x40 +#define USBFS_UIE_FIFO_OV 0x10 +#define USBFS_UIE_HST_SOF 0x08 +#define USBFS_UIE_SUSPEND 0x04 +#define USBFS_UIE_TRANSFER 0x02 +#define USBFS_UIE_DETECT 0x01 +#define USBFS_UIE_BUS_RST 0x01 + +/* R8_USB_DEV_AD */ +#define USBFS_UDA_GP_BIT 0x80 +#define USBFS_USB_ADDR_MASK 0x7F + +/* R8_USB_MIS_ST */ +#define USBFS_UMS_SOF_PRES 0x80 +#define USBFS_UMS_SOF_ACT 0x40 +#define USBFS_UMS_SIE_FREE 0x20 +#define USBFS_UMS_R_FIFO_RDY 0x10 +#define USBFS_UMS_BUS_RESET 0x08 +#define USBFS_UMS_SUSPEND 0x04 +#define USBFS_UMS_DM_LEVEL 0x02 +#define USBFS_UMS_DEV_ATTACH 0x01 + + + + +#define USBFS_UDA_GP_BIT 0x80 +#define USBFS_USB_ADDR_MASK 0x7F + +#define DEF_USBD_UEP0_SIZE 64 /* usb hs/fs device end-point 0 size */ +#define UEP_SIZE 64 + +#define DEF_UEP_IN 0x80 +#define DEF_UEP_OUT 0x00 +#define DEF_UEP_BUSY 0x01 +#define DEF_UEP_FREE 0x00 + +#define DEF_UEP0 0 +#define DEF_UEP1 1 +#define DEF_UEP2 2 +#define DEF_UEP3 3 +#define DEF_UEP4 4 +#define DEF_UEP5 5 +#define DEF_UEP6 6 +#define DEF_UEP7 7 +#define UNUM_EP 8 + + +#define UDP_PUE_MASK 0x0000000C +#define UDP_PUE_DISABLE 0x00000000 +#define UDP_PUE_35UA 0x00000004 +#define UDP_PUE_10K 0x00000008 +#define UDP_PUE_1K5 0x0000000C + +#define UDM_PUE_MASK 0x00000003 +#define UDM_PUE_DISABLE 0x00000000 +#define UDM_PUE_35UA 0x00000001 +#define UDM_PUE_10K 0x00000002 +#define UDM_PUE_1K5 0x00000003 + /* USB Host Mode */ typedef struct diff --git a/examples_x035/usbdevice.incomplete/Makefile b/examples_x035/usbdevice.incomplete/Makefile index adabf99a..e28de11d 100644 --- a/examples_x035/usbdevice.incomplete/Makefile +++ b/examples_x035/usbdevice.incomplete/Makefile @@ -2,7 +2,7 @@ all : flash TARGET:=usbdevice TARGET_MCU:=CH32X035 -ADDITIONAL_C_FILES:=fsusb.c descriptor.c +ADDITIONAL_C_FILES:=fsusb.c include ../../ch32v003fun/ch32v003fun.mk diff --git a/examples_x035/usbdevice.incomplete/descriptor.c b/examples_x035/usbdevice.incomplete/descriptor.c deleted file mode 100644 index 2d1b2f6d..00000000 --- a/examples_x035/usbdevice.incomplete/descriptor.c +++ /dev/null @@ -1,266 +0,0 @@ -/********************************** (C) COPYRIGHT ******************************* - * File Name : composite_km_desc.h - * Author : WCH - * Version : V1.0.0 - * Date : 2023/04/06 - * Description : All descriptors for the keyboard and mouse composite device. -********************************************************************************* -* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. -* Attention: This software (modified or not) and binary are used for -* microcontroller manufactured by Nanjing Qinheng Microelectronics. -*******************************************************************************/ - - -/*******************************************************************************/ -/* Header File */ -#include "descriptor.h" - -/*******************************************************************************/ -/* Device Descriptor */ -const uint8_t MyDevDescr[ ] = -{ - 0x12, // bLength - 0x01, // bDescriptorType - 0x00, 0x02, // bcdUSB - 0x00, // bDeviceClass - 0x00, // bDeviceSubClass - 0x00, // bDeviceProtocol - DEF_USBD_UEP0_SIZE, // bMaxPacketSize0 - (uint8_t)DEF_USB_VID, (uint8_t)( DEF_USB_VID >> 8 ), // idVendor - (uint8_t)DEF_USB_PID, (uint8_t)( DEF_USB_PID >> 8 ), // idProduct - 0x00, DEF_IC_PRG_VER, // bcdDevice - 0x01, // iManufacturer - 0x02, // iProduct - 0x03, // iSerialNumber - 0x01, // bNumConfigurations -}; - -/* Configuration Descriptor Set */ -const uint8_t MyCfgDescr[ ] = -{ - /* Configuration Descriptor */ - 0x09, // bLength - 0x02, // bDescriptorType - 0x3B, 0x00, // wTotalLength - 0x02, // bNumInterfaces - 0x01, // bConfigurationValue - 0x00, // iConfiguration - 0xA0, // bmAttributes: Bus Powered; Remote Wakeup - 0x32, // MaxPower: 100mA - - /* Interface Descriptor (Keyboard) */ - 0x09, // bLength - 0x04, // bDescriptorType - 0x00, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x01, // bNumEndpoints - 0x03, // bInterfaceClass - 0x01, // bInterfaceSubClass - 0x01, // bInterfaceProtocol: Keyboard - 0x00, // iInterface - - /* HID Descriptor (Keyboard) */ - 0x09, // bLength - 0x21, // bDescriptorType - 0x11, 0x01, // bcdHID - 0x00, // bCountryCode - 0x01, // bNumDescriptors - 0x22, // bDescriptorType - 0x3E, 0x00, // wDescriptorLength - - /* Endpoint Descriptor (Keyboard) */ - 0x07, // bLength - 0x05, // bDescriptorType - 0x81, // bEndpointAddress: IN Endpoint 1 - 0x03, // bmAttributes - 0x08, 0x00, // wMaxPacketSize - 0x0A, // bInterval: 10mS - - /* Interface Descriptor (Mouse) */ - 0x09, // bLength - 0x04, // bDescriptorType - 0x01, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x01, // bNumEndpoints - 0x03, // bInterfaceClass - 0x01, // bInterfaceSubClass - 0x02, // bInterfaceProtocol: Mouse - 0x00, // iInterface - - /* HID Descriptor (Mouse) */ - 0x09, // bLength - 0x21, // bDescriptorType - 0x10, 0x01, // bcdHID - 0x00, // bCountryCode - 0x01, // bNumDescriptors - 0x22, // bDescriptorType - 0x34, 0x00, // wDescriptorLength - - /* Endpoint Descriptor (Mouse) */ - 0x07, // bLength - 0x05, // bDescriptorType - 0x82, // bEndpointAddress: IN Endpoint 2 - 0x03, // bmAttributes - 0x08, 0x00, // wMaxPacketSize - 0x01 // bInterval: 1mS -}; - -/* Keyboard Report Descriptor */ -const uint8_t KeyRepDesc[ ] = -{ - 0x05, 0x01, // Usage Page (Generic Desktop) - 0x09, 0x06, // Usage (Keyboard) - 0xA1, 0x01, // Collection (Application) - 0x05, 0x07, // Usage Page (Key Codes) - 0x19, 0xE0, // Usage Minimum (224) - 0x29, 0xE7, // Usage Maximum (231) - 0x15, 0x00, // Logical Minimum (0) - 0x25, 0x01, // Logical Maximum (1) - 0x75, 0x01, // Report Size (1) - 0x95, 0x08, // Report Count (8) - 0x81, 0x02, // Input (Data,Variable,Absolute) - 0x95, 0x01, // Report Count (1) - 0x75, 0x08, // Report Size (8) - 0x81, 0x01, // Input (Constant) - 0x95, 0x03, // Report Count (3) - 0x75, 0x01, // Report Size (1) - 0x05, 0x08, // Usage Page (LEDs) - 0x19, 0x01, // Usage Minimum (1) - 0x29, 0x03, // Usage Maximum (3) - 0x91, 0x02, // Output (Data,Variable,Absolute) - 0x95, 0x05, // Report Count (5) - 0x75, 0x01, // Report Size (1) - 0x91, 0x01, // Output (Constant,Array,Absolute) - 0x95, 0x06, // Report Count (6) - 0x75, 0x08, // Report Size (8) - 0x26, 0xFF, 0x00, // Logical Maximum (255) - 0x05, 0x07, // Usage Page (Key Codes) - 0x19, 0x00, // Usage Minimum (0) - 0x29, 0x91, // Usage Maximum (145) - 0x81, 0x00, // Input(Data,Array,Absolute) - 0xC0 // End Collection -}; - -/* Mouse Report Descriptor */ -const uint8_t MouseRepDesc[ ] = -{ - 0x05, 0x01, // Usage Page (Generic Desktop) - 0x09, 0x02, // Usage (Mouse) - 0xA1, 0x01, // Collection (Application) - 0x09, 0x01, // Usage (Pointer) - 0xA1, 0x00, // Collection (Physical) - 0x05, 0x09, // Usage Page (Button) - 0x19, 0x01, // Usage Minimum (Button 1) - 0x29, 0x03, // Usage Maximum (Button 3) - 0x15, 0x00, // Logical Minimum (0) - 0x25, 0x01, // Logical Maximum (1) - 0x75, 0x01, // Report Size (1) - 0x95, 0x03, // Report Count (3) - 0x81, 0x02, // Input (Data,Variable,Absolute) - 0x75, 0x05, // Report Size (5) - 0x95, 0x01, // Report Count (1) - 0x81, 0x01, // Input (Constant,Array,Absolute) - 0x05, 0x01, // Usage Page (Generic Desktop) - 0x09, 0x30, // Usage (X) - 0x09, 0x31, // Usage (Y) - 0x09, 0x38, // Usage (Wheel) - 0x15, 0x81, // Logical Minimum (-127) - 0x25, 0x7F, // Logical Maximum (127) - 0x75, 0x08, // Report Size (8) - 0x95, 0x03, // Report Count (3) - 0x81, 0x06, // Input (Data,Variable,Relative) - 0xC0, // End Collection - 0xC0 // End Collection -}; - -/* Qualifier Descriptor */ -const uint8_t MyQuaDesc[ ] = -{ - 0x0A, // bLength - 0x06, // bDescriptorType - 0x00, 0x02, // bcdUSB - 0x00, // bDeviceClass - 0x00, // bDeviceSubClass - 0x00, // bDeviceProtocol - 0x40, // bMaxPacketSize0 - 0x00, // bNumConfigurations - 0x00 // bReserved -}; - -/* Language Descriptor */ -const uint8_t MyLangDescr[ ] = -{ - 0x04, - 0x03, - 0x09, - 0x04 -}; - -/* Manufacturer Descriptor */ -const uint8_t MyManuInfo[ ] = -{ - 0x0E, - 0x03, - 'w', - 0, - 'c', - 0, - 'h', - 0, - '.', - 0, - 'c', - 0, - 'n', - 0 -}; - -/* Product Information */ -const uint8_t MyProdInfo[ ] = -{ - 0x12, - 0x03, - 'C', - 0, - 'H', - 0, - '3', - 0, - '2', - 0, - 'x', - 0, - '0', - 0, - '3', - 0, - '5', - 0 -}; - -/* Serial Number Information */ -const uint8_t MySerNumInfo[ ] = -{ - 0x16, - 0x03, - '0', - 0, - '1', - 0, - '2', - 0, - '3', - 0, - '4', - 0, - '5', - 0, - '6', - 0, - '7', - 0, - '8', - 0, - '9', - 0 -}; diff --git a/examples_x035/usbdevice.incomplete/descriptor.h b/examples_x035/usbdevice.incomplete/descriptor.h deleted file mode 100644 index b746eecf..00000000 --- a/examples_x035/usbdevice.incomplete/descriptor.h +++ /dev/null @@ -1,92 +0,0 @@ -/********************************** (C) COPYRIGHT ******************************* - * File Name : usbd_descriptor.h - * Author : WCH - * Version : V1.0.0 - * Date : 2023/04/06 - * Description : All descriptors for the keyboard and mouse composite device. -********************************************************************************* -* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. -* Attention: This software (modified or not) and binary are used for -* microcontroller manufactured by Nanjing Qinheng Microelectronics. -*******************************************************************************/ - - -#ifndef __USBD_DESC_H -#define __USBD_DESC_H - -/*******************************************************************************/ -/* Header File */ -#include "stdint.h" - -/*******************************************************************************/ -/* Macro Definition */ - -/* File Version */ -#define DEF_FILE_VERSION 0x01 - -/* USB Device Info */ -#define DEF_USB_VID 0x1A86 -#define DEF_USB_PID 0xFE00 - -/* USB Device Descriptor, Device Serial Number(bcdDevice) */ -#define DEF_IC_PRG_VER DEF_FILE_VERSION - -/* USB Device Endpoint Size */ -#define DEF_USBD_UEP0_SIZE 64 /* usb hs/fs device end-point 0 size */ -/* HS */ -#define DEF_USBD_HS_PACK_SIZE 512 /* usb hs device max bluk/int pack size */ -#define DEF_USBD_HS_ISO_PACK_SIZE 1024 /* usb hs device max iso pack size */ -/* FS */ -#define DEF_USBD_FS_PACK_SIZE 64 /* usb fs device max bluk/int pack size */ -#define DEF_USBD_FS_ISO_PACK_SIZE 1023 /* usb fs device max iso pack size */ -/* LS */ -#define DEf_USBD_LS_UEP0_SIZE 8 /* usb ls device end-point 0 size */ -#define DEF_USBD_LS_PACK_SIZE 64 /* usb ls device max int pack size */ - -/* USB Device Endpoint1-6 Size */ -/* HS */ -#define DEF_USB_EP1_HS_SIZE DEF_USBD_HS_PACK_SIZE -#define DEF_USB_EP2_HS_SIZE DEF_USBD_HS_PACK_SIZE -#define DEF_USB_EP3_HS_SIZE DEF_USBD_HS_PACK_SIZE -#define DEF_USB_EP4_HS_SIZE DEF_USBD_HS_PACK_SIZE -#define DEF_USB_EP5_HS_SIZE DEF_USBD_HS_PACK_SIZE -#define DEF_USB_EP6_HS_SIZE DEF_USBD_HS_PACK_SIZE -/* FS */ -#define DEF_USB_EP1_FS_SIZE DEF_USBD_FS_PACK_SIZE -#define DEF_USB_EP2_FS_SIZE DEF_USBD_FS_PACK_SIZE -#define DEF_USB_EP3_FS_SIZE DEF_USBD_FS_PACK_SIZE -#define DEF_USB_EP4_FS_SIZE DEF_USBD_FS_PACK_SIZE -#define DEF_USB_EP5_FS_SIZE DEF_USBD_FS_PACK_SIZE -#define DEF_USB_EP6_FS_SIZE DEF_USBD_FS_PACK_SIZE -/* LS */ -/* ... */ - -/* USB Device Descriptor Length */ -/* Note: If a descriptor does not exist, set the length to 0. */ -#define DEF_USBD_DEVICE_DESC_LEN ( (uint16_t)MyDevDescr[ 0 ] ) -#define DEF_USBD_CONFIG_DESC_LEN ( (uint16_t)MyCfgDescr[ 2 ] + ( (uint16_t)MyCfgDescr[ 3 ] << 8 ) ) -#define DEF_USBD_REPORT_DESC_LEN_KB 0x3E -#define DEF_USBD_REPORT_DESC_LEN_MS 0x34 -#define DEF_USBD_LANG_DESC_LEN ( (uint16_t)MyLangDescr[ 0 ] ) -#define DEF_USBD_MANU_DESC_LEN ( (uint16_t)MyManuInfo[ 0 ] ) -#define DEF_USBD_PROD_DESC_LEN ( (uint16_t)MyProdInfo[ 0 ] ) -#define DEF_USBD_SN_DESC_LEN ( (uint16_t)MySerNumInfo[ 0 ] ) -#define DEF_USBD_QUALFY_DESC_LEN ( (uint16_t)MyQuaDesc[ 0 ]) -#define DEF_USBD_BOS_DESC_LEN 0 -#define DEF_USBD_FS_OTH_DESC_LEN 0 -#define DEF_USBD_HS_OTH_DESC_LEN 0 - - -/*******************************************************************************/ -/* Descriptor Declaration */ -extern const uint8_t MyDevDescr[ ]; -extern const uint8_t MyCfgDescr[ ]; -extern const uint8_t KeyRepDesc[ ]; -extern const uint8_t MouseRepDesc[ ]; -extern const uint8_t MyQuaDesc[ ]; -extern const uint8_t MyLangDescr[ ]; -extern const uint8_t MyManuInfo[ ]; -extern const uint8_t MyProdInfo[ ]; -extern const uint8_t MySerNumInfo[ ]; - -#endif diff --git a/examples_x035/usbdevice.incomplete/fsusb.c b/examples_x035/usbdevice.incomplete/fsusb.c index ea8d03ba..319018c4 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.c +++ b/examples_x035/usbdevice.incomplete/fsusb.c @@ -5,6 +5,9 @@ uint32_t USBDEBUG0, USBDEBUG1, USBDEBUG2; + +struct _USBState FSUSBCTX; + // based on https://github.com/openwch/ch32x035/tree/main/EVT/EXAM/USB/USBFS/DEVICE/CompositeKM/User // Mask for the combined USBFSD->INT_FG + USBFSD->INT_ST @@ -16,94 +19,20 @@ uint32_t USBDEBUG0, USBDEBUG1, USBDEBUG2; #define CRB_UIF_SUSPEND (1<<2) #define CRB_UIF_TRANSFER (1<<1) #define CRB_UIF_BUS_RST (1<<0) -#define CSETUP_ACT (1<<15) +#define CSETUP_ACT (1<<15) #define CRB_UIS_TOG_OK (1<<14) #define CMASK_UIS_TOKEN (3<<12) #define CMASK_UIS_ENDP (0xf<<8) -#define CUIS_TOKEN_OUT 0x0 -#define CUIS_TOKEN_SOF 0x1 -#define CUIS_TOKEN_IN 0x2 -#define CUIS_TOKEN_SETUP 0x3 - - -// Hardware specific - -/* R8_USB_CTRL */ -#define USBFS_UC_HOST_MODE 0x80 -#define USBFS_UC_LOW_SPEED 0x40 -#define USBFS_UC_DEV_PU_EN 0x20 -#define USBFS_UC_SYS_CTRL_MASK 0x30 -#define USBFS_UC_SYS_CTRL0 0x00 -#define USBFS_UC_SYS_CTRL1 0x10 -#define USBFS_UC_SYS_CTRL2 0x20 -#define USBFS_UC_SYS_CTRL3 0x30 -#define USBFS_UC_INT_BUSY 0x08 -#define USBFS_UC_RESET_SIE 0x04 -#define USBFS_UC_CLR_ALL 0x02 -#define USBFS_UC_DMA_EN 0x01 - -/* R8_USB_INT_EN */ -#define USBFS_UIE_DEV_SOF 0x80 -#define USBFS_UIE_DEV_NAK 0x40 -#define USBFS_UIE_FIFO_OV 0x10 -#define USBFS_UIE_HST_SOF 0x08 -#define USBFS_UIE_SUSPEND 0x04 -#define USBFS_UIE_TRANSFER 0x02 -#define USBFS_UIE_DETECT 0x01 -#define USBFS_UIE_BUS_RST 0x01 - -/* R8_USB_DEV_AD */ -#define USBFS_UDA_GP_BIT 0x80 -#define USBFS_USB_ADDR_MASK 0x7F - -/* R8_USB_MIS_ST */ -#define USBFS_UMS_SOF_PRES 0x80 -#define USBFS_UMS_SOF_ACT 0x40 -#define USBFS_UMS_SIE_FREE 0x20 -#define USBFS_UMS_R_FIFO_RDY 0x10 -#define USBFS_UMS_BUS_RESET 0x08 -#define USBFS_UMS_SUSPEND 0x04 -#define USBFS_UMS_DM_LEVEL 0x02 -#define USBFS_UMS_DEV_ATTACH 0x01 - -// XXX TODO: Put these in a struct. - -/* Setup Request */ -volatile uint8_t USBFS_SetupReqCode; -volatile uint8_t USBFS_SetupReqType; -volatile uint16_t USBFS_SetupReqValue; -volatile uint16_t USBFS_SetupReqIndex; -volatile uint16_t USBFS_SetupReqLen; - -/* USB Device Status */ -volatile uint8_t USBFS_DevConfig; -volatile uint8_t USBFS_DevAddr; -volatile uint8_t USBFS_DevSleepStatus; -volatile uint8_t USBFS_DevEnumStatus; - -/* Endpoint Buffer */ -__attribute__ ((aligned(4))) uint8_t USBFS_EP0_Buf[64]; -__attribute__ ((aligned(4))) uint8_t USBFS_EP1_Buf[64]; -__attribute__ ((aligned(4))) uint8_t USBFS_EP2_Buf[64]; -#define pUSBFS_SetupReqPak ((PUSB_SETUP_REQ)USBFS_EP0_Buf) - - -int USBFS_HidIdle[2]; -int USBFS_HidProtocol[2]; - -const uint8_t *pUSBFS_Descr; - -/* USB IN Endpoint Busy Flag */ -volatile uint8_t USBFS_Endp_Busy[NUM_EP]; - - +#define CUIS_TOKEN_OUT 0x0 +#define CUIS_TOKEN_SOF 0x1 +#define CUIS_TOKEN_IN 0x2 +#define CUIS_TOKEN_SETUP 0x3 void USBFS_IRQHandler() __attribute__((section(".text.vector_handler"))) __attribute__((interrupt)); - void USBFS_IRQHandler() { // Based on https://github.com/openwch/ch32x035/blob/main/EVT/EXAM/USB/USBFS/DEVICE/CompositeKM/User/ch32x035_usbfs_device.c @@ -111,7 +40,7 @@ void USBFS_IRQHandler() // Combined FG + ST flag. uint16_t intfgst = *(uint16_t*)(&USBFS->INT_FG); int len = 0, errflag = 0; - + struct _USBState * ctx = &FSUSBCTX; GPIOA->BSHR = 1; // TODO: Check if needs to be do-while to re-check. @@ -120,9 +49,6 @@ void USBFS_IRQHandler() int token = ( intfgst & CMASK_UIS_TOKEN) >> 12; int ep = ( intfgst & CMASK_UIS_ENDP ) >> 8; - if( ep == 2 ) - USBDEBUG1++; - switch ( token ) { case CUIS_TOKEN_IN: @@ -130,30 +56,30 @@ void USBFS_IRQHandler() { /* end-point 0 data in interrupt */ case DEF_UEP0: - if( USBFS_SetupReqLen == 0 ) + if( ctx->USBFS_SetupReqLen == 0 ) { USBFS->UEP0_CTRL_H = USBFS_UEP_R_TOG | USBFS_UEP_R_RES_ACK; } - if ( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) + if ( ( ctx->USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) { /* Non-standard request endpoint 0 Data upload, noted by official docs, but I don't think this would ever really be used. */ } else { - switch( USBFS_SetupReqCode ) + switch( FSUSBCTX.USBFS_SetupReqCode ) { case USB_GET_DESCRIPTOR: - len = USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen; - memcpy( USBFS_EP0_Buf, pUSBFS_Descr, len ); - USBFS_SetupReqLen -= len; - pUSBFS_Descr += len; + len = ctx->USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : ctx->USBFS_SetupReqLen; + memcpy( ctx->USBFS_EP0_Buf, ctx->pUSBFS_Descr, len ); + ctx->USBFS_SetupReqLen -= len; + ctx->pUSBFS_Descr += len; USBFS->UEP0_TX_LEN = len; USBFS->UEP0_CTRL_H ^= USBFS_UEP_T_TOG; break; case USB_SET_ADDRESS: - USBFS->DEV_ADDR = ( USBFS->DEV_ADDR & USBFS_UDA_GP_BIT ) | USBFS_DevAddr; + USBFS->DEV_ADDR = ( USBFS->DEV_ADDR & USBFS_UDA_GP_BIT ) | ctx->USBFS_DevAddr; break; default: @@ -166,16 +92,14 @@ void USBFS_IRQHandler() case DEF_UEP1: USBFS->UEP1_CTRL_H = ( USBFS->UEP1_CTRL_H & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_NAK; USBFS->UEP1_CTRL_H ^= USBFS_UEP_T_TOG; - USBFS_Endp_Busy[ DEF_UEP1 ] = 0; - USBDEBUG0++; + ctx->USBFS_Endp_Busy[ DEF_UEP1 ] = 0; break; /* end-point 2 data in interrupt */ case DEF_UEP2: USBFS->UEP2_CTRL_H = ( USBFS->UEP2_CTRL_H & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_NAK; USBFS->UEP2_CTRL_H ^= USBFS_UEP_T_TOG; - USBFS_Endp_Busy[ DEF_UEP2 ] = 0; - USBDEBUG0++; + ctx->USBFS_Endp_Busy[ DEF_UEP2 ] = 0; break; default : @@ -191,16 +115,16 @@ void USBFS_IRQHandler() case DEF_UEP0: if( intfgst & CRB_UIS_TOG_OK ) { - if( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) + if( ( FSUSBCTX.USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) { - if( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) == USB_REQ_TYP_CLASS ) + if( ( FSUSBCTX.USBFS_SetupReqType & USB_REQ_TYP_MASK ) == USB_REQ_TYP_CLASS ) { - switch( USBFS_SetupReqCode ) + switch( FSUSBCTX.USBFS_SetupReqCode ) { case HID_SET_REPORT: //KB_LED_Cur_Status = USBFS_EP0_Buf[ 0 ]; // Do stuff... - USBFS_SetupReqLen = 0; + FSUSBCTX.USBFS_SetupReqLen = 0; break; default: break; @@ -213,7 +137,7 @@ void USBFS_IRQHandler() /* Add your code here */ } } - if( USBFS_SetupReqLen == 0 ) + if( FSUSBCTX.USBFS_SetupReqLen == 0 ) { USBFS->UEP0_TX_LEN = 0; USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK; @@ -230,11 +154,11 @@ void USBFS_IRQHandler() USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG|USBFS_UEP_T_RES_NAK|USBFS_UEP_R_TOG|USBFS_UEP_R_RES_NAK; /* Store All Setup Values */ - USBFS_SetupReqType = pUSBFS_SetupReqPak->bRequestType; - USBFS_SetupReqCode = pUSBFS_SetupReqPak->bRequest; - USBFS_SetupReqLen = pUSBFS_SetupReqPak->wLength; - USBFS_SetupReqValue = pUSBFS_SetupReqPak->wValue; - USBFS_SetupReqIndex = pUSBFS_SetupReqPak->wIndex; + int USBFS_SetupReqType = FSUSBCTX.USBFS_SetupReqType = pUSBFS_SetupReqPak->bmRequestType; + int USBFS_SetupReqCode = FSUSBCTX.USBFS_SetupReqCode = pUSBFS_SetupReqPak->bRequest; + int USBFS_SetupReqLen = FSUSBCTX.USBFS_SetupReqLen = pUSBFS_SetupReqPak->wLength; + int USBFS_SetupReqIndex = pUSBFS_SetupReqPak->wIndex; + int USBFS_IndexValue = FSUSBCTX.USBFS_IndexValue = ( pUSBFS_SetupReqPak->wIndex << 16 ) | pUSBFS_SetupReqPak->wValue; len = 0; errflag = 0; @@ -250,13 +174,13 @@ void USBFS_IRQHandler() case HID_SET_IDLE: if( USBFS_SetupReqIndex < 0x02 ) - USBFS_HidIdle[ USBFS_SetupReqIndex ] = (uint8_t)( USBFS_SetupReqValue >> 8 ); + FSUSBCTX.USBFS_HidIdle[ USBFS_SetupReqIndex ] = (uint8_t)( USBFS_IndexValue >> 8 ); else errflag = 0xFF; break; case HID_SET_PROTOCOL: if ( USBFS_SetupReqIndex < 0x02 ) - USBFS_HidProtocol[USBFS_SetupReqIndex] = (uint8_t)USBFS_SetupReqValue; + FSUSBCTX.USBFS_HidProtocol[USBFS_SetupReqIndex] = (uint8_t)USBFS_IndexValue; else errflag = 0xFF; break; @@ -264,7 +188,7 @@ void USBFS_IRQHandler() case HID_GET_IDLE: if( USBFS_SetupReqIndex < 0x02 ) { - USBFS_EP0_Buf[ 0 ] = USBFS_HidIdle[ USBFS_SetupReqIndex ]; + FSUSBCTX.USBFS_EP0_Buf[ 0 ] = FSUSBCTX.USBFS_HidIdle[ USBFS_SetupReqIndex ]; len = 1; } else @@ -274,7 +198,7 @@ void USBFS_IRQHandler() case HID_GET_PROTOCOL: if( USBFS_SetupReqIndex < 0x02 ) { - USBFS_EP0_Buf[ 0 ] = USBFS_HidProtocol[ USBFS_SetupReqIndex ]; + FSUSBCTX.USBFS_EP0_Buf[ 0 ] = FSUSBCTX.USBFS_HidProtocol[ USBFS_SetupReqIndex ]; len = 1; } else @@ -294,93 +218,22 @@ void USBFS_IRQHandler() { /* get device/configuration/string/report/... descriptors */ case USB_GET_DESCRIPTOR: - switch( (uint8_t)( USBFS_SetupReqValue >> 8 ) ) + { + int match = USBFS_IndexValue; + struct descriptor_list_struct * e = descriptor_list; + struct descriptor_list_struct * e_end = e + DESCRIPTOR_LIST_ENTRIES; + for( ; e != e_end; e++ ) { - /* get usb device descriptor */ - case USB_DESCR_TYP_DEVICE: - pUSBFS_Descr = MyDevDescr; - len = DEF_USBD_DEVICE_DESC_LEN; - break; - - /* get usb configuration descriptor */ - case USB_DESCR_TYP_CONFIG: - pUSBFS_Descr = MyCfgDescr; - len = DEF_USBD_CONFIG_DESC_LEN; - break; - - /* get usb hid descriptor */ - case USB_DESCR_TYP_HID: - if( USBFS_SetupReqIndex == 0x00 ) - { - pUSBFS_Descr = &MyCfgDescr[ 18 ]; - len = 9; - } - else if( USBFS_SetupReqIndex == 0x01 ) - { - pUSBFS_Descr = &MyCfgDescr[ 43 ]; - len = 9; - } - else - { - errflag = 0xFF; - } - break; - - /* get usb report descriptor */ - case USB_DESCR_TYP_REPORT: - if( USBFS_SetupReqIndex == 0x00 ) - { - pUSBFS_Descr = KeyRepDesc; - len = DEF_USBD_REPORT_DESC_LEN_KB; - } - else if( USBFS_SetupReqIndex == 0x01 ) - { - pUSBFS_Descr = MouseRepDesc; - len = DEF_USBD_REPORT_DESC_LEN_MS; - } - else - { - errflag = 0xFF; - } - break; - - /* get usb string descriptor */ - case USB_DESCR_TYP_STRING: - switch( (uint8_t)( USBFS_SetupReqValue & 0xFF ) ) - { - /* Descriptor 0, Language descriptor */ - case DEF_STRING_DESC_LANG: - pUSBFS_Descr = MyLangDescr; - len = DEF_USBD_LANG_DESC_LEN; - break; - - /* Descriptor 1, Manufacturers String descriptor */ - case DEF_STRING_DESC_MANU: - pUSBFS_Descr = MyManuInfo; - len = DEF_USBD_MANU_DESC_LEN; - break; - - /* Descriptor 2, Product String descriptor */ - case DEF_STRING_DESC_PROD: - pUSBFS_Descr = MyProdInfo; - len = DEF_USBD_PROD_DESC_LEN; - break; - - /* Descriptor 3, Serial-number String descriptor */ - case DEF_STRING_DESC_SERN: - pUSBFS_Descr = MySerNumInfo; - len = DEF_USBD_SN_DESC_LEN; - break; - - default: - errflag = 0xFF; - break; - } - break; - - default : - errflag = 0xFF; + if( e->lIndexValue == USBFS_IndexValue ) + { + ctx->pUSBFS_Descr = e->addr; + len = e->length; break; + } + } + if( e == e_end ) + { + errflag = 0xFF; } /* Copy Descriptors to Endp0 DMA buffer */ @@ -389,28 +242,29 @@ void USBFS_IRQHandler() USBFS_SetupReqLen = len; } len = ( USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ) ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen; - memcpy( USBFS_EP0_Buf, pUSBFS_Descr, len ); - pUSBFS_Descr += len; + memcpy( ctx->USBFS_EP0_Buf, ctx->pUSBFS_Descr, len ); + ctx->pUSBFS_Descr += len; break; + } /* Set usb address */ case USB_SET_ADDRESS: - USBFS_DevAddr = (uint8_t)( USBFS_SetupReqValue & 0xFF ); + ctx->USBFS_DevAddr = (uint8_t)( ctx->USBFS_IndexValue & 0xFF ); break; /* Get usb configuration now set */ case USB_GET_CONFIGURATION: - USBFS_EP0_Buf[ 0 ] = USBFS_DevConfig; - if( USBFS_SetupReqLen > 1 ) + ctx->USBFS_EP0_Buf[ 0 ] = ctx->USBFS_DevConfig; + if( ctx->USBFS_SetupReqLen > 1 ) { - USBFS_SetupReqLen = 1; + ctx->USBFS_SetupReqLen = 1; } break; /* Set usb configuration to use */ case USB_SET_CONFIGURATION: - USBFS_DevConfig = (uint8_t)( USBFS_SetupReqValue & 0xFF ); - USBFS_DevEnumStatus = 0x01; + ctx->USBFS_DevConfig = (uint8_t)( ctx->USBFS_IndexValue & 0xFF ); + ctx->USBFS_DevEnumStatus = 0x01; break; /* Clear or disable one usb feature */ @@ -418,10 +272,10 @@ void USBFS_IRQHandler() if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE ) { /* clear one device feature */ - if( (uint8_t)( USBFS_SetupReqValue & 0xFF ) == USB_REQ_FEAT_REMOTE_WAKEUP ) + if( (uint8_t)( USBFS_IndexValue & 0xFF ) == USB_REQ_FEAT_REMOTE_WAKEUP ) { /* clear usb sleep status, device not prepare to sleep */ - USBFS_DevSleepStatus &= ~0x01; + ctx->USBFS_DevSleepStatus &= ~0x01; } else { @@ -430,7 +284,7 @@ void USBFS_IRQHandler() } else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) { - if( (uint8_t)( USBFS_SetupReqValue & 0xFF ) == USB_REQ_FEAT_ENDP_HALT ) + if( (uint8_t)( USBFS_IndexValue & 0xFF ) == USB_REQ_FEAT_ENDP_HALT ) { /* Clear End-point Feature */ switch( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) ) @@ -465,20 +319,15 @@ void USBFS_IRQHandler() case USB_SET_FEATURE: if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE ) { +#if FUSB_SUPPORTS_SLEEP /* Set Device Feature */ - if( (uint8_t)( USBFS_SetupReqValue & 0xFF ) == USB_REQ_FEAT_REMOTE_WAKEUP ) + if( (uint8_t)( USBFS_IndexValue & 0xFF ) == USB_REQ_FEAT_REMOTE_WAKEUP ) { - if( MyCfgDescr[ 7 ] & 0x20 ) - { - /* Set Wake-up flag, device prepare to sleep */ - USBFS_DevSleepStatus |= 0x01; - } - else - { - errflag = 0xFF; - } + /* Set Wake-up flag, device prepare to sleep */ + USBFS_DevSleepStatus |= 0x01; } else +#endif { errflag = 0xFF; } @@ -486,7 +335,7 @@ void USBFS_IRQHandler() else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) { /* Set Endpoint Feature */ - if( (uint8_t)( USBFS_SetupReqValue & 0xFF ) == USB_REQ_FEAT_ENDP_HALT ) + if( (uint8_t)( USBFS_IndexValue & 0xFF ) == USB_REQ_FEAT_ENDP_HALT ) { switch( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) ) { @@ -516,7 +365,7 @@ void USBFS_IRQHandler() /* This request allows the host to select another setting for the specified interface */ case USB_GET_INTERFACE: - USBFS_EP0_Buf[ 0 ] = 0x00; + ctx->USBFS_EP0_Buf[ 0 ] = 0x00; if( USBFS_SetupReqLen > 1 ) { USBFS_SetupReqLen = 1; @@ -528,17 +377,17 @@ void USBFS_IRQHandler() /* host get status of specified device/interface/end-points */ case USB_GET_STATUS: - USBFS_EP0_Buf[ 0 ] = 0x00; - USBFS_EP0_Buf[ 1 ] = 0x00; + ctx->USBFS_EP0_Buf[ 0 ] = 0x00; + ctx->USBFS_EP0_Buf[ 1 ] = 0x00; if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE ) { - if( USBFS_DevSleepStatus & 0x01 ) + if( ctx->USBFS_DevSleepStatus & 0x01 ) { - USBFS_EP0_Buf[ 0 ] = 0x02; + ctx->USBFS_EP0_Buf[ 0 ] = 0x02; } else { - USBFS_EP0_Buf[ 0 ] = 0x00; + ctx->USBFS_EP0_Buf[ 0 ] = 0x00; } } else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) @@ -547,14 +396,14 @@ void USBFS_IRQHandler() { if( ( USBFS->UEP1_CTRL_H & USBFS_UEP_T_RES_MASK ) == USBFS_UEP_T_RES_STALL ) { - USBFS_EP0_Buf[ 0 ] = 0x01; + ctx->USBFS_EP0_Buf[ 0 ] = 0x01; } } else if( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) == ( DEF_UEP_IN | DEF_UEP2 ) ) { if( ( USBFS->UEP2_CTRL_H & USBFS_UEP_T_RES_MASK ) == USBFS_UEP_T_RES_STALL ) { - USBFS_EP0_Buf[ 0 ] = 0x01; + ctx->USBFS_EP0_Buf[ 0 ] = 0x01; } } else @@ -620,10 +469,10 @@ void USBFS_IRQHandler() else if( intfgst & CRB_UIF_BUS_RST ) { /* usb reset interrupt processing */ - USBFS_DevConfig = 0; - USBFS_DevAddr = 0; - USBFS_DevSleepStatus = 0; - USBFS_DevEnumStatus = 0; + ctx->USBFS_DevConfig = 0; + ctx->USBFS_DevAddr = 0; + ctx->USBFS_DevSleepStatus = 0; + ctx->USBFS_DevEnumStatus = 0; USBFS->DEV_ADDR = 0; USBFS_Device_Endp_Init( ); @@ -633,8 +482,8 @@ void USBFS_IRQHandler() /* usb suspend interrupt processing */ if( USBFS->MIS_ST & USBFS_UMS_SUSPEND ) { - USBFS_DevSleepStatus |= 0x02; - if( USBFS_DevSleepStatus == 0x03 ) + ctx->USBFS_DevSleepStatus |= 0x02; + if( ctx->USBFS_DevSleepStatus == 0x03 ) { /* Handling usb sleep here */ //TODO: MCU_Sleep_Wakeup_Operate( ); @@ -642,7 +491,7 @@ void USBFS_IRQHandler() } else { - USBFS_DevSleepStatus &= ~0x02; + ctx->USBFS_DevSleepStatus &= ~0x02; } } @@ -659,18 +508,18 @@ void USBFS_Device_Endp_Init() USBFS->UEP2_3_MOD = RB_UEP2_TX_EN; USBFS->UEP567_MOD = 0; - USBFS->UEP0_DMA = (intptr_t)USBFS_EP0_Buf; - USBFS->UEP1_DMA = (intptr_t)USBFS_EP1_Buf; - USBFS->UEP2_DMA = (intptr_t)USBFS_EP2_Buf; + USBFS->UEP0_DMA = (intptr_t)FSUSBCTX.USBFS_EP0_Buf; + USBFS->UEP1_DMA = (intptr_t)FSUSBCTX.USBFS_EP1_Buf; + USBFS->UEP2_DMA = (intptr_t)FSUSBCTX.USBFS_EP2_Buf; USBFS->UEP0_CTRL_H = USBFS_UEP_R_RES_ACK | USBFS_UEP_T_RES_NAK; USBFS->UEP1_CTRL_H = USBFS_UEP_T_RES_NAK; USBFS->UEP2_CTRL_H = USBFS_UEP_T_RES_NAK; /* Clear End-points Busy Status */ - for(uint8_t i=0; i< sizeof(USBFS_Endp_Busy)/sizeof(USBFS_Endp_Busy[0]); i++ ) + for(uint8_t i=0; i< sizeof(FSUSBCTX.USBFS_Endp_Busy)/sizeof(FSUSBCTX.USBFS_Endp_Busy[0]); i++ ) { - USBFS_Endp_Busy[ i ] = 0; + FSUSBCTX.USBFS_Endp_Busy[ i ] = 0; } } @@ -720,7 +569,12 @@ int FSUSBSetup() // GPIOC_OUTDR selects the up pull, and PC16 // corresponding to CNF=01 selects the floating input. - // XXX TODO: Handle for 5V VDD. +#if FUSB_5V_OPERATION + // XXX This is dubious, copied from x035 - checkme. + AFIO->CTLR = (AFIO->CTLR & ~(UDP_PUE_MASK | UDM_PUE_MASK | USB_PHY_V33)) | UDP_PUE_10K | USB_IOEN; +#else + AFIO->CTLR = (AFIO->CTLR & ~(UDP_PUE_MASK | UDM_PUE_MASK )) | USB_PHY_V33 | UDP_PUE_1K5 | USB_IOEN; +#endif AFIO->CTLR = (AFIO->CTLR & ~(UDP_PUE_11 | UDM_PUE_11 )) | USB_PHY_V33 | USB_IOEN | UDP_PUE_11; //1.5k pullup @@ -746,7 +600,7 @@ uint8_t USBFS_Endp_DataUp(uint8_t endp, uint8_t *pbuf, uint16_t len, uint8_t mod /* DMA config, endp_ctrl config, endp_len config */ if( ( endp >= DEF_UEP1 ) && ( endp <= DEF_UEP7 ) ) { - if( USBFS_Endp_Busy[ endp ] == 0 ) + if( FSUSBCTX.USBFS_Endp_Busy[ endp ] == 0 ) { if( (endp == DEF_UEP1) || (endp == DEF_UEP4) ) { @@ -843,7 +697,7 @@ uint8_t USBFS_Endp_DataUp(uint8_t endp, uint8_t *pbuf, uint16_t len, uint8_t mod /* response ack */ USBFSD_UEP_TX_CTRL( endp ) = ( USBFSD_UEP_TX_CTRL( endp ) & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_ACK; /* Set end-point busy */ - USBFS_Endp_Busy[ endp ] = 0x01; + FSUSBCTX.USBFS_Endp_Busy[ endp ] = 0x01; } } else diff --git a/examples_x035/usbdevice.incomplete/fsusb.h b/examples_x035/usbdevice.incomplete/fsusb.h index f34f9f54..0ea32230 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.h +++ b/examples_x035/usbdevice.incomplete/fsusb.h @@ -2,8 +2,9 @@ #define _FSUSB_H #include - -#include "descriptor.h" +#include "ch32v003fun.h" +#include "usb_defines.h" +#include "usb_config.h" extern uint32_t USBDEBUG0, USBDEBUG1, USBDEBUG2; @@ -11,13 +12,42 @@ int FSUSBSetup(); void USBFS_Poll(); uint8_t USBFS_Endp_DataUp(uint8_t endp, uint8_t *pbuf, uint16_t len, uint8_t mod); -// XXX TODO: Put the below in an object. -/*******************************************************************************/ -/* Variable Definition */ -/* Global */ -extern const uint8_t *pUSBFS_Descr; +struct _USBState +{ + /* Setup Request */ + volatile uint8_t USBFS_SetupReqCode; + volatile uint8_t USBFS_SetupReqType; + volatile uint16_t USBFS_SetupReqLen; + volatile uint32_t USBFS_IndexValue; + + /* USB Device Status */ + volatile uint8_t USBFS_DevConfig; + volatile uint8_t USBFS_DevAddr; + volatile uint8_t USBFS_DevSleepStatus; + volatile uint8_t USBFS_DevEnumStatus; + + /* Endpoint Buffer */ + __attribute__ ((aligned(4))) uint8_t USBFS_EP0_Buf[64]; + __attribute__ ((aligned(4))) uint8_t USBFS_EP1_Buf[64]; + __attribute__ ((aligned(4))) uint8_t USBFS_EP2_Buf[64]; + #define pUSBFS_SetupReqPak ((tusb_control_request_t*)ctx->USBFS_EP0_Buf) + + + int USBFS_HidIdle[2]; + int USBFS_HidProtocol[2]; + + const uint8_t *pUSBFS_Descr; + + /* USB IN Endpoint Busy Flag */ + volatile uint8_t USBFS_Endp_Busy[UNUM_EP]; +}; +extern struct _USBState FSUSBCTX; + + +#if 0 +extern const uint8_t *pUSBFS_Descr; /* USB Device Status */ extern volatile uint8_t USBFS_DevConfig; @@ -35,405 +65,7 @@ extern volatile uint8_t USBFS_Endp_Busy[ ]; // ABOVE: TOOD: REWRITE! - -// Copied from x035 documentation. -#define USBFSD_UEP_MOD_BASE 0x4002340C -#define USBFSD_UEP_DMA_BASE 0x40023410 -#define USBFSD_UEP_LEN_BASE 0x40023420 -#define USBFSD_UEP_CTL_BASE 0x40023422 -#define USBFSD_UEP_RX_EN 0x08 -#define USBFSD_UEP_TX_EN 0x04 -#define USBFSD_UEP_BUF_MOD 0x01 -#define DEF_UEP_DMA_LOAD 0 /* Direct the DMA address to the data to be processed */ -#define DEF_UEP_CPY_LOAD 1 /* Use memcpy to move data to a buffer */ -#define USBFSD_UEP_MOD( N ) (*((volatile uint8_t *)( USBFSD_UEP_MOD_BASE + N ))) -#define USBFSD_UEP_TX_CTRL( N ) (*((volatile uint8_t *)( USBFSD_UEP_CTL_BASE + N * 0x04 ))) -#define USBFSD_UEP_RX_CTRL( N ) (*((volatile uint8_t *)( USBFSD_UEP_CTL_BASE + N * 0x04 ))) -#define USBFSD_UEP_DMA( N ) (*((volatile uint32_t *)( USBFSD_UEP_DMA_BASE + N * 0x04 ))) -#define USBFSD_UEP_BUF( N ) ((uint8_t *)(*((volatile uint32_t *)( USBFSD_UEP_DMA_BASE + N * 0x04 ))) + 0x20000000) -#define USBFSD_UEP_TLEN( N ) (*((volatile uint16_t *)( USBFSD_UEP_LEN_BASE + N * 0x04 ))) - -/* R8_UEPn_TX_CTRL */ -#define USBFS_UEP_T_AUTO_TOG (1<<4) // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle -#define USBFS_UEP_T_TOG (1<<6) // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1 -#define USBFS_UEP_T_RES_MASK (3<<0) // bit mask of handshake response type for USB endpoint X transmittal (IN) -#define USBFS_UEP_T_RES_ACK (0<<1) -#define USBFS_UEP_T_RES_NONE (1<<0) -#define USBFS_UEP_T_RES_NAK (1<<1) -#define USBFS_UEP_T_RES_STALL (3<<0) -// bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmittal (IN) -// 00: DATA0 or DATA1 then expecting ACK (ready) -// 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions -// 10: NAK (busy) -// 11: STALL (error) -// host aux setup - -/* R8_UEPn_RX_CTRL, n=0-7 */ -#define USBFS_UEP_R_AUTO_TOG (1<<4) // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle -#define USBFS_UEP_R_TOG (1<<7) // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1 -#define USBFS_UEP_R_RES_MASK (3<<2) // bit mask of handshake response type for USB endpoint X receiving (OUT) -#define USBFS_UEP_R_RES_ACK (0<<3) -#define USBFS_UEP_R_RES_NONE (1<<2) -#define USBFS_UEP_R_RES_NAK (1<<3) -#define USBFS_UEP_R_RES_STALL (3<<2) - - -/* R8_USB_DEV_AD */ -#define USBFS_UDA_GP_BIT 0x80 -#define USBFS_USB_ADDR_MASK 0x7F - - - -#define DEF_USBD_UEP0_SIZE 64 /* usb hs/fs device end-point 0 size */ -#define EP_SIZE 64 - -#define DEF_UEP_IN 0x80 -#define DEF_UEP_OUT 0x00 -#define DEF_UEP_BUSY 0x01 -#define DEF_UEP_FREE 0x00 - -#define DEF_UEP0 0 -#define DEF_UEP1 1 -#define DEF_UEP2 2 -#define DEF_UEP3 3 -#define DEF_UEP4 4 -#define DEF_UEP5 5 -#define DEF_UEP6 6 -#define DEF_UEP7 7 -#define NUM_EP 8 - -// Hardware specific - -#define EP1_T_EN (1<<6) -#define EP2_T_EN (1<<2) -#define EP3_T_EN (1<<6) -#define EP4_T_EN (1<<2) -#define EP1_R_EN (1<<7) -#define EP2_R_EN (1<<3) -#define EP3_R_EN (1<<7) -#define EP4_R_EN (1<<3) - - -/* R8_USB_CTRL */ -#define USBFS_UC_HOST_MODE 0x80 -#define USBFS_UC_LOW_SPEED 0x40 -#define USBFS_UC_DEV_PU_EN 0x20 -#define USBFS_UC_SYS_CTRL_MASK 0x30 -#define USBFS_UC_SYS_CTRL0 0x00 -#define USBFS_UC_SYS_CTRL1 0x10 -#define USBFS_UC_SYS_CTRL2 0x20 -#define USBFS_UC_SYS_CTRL3 0x30 -#define USBFS_UC_INT_BUSY 0x08 -#define USBFS_UC_RESET_SIE 0x04 -#define USBFS_UC_CLR_ALL 0x02 -#define USBFS_UC_DMA_EN 0x01 - -/* R8_USB_INT_EN */ -#define USBFS_UIE_DEV_SOF 0x80 -#define USBFS_UIE_DEV_NAK 0x40 -#define USBFS_UIE_FIFO_OV 0x10 -#define USBFS_UIE_HST_SOF 0x08 -#define USBFS_UIE_SUSPEND 0x04 -#define USBFS_UIE_TRANSFER 0x02 -#define USBFS_UIE_DETECT 0x01 -#define USBFS_UIE_BUS_RST 0x01 - -/* R8_USB_DEV_AD */ -#define USBFS_UDA_GP_BIT 0x80 -#define USBFS_USB_ADDR_MASK 0x7F - -/* R8_USB_MIS_ST */ -#define USBFS_UMS_SOF_PRES 0x80 -#define USBFS_UMS_SOF_ACT 0x40 -#define USBFS_UMS_SIE_FREE 0x20 -#define USBFS_UMS_R_FIFO_RDY 0x10 -#define USBFS_UMS_BUS_RESET 0x08 -#define USBFS_UMS_SUSPEND 0x04 -#define USBFS_UMS_DM_LEVEL 0x02 -#define USBFS_UMS_DEV_ATTACH 0x01 - -/* USB Setup Request */ -typedef struct __attribute__((packed)) _USB_SETUP_REQ -{ - uint8_t bRequestType; - uint8_t bRequest; - uint16_t wValue; - uint16_t wIndex; - uint16_t wLength; -} USB_SETUP_REQ, *PUSB_SETUP_REQ; - -/* USB Device Descriptor */ -typedef struct __attribute__((packed)) _USB_DEVICE_DESCR -{ - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdUSB; - uint8_t bDeviceClass; - uint8_t bDeviceSubClass; - uint8_t bDeviceProtocol; - uint8_t bMaxPacketSize0; - uint16_t idVendor; - uint16_t idProduct; - uint16_t bcdDevice; - uint8_t iManufacturer; - uint8_t iProduct; - uint8_t iSerialNumber; - uint8_t bNumConfigurations; -} USB_DEV_DESCR, *PUSB_DEV_DESCR; - -/* USB Configuration Descriptor */ -typedef struct __attribute__((packed)) _USB_CONFIG_DESCR -{ - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t wTotalLength; - uint8_t bNumInterfaces; - uint8_t bConfigurationValue; - uint8_t iConfiguration; - uint8_t bmAttributes; - uint8_t MaxPower; -} USB_CFG_DESCR, *PUSB_CFG_DESCR; - -/* USB Interface Descriptor */ -typedef struct __attribute__((packed)) _USB_INTERF_DESCR -{ - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bInterfaceNumber; - uint8_t bAlternateSetting; - uint8_t bNumEndpoints; - uint8_t bInterfaceClass; - uint8_t bInterfaceSubClass; - uint8_t bInterfaceProtocol; - uint8_t iInterface; -} USB_ITF_DESCR, *PUSB_ITF_DESCR; - -/* USB Endpoint Descriptor */ -typedef struct __attribute__((packed)) _USB_ENDPOINT_DESCR -{ - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bEndpointAddress; - uint8_t bmAttributes; - uint8_t wMaxPacketSizeL; - uint8_t wMaxPacketSizeH; - uint8_t bInterval; -} USB_ENDP_DESCR, *PUSB_ENDP_DESCR; - -/* USB Configuration Descriptor Set */ -typedef struct __attribute__((packed)) _USB_CONFIG_DESCR_LONG -{ - USB_CFG_DESCR cfg_descr; - USB_ITF_DESCR itf_descr; - USB_ENDP_DESCR endp_descr[ 1 ]; -} USB_CFG_DESCR_LONG, *PUSB_CFG_DESCR_LONG; - -/* USB HUB Descriptor */ -typedef struct __attribute__((packed)) _USB_HUB_DESCR -{ - uint8_t bDescLength; - uint8_t bDescriptorType; - uint8_t bNbrPorts; - uint8_t wHubCharacteristicsL; - uint8_t wHubCharacteristicsH; - uint8_t bPwrOn2PwrGood; - uint8_t bHubContrCurrent; - uint8_t DeviceRemovable; - uint8_t PortPwrCtrlMask; -} USB_HUB_DESCR, *PUSB_HUB_DESCR; - -/* USB HID Descriptor */ -typedef struct __attribute__((packed)) _USB_HID_DESCR -{ - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdHID; - uint8_t bCountryCode; - uint8_t bNumDescriptors; - uint8_t bDescriptorTypeX; - uint8_t wDescriptorLengthL; - uint8_t wDescriptorLengthH; -} USB_HID_DESCR, *PUSB_HID_DESCR; - - -/*******************************************************************************/ -/* USB Communication Related Macro Definition */ - -/* USB PID */ -#ifndef USB_PID_SETUP -#define USB_PID_NULL 0x00 -#define USB_PID_SOF 0x05 -#define USB_PID_SETUP 0x0D -#define USB_PID_IN 0x09 -#define USB_PID_OUT 0x01 -#define USB_PID_NYET 0x06 -#define USB_PID_ACK 0x02 -#define USB_PID_NAK 0x0A -#define USB_PID_STALL 0x0E -#define USB_PID_DATA0 0x03 -#define USB_PID_DATA1 0x0B -#define USB_PID_PRE 0x0C -#endif - -/* USB standard device request code */ -#ifndef USB_GET_DESCRIPTOR -#define USB_GET_STATUS 0x00 -#define USB_CLEAR_FEATURE 0x01 -#define USB_SET_FEATURE 0x03 -#define USB_SET_ADDRESS 0x05 -#define USB_GET_DESCRIPTOR 0x06 -#define USB_SET_DESCRIPTOR 0x07 -#define USB_GET_CONFIGURATION 0x08 -#define USB_SET_CONFIGURATION 0x09 -#define USB_GET_INTERFACE 0x0A -#define USB_SET_INTERFACE 0x0B -#define USB_SYNCH_FRAME 0x0C -#endif - -#define DEF_STRING_DESC_LANG 0x00 -#define DEF_STRING_DESC_MANU 0x01 -#define DEF_STRING_DESC_PROD 0x02 -#define DEF_STRING_DESC_SERN 0x03 - -/* USB hub class request code */ -#ifndef HUB_GET_DESCRIPTOR -#define HUB_GET_STATUS 0x00 -#define HUB_CLEAR_FEATURE 0x01 -#define HUB_GET_STATE 0x02 -#define HUB_SET_FEATURE 0x03 -#define HUB_GET_DESCRIPTOR 0x06 -#define HUB_SET_DESCRIPTOR 0x07 -#endif - -/* USB HID class request code */ -#ifndef HID_GET_REPORT -#define HID_GET_REPORT 0x01 -#define HID_GET_IDLE 0x02 -#define HID_GET_PROTOCOL 0x03 -#define HID_SET_REPORT 0x09 -#define HID_SET_IDLE 0x0A -#define HID_SET_PROTOCOL 0x0B -#endif - -/* Bit Define for USB Request Type */ -#ifndef USB_REQ_TYP_MASK -#define USB_REQ_TYP_IN 0x80 -#define USB_REQ_TYP_OUT 0x00 -#define USB_REQ_TYP_READ 0x80 -#define USB_REQ_TYP_WRITE 0x00 -#define USB_REQ_TYP_MASK 0x60 -#define USB_REQ_TYP_STANDARD 0x00 -#define USB_REQ_TYP_CLASS 0x20 -#define USB_REQ_TYP_VENDOR 0x40 -#define USB_REQ_TYP_RESERVED 0x60 -#define USB_REQ_RECIP_MASK 0x1F -#define USB_REQ_RECIP_DEVICE 0x00 -#define USB_REQ_RECIP_INTERF 0x01 -#define USB_REQ_RECIP_ENDP 0x02 -#define USB_REQ_RECIP_OTHER 0x03 -#define USB_REQ_FEAT_REMOTE_WAKEUP 0x01 -#define USB_REQ_FEAT_ENDP_HALT 0x00 -#endif - -/* USB Descriptor Type */ -#ifndef USB_DESCR_TYP_DEVICE -#define USB_DESCR_TYP_DEVICE 0x01 -#define USB_DESCR_TYP_CONFIG 0x02 -#define USB_DESCR_TYP_STRING 0x03 -#define USB_DESCR_TYP_INTERF 0x04 -#define USB_DESCR_TYP_ENDP 0x05 -#define USB_DESCR_TYP_QUALIF 0x06 -#define USB_DESCR_TYP_SPEED 0x07 -#define USB_DESCR_TYP_OTG 0x09 -#define USB_DESCR_TYP_BOS 0X0F -#define USB_DESCR_TYP_HID 0x21 -#define USB_DESCR_TYP_REPORT 0x22 -#define USB_DESCR_TYP_PHYSIC 0x23 -#define USB_DESCR_TYP_CS_INTF 0x24 -#define USB_DESCR_TYP_CS_ENDP 0x25 -#define USB_DESCR_TYP_HUB 0x29 -#endif - -/* USB Device Class */ -#ifndef USB_DEV_CLASS_HUB -#define USB_DEV_CLASS_RESERVED 0x00 -#define USB_DEV_CLASS_AUDIO 0x01 -#define USB_DEV_CLASS_COMMUNIC 0x02 -#define USB_DEV_CLASS_HID 0x03 -#define USB_DEV_CLASS_MONITOR 0x04 -#define USB_DEV_CLASS_PHYSIC_IF 0x05 -#define USB_DEV_CLASS_POWER 0x06 -#define USB_DEV_CLASS_PRINTER 0x07 -#define USB_DEV_CLASS_STORAGE 0x08 -#define USB_DEV_CLASS_HUB 0x09 -#define USB_DEV_CLASS_VEN_SPEC 0xFF -#endif - -/* USB Hub Class Request */ -#ifndef HUB_GET_HUB_DESCRIPTOR -#define HUB_CLEAR_HUB_FEATURE 0x20 -#define HUB_CLEAR_PORT_FEATURE 0x23 -#define HUB_GET_BUS_STATE 0xA3 -#define HUB_GET_HUB_DESCRIPTOR 0xA0 -#define HUB_GET_HUB_STATUS 0xA0 -#define HUB_GET_PORT_STATUS 0xA3 -#define HUB_SET_HUB_DESCRIPTOR 0x20 -#define HUB_SET_HUB_FEATURE 0x20 -#define HUB_SET_PORT_FEATURE 0x23 -#endif - -/* Hub Class Feature Selectors */ -#ifndef HUB_PORT_RESET -#define HUB_C_HUB_LOCAL_POWER 0 -#define HUB_C_HUB_OVER_CURRENT 1 -#define HUB_PORT_CONNECTION 0 -#define HUB_PORT_ENABLE 1 -#define HUB_PORT_SUSPEND 2 -#define HUB_PORT_OVER_CURRENT 3 -#define HUB_PORT_RESET 4 -#define HUB_PORT_POWER 8 -#define HUB_PORT_LOW_SPEED 9 -#define HUB_C_PORT_CONNECTION 16 -#define HUB_C_PORT_ENABLE 17 -#define HUB_C_PORT_SUSPEND 18 -#define HUB_C_PORT_OVER_CURRENT 19 -#define HUB_C_PORT_RESET 20 -#endif - -/* USB HID Class Request Code */ -#ifndef HID_GET_REPORT -#define HID_GET_REPORT 0x01 -#define HID_GET_IDLE 0x02 -#define HID_GET_PROTOCOL 0x03 -#define HID_SET_REPORT 0x09 -#define HID_SET_IDLE 0x0A -#define HID_SET_PROTOCOL 0x0B -#endif - -/* USB UDisk */ -#ifndef USB_BO_CBW_SIZE -#define USB_BO_CBW_SIZE 0x1F -#define USB_BO_CSW_SIZE 0x0D -#endif -#ifndef USB_BO_CBW_SIG0 -#define USB_BO_CBW_SIG0 0x55 -#define USB_BO_CBW_SIG1 0x53 -#define USB_BO_CBW_SIG2 0x42 -#define USB_BO_CBW_SIG3 0x43 -#define USB_BO_CSW_SIG0 0x55 -#define USB_BO_CSW_SIG1 0x53 -#define USB_BO_CSW_SIG2 0x42 -#define USB_BO_CSW_SIG3 0x53 -#endif - -/* USB CDC Class request code */ -#ifndef CDC_GET_LINE_CODING -#define CDC_GET_LINE_CODING 0X21 /* This request allows the host to find out the currently configured line coding */ -#define CDC_SET_LINE_CODING 0x20 /* Configures DTE rate, stop-bits, parity, and number-of-character */ -#define CDC_SET_LINE_CTLSTE 0X22 /* This request generates RS-232/V.24 style control signals */ -#define CDC_SEND_BREAK 0X23 /* Sends special carrier modulation used to specify RS-232 style break */ #endif -/*******************************************************************************/ #endif diff --git a/examples_x035/usbdevice.incomplete/usbdevice.c b/examples_x035/usbdevice.incomplete/usbdevice.c index 2220c2b8..3dfd0251 100644 --- a/examples_x035/usbdevice.incomplete/usbdevice.c +++ b/examples_x035/usbdevice.incomplete/usbdevice.c @@ -29,13 +29,13 @@ void USBFS_IRQHandler(); //extern int USBFS_IRQHandler; while(1) { - printf( "%lu %lu %lu %d %d\n", USBDEBUG0, USBDEBUG1, USBDEBUG2, USBFS_Endp_Busy[0], USBFS_Endp_Busy[1] ); + printf( "%lu %08x %lu %d %d\n", USBDEBUG0, USBDEBUG1, USBDEBUG2, 0, 0 ); USBFS_Poll(); int i; //printf( "!! %d %d %d\n", NUM_EP, USBFS_Endp_Busy[0], USBFS_Endp_Busy[1] ); for( i = 1; i < 3; i++ ) { - if( !USBFS_Endp_Busy[i] ) + if( !FSUSBCTX.USBFS_Endp_Busy[i] ) { /* @@ -46,7 +46,7 @@ USBDEBUG0+= 100; // USBFSD_UEP_TX_CTRL( i ) = ( USBFSD_UEP_TX_CTRL( i ) & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_ACK; // USBFS_Endp_Busy[i] = 1; - char pbuf[16] = { 0 }; + char pbuf[16] = { 0x00, 1, 1 }; uint8_t r = USBFS_Endp_DataUp( i, pbuf, (i==1)?8:4, DEF_UEP_CPY_LOAD); //USBDEBUG1+=r; } From 1dca24bbf6e6aa294983a6da2a807cc3fa11f04c Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sun, 21 Apr 2024 14:50:36 -0400 Subject: [PATCH 14/31] Clean up some control flow. --- examples_x035/usbdevice.incomplete/fsusb.c | 100 +-- examples_x035/usbdevice.incomplete/fsusb.h | 14 +- .../usbdevice.incomplete/usb_config.h | 225 +++++ .../usbdevice.incomplete/usb_defines.h | 833 ++++++++++++++++++ .../usbdevice.incomplete/usbdevice.c | 15 +- 5 files changed, 1121 insertions(+), 66 deletions(-) create mode 100644 examples_x035/usbdevice.incomplete/usb_config.h create mode 100644 examples_x035/usbdevice.incomplete/usb_defines.h diff --git a/examples_x035/usbdevice.incomplete/fsusb.c b/examples_x035/usbdevice.incomplete/fsusb.c index 319018c4..d16530eb 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.c +++ b/examples_x035/usbdevice.incomplete/fsusb.c @@ -39,7 +39,7 @@ void USBFS_IRQHandler() // Combined FG + ST flag. uint16_t intfgst = *(uint16_t*)(&USBFS->INT_FG); - int len = 0, errflag = 0; + int len = 0; struct _USBState * ctx = &FSUSBCTX; GPIOA->BSHR = 1; @@ -71,7 +71,7 @@ void USBFS_IRQHandler() { case USB_GET_DESCRIPTOR: len = ctx->USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : ctx->USBFS_SetupReqLen; - memcpy( ctx->USBFS_EP0_Buf, ctx->pUSBFS_Descr, len ); + memcpy( ctx->USBFS_EP_Buf[0], ctx->pUSBFS_Descr, len ); ctx->USBFS_SetupReqLen -= len; ctx->pUSBFS_Descr += len; USBFS->UEP0_TX_LEN = len; @@ -160,10 +160,10 @@ void USBFS_IRQHandler() int USBFS_SetupReqIndex = pUSBFS_SetupReqPak->wIndex; int USBFS_IndexValue = FSUSBCTX.USBFS_IndexValue = ( pUSBFS_SetupReqPak->wIndex << 16 ) | pUSBFS_SetupReqPak->wValue; len = 0; - errflag = 0; if( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) { +#if FUSB_HID_INTERFACES > 0 if( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) == USB_REQ_TYP_CLASS ) { /* Class Request */ @@ -173,43 +173,36 @@ void USBFS_IRQHandler() break; case HID_SET_IDLE: - if( USBFS_SetupReqIndex < 0x02 ) + if( USBFS_SetupReqIndex < FUSB_HID_INTERFACES ) FSUSBCTX.USBFS_HidIdle[ USBFS_SetupReqIndex ] = (uint8_t)( USBFS_IndexValue >> 8 ); - else - errflag = 0xFF; break; case HID_SET_PROTOCOL: - if ( USBFS_SetupReqIndex < 0x02 ) + if ( USBFS_SetupReqIndex < FUSB_HID_INTERFACES ) FSUSBCTX.USBFS_HidProtocol[USBFS_SetupReqIndex] = (uint8_t)USBFS_IndexValue; - else - errflag = 0xFF; break; case HID_GET_IDLE: - if( USBFS_SetupReqIndex < 0x02 ) + if( USBFS_SetupReqIndex < FUSB_HID_INTERFACES ) { - FSUSBCTX.USBFS_EP0_Buf[ 0 ] = FSUSBCTX.USBFS_HidIdle[ USBFS_SetupReqIndex ]; + FSUSBCTX.USBFS_EP_Buf[0][0] = FSUSBCTX.USBFS_HidIdle[ USBFS_SetupReqIndex ]; len = 1; } - else - errflag = 0xFF; break; case HID_GET_PROTOCOL: - if( USBFS_SetupReqIndex < 0x02 ) + if( USBFS_SetupReqIndex < FUSB_HID_INTERFACES ) { - FSUSBCTX.USBFS_EP0_Buf[ 0 ] = FSUSBCTX.USBFS_HidProtocol[ USBFS_SetupReqIndex ]; + FSUSBCTX.USBFS_EP_Buf[0][0] = FSUSBCTX.USBFS_HidProtocol[ USBFS_SetupReqIndex ]; len = 1; } - else - errflag = 0xFF; break; default: - errflag = 0xFF; + goto reporterror; break; } } +#endif } else { @@ -233,7 +226,7 @@ void USBFS_IRQHandler() } if( e == e_end ) { - errflag = 0xFF; + goto reporterror; } /* Copy Descriptors to Endp0 DMA buffer */ @@ -242,7 +235,7 @@ void USBFS_IRQHandler() USBFS_SetupReqLen = len; } len = ( USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ) ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen; - memcpy( ctx->USBFS_EP0_Buf, ctx->pUSBFS_Descr, len ); + memcpy( ctx->USBFS_EP_Buf[0], ctx->pUSBFS_Descr, len ); ctx->pUSBFS_Descr += len; break; } @@ -254,7 +247,7 @@ void USBFS_IRQHandler() /* Get usb configuration now set */ case USB_GET_CONFIGURATION: - ctx->USBFS_EP0_Buf[ 0 ] = ctx->USBFS_DevConfig; + ctx->USBFS_EP_Buf[0][0] = ctx->USBFS_DevConfig; if( ctx->USBFS_SetupReqLen > 1 ) { ctx->USBFS_SetupReqLen = 1; @@ -279,7 +272,7 @@ void USBFS_IRQHandler() } else { - errflag = 0xFF; + goto reporterror; } } else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) @@ -300,18 +293,18 @@ void USBFS_IRQHandler() break; default: - errflag = 0xFF; + goto reporterror; break; } } else { - errflag = 0xFF; + goto reporterror; } } else { - errflag = 0xFF; + goto reporterror; } break; @@ -329,7 +322,7 @@ void USBFS_IRQHandler() else #endif { - errflag = 0xFF; + goto reporterror; } } else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) @@ -348,24 +341,24 @@ void USBFS_IRQHandler() break; default: - errflag = 0xFF; + goto reporterror; break; } } else { - errflag = 0xFF; + goto reporterror; } } else { - errflag = 0xFF; + goto reporterror; } break; /* This request allows the host to select another setting for the specified interface */ case USB_GET_INTERFACE: - ctx->USBFS_EP0_Buf[ 0 ] = 0x00; + ctx->USBFS_EP_Buf[0][0] = 0x00; if( USBFS_SetupReqLen > 1 ) { USBFS_SetupReqLen = 1; @@ -377,17 +370,17 @@ void USBFS_IRQHandler() /* host get status of specified device/interface/end-points */ case USB_GET_STATUS: - ctx->USBFS_EP0_Buf[ 0 ] = 0x00; - ctx->USBFS_EP0_Buf[ 1 ] = 0x00; + ctx->USBFS_EP_Buf[0][0] = 0x00; + ctx->USBFS_EP_Buf[0][1] = 0x00; if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE ) { if( ctx->USBFS_DevSleepStatus & 0x01 ) { - ctx->USBFS_EP0_Buf[ 0 ] = 0x02; + ctx->USBFS_EP_Buf[0][0] = 0x02; } else { - ctx->USBFS_EP0_Buf[ 0 ] = 0x00; + ctx->USBFS_EP_Buf[0][0] = 0x00; } } else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) @@ -396,24 +389,24 @@ void USBFS_IRQHandler() { if( ( USBFS->UEP1_CTRL_H & USBFS_UEP_T_RES_MASK ) == USBFS_UEP_T_RES_STALL ) { - ctx->USBFS_EP0_Buf[ 0 ] = 0x01; + ctx->USBFS_EP_Buf[0][0] = 0x01; } } else if( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) == ( DEF_UEP_IN | DEF_UEP2 ) ) { if( ( USBFS->UEP2_CTRL_H & USBFS_UEP_T_RES_MASK ) == USBFS_UEP_T_RES_STALL ) { - ctx->USBFS_EP0_Buf[ 0 ] = 0x01; + ctx->USBFS_EP_Buf[0][0] = 0x01; } } else { - errflag = 0xFF; + goto reporterror; } } else { - errflag = 0xFF; + goto reporterror; } if( USBFS_SetupReqLen > 2 ) { @@ -422,18 +415,12 @@ void USBFS_IRQHandler() break; default: - errflag = 0xFF; + goto reporterror; break; } } - /* errflag = 0xFF means a request not support or some errors occurred, else correct */ - if( errflag == 0xFF ) - { - /* if one request not support, return stall */ - USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_STALL|USBFS_UEP_R_TOG | USBFS_UEP_R_RES_STALL; - } - else + { /* end-point 0 data Tx/Rx */ if( USBFS_SetupReqType & DEF_UEP_IN ) @@ -458,6 +445,12 @@ void USBFS_IRQHandler() } break; + // This might look a little weird, for error handling but it saves a nontrivial amount of storage, and simplifies + // control flow to hard-abort here. + reporterror: + // if one request not support, return stall. Stall means permanent error. + USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_STALL|USBFS_UEP_R_TOG | USBFS_UEP_R_RES_STALL; + /* Sof pack processing */ case CUIS_TOKEN_SOF: break; @@ -465,6 +458,8 @@ void USBFS_IRQHandler() default : break; } + + } else if( intfgst & CRB_UIF_BUS_RST ) { @@ -508,9 +503,9 @@ void USBFS_Device_Endp_Init() USBFS->UEP2_3_MOD = RB_UEP2_TX_EN; USBFS->UEP567_MOD = 0; - USBFS->UEP0_DMA = (intptr_t)FSUSBCTX.USBFS_EP0_Buf; - USBFS->UEP1_DMA = (intptr_t)FSUSBCTX.USBFS_EP1_Buf; - USBFS->UEP2_DMA = (intptr_t)FSUSBCTX.USBFS_EP2_Buf; + USBFS->UEP0_DMA = (intptr_t)FSUSBCTX.USBFS_EP_Buf[0]; + USBFS->UEP1_DMA = (intptr_t)FSUSBCTX.USBFS_EP_Buf[1]; + USBFS->UEP2_DMA = (intptr_t)FSUSBCTX.USBFS_EP_Buf[2]; USBFS->UEP0_CTRL_H = USBFS_UEP_R_RES_ACK | USBFS_UEP_T_RES_NAK; USBFS->UEP1_CTRL_H = USBFS_UEP_T_RES_NAK; @@ -523,13 +518,6 @@ void USBFS_Device_Endp_Init() } } - -void USBFS_Poll() -{ - //USBDEBUG2 = USBFS->INT_ST;//EP0_DATA[1]; - //USBDEBUG1 = USBFS->MIS_ST; -} - int FSUSBSetup() { RCC->APB2PCENR |= RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOC; diff --git a/examples_x035/usbdevice.incomplete/fsusb.h b/examples_x035/usbdevice.incomplete/fsusb.h index 0ea32230..3aca2ced 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.h +++ b/examples_x035/usbdevice.incomplete/fsusb.h @@ -9,7 +9,6 @@ extern uint32_t USBDEBUG0, USBDEBUG1, USBDEBUG2; int FSUSBSetup(); -void USBFS_Poll(); uint8_t USBFS_Endp_DataUp(uint8_t endp, uint8_t *pbuf, uint16_t len, uint8_t mod); @@ -28,19 +27,18 @@ struct _USBState volatile uint8_t USBFS_DevEnumStatus; /* Endpoint Buffer */ - __attribute__ ((aligned(4))) uint8_t USBFS_EP0_Buf[64]; - __attribute__ ((aligned(4))) uint8_t USBFS_EP1_Buf[64]; - __attribute__ ((aligned(4))) uint8_t USBFS_EP2_Buf[64]; - #define pUSBFS_SetupReqPak ((tusb_control_request_t*)ctx->USBFS_EP0_Buf) + __attribute__ ((aligned(4))) uint8_t USBFS_EP_Buf[FUSB_CONFIG_EPS][64]; + #define pUSBFS_SetupReqPak ((tusb_control_request_t*)ctx->USBFS_EP_Buf[0]) - int USBFS_HidIdle[2]; - int USBFS_HidProtocol[2]; + + uint8_t USBFS_HidIdle[FUSB_HID_INTERFACES]; + uint8_t USBFS_HidProtocol[FUSB_HID_INTERFACES]; const uint8_t *pUSBFS_Descr; /* USB IN Endpoint Busy Flag */ - volatile uint8_t USBFS_Endp_Busy[UNUM_EP]; + volatile uint8_t USBFS_Endp_Busy[FUSB_CONFIG_EPS]; }; extern struct _USBState FSUSBCTX; diff --git a/examples_x035/usbdevice.incomplete/usb_config.h b/examples_x035/usbdevice.incomplete/usb_config.h new file mode 100644 index 00000000..840c0123 --- /dev/null +++ b/examples_x035/usbdevice.incomplete/usb_config.h @@ -0,0 +1,225 @@ +#ifndef _USB_CONFIG_H +#define _USB_CONFIG_H + +#define FUSB_5V_OPERATION 0 +#define FUSB_CONFIG_EPS 3 // Include EP0 in this count +#define FUSB_SUPPORTS_SLEEP 0 + +#define FUSB_HID_INTERFACES 2 + + +//Taken from http://www.usbmadesimple.co.uk/ums_ms_desc_dev.htm +static const uint8_t device_descriptor[] = { + 18, //Length + 1, //Type (Device) + 0x00, 0x02, //Spec + 0x0, //Device Class + 0x0, //Device Subclass + 0x0, //Device Protocol (000 = use config descriptor) + 64, //Max packet size for EP0 (This has to be 8 because of the USB Low-Speed Standard) + 0xaa, 0xaa, //ID Vendor + 0x04, 0xd0, //ID Product + 0x03, 0x00, //ID Rev + 1, //Manufacturer string + 2, //Product string + 3, //Serial string + 1, //Max number of configurations +}; + + + +/* Configuration Descriptor Set */ +static const uint8_t config_descriptor[ ] = +{ + /* Configuration Descriptor */ + 0x09, // bLength + 0x02, // bDescriptorType + 0x3B, 0x00, // wTotalLength + 0x02, // bNumInterfaces + 0x01, // bConfigurationValue + 0x00, // iConfiguration + 0xA0, // bmAttributes: Bus Powered; Remote Wakeup + 0x32, // MaxPower: 100mA + + /* Interface Descriptor (Keyboard) */ + 0x09, // bLength + 0x04, // bDescriptorType + 0x00, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x01, // bNumEndpoints + 0x03, // bInterfaceClass + 0x01, // bInterfaceSubClass + 0x01, // bInterfaceProtocol: Keyboard + 0x00, // iInterface + + /* HID Descriptor (Keyboard) */ + 0x09, // bLength + 0x21, // bDescriptorType + 0x11, 0x01, // bcdHID + 0x00, // bCountryCode + 0x01, // bNumDescriptors + 0x22, // bDescriptorType + 0x3E, 0x00, // wDescriptorLength + + /* Endpoint Descriptor (Keyboard) */ + 0x07, // bLength + 0x05, // bDescriptorType + 0x81, // bEndpointAddress: IN Endpoint 1 + 0x03, // bmAttributes + 0x08, 0x00, // wMaxPacketSize + 0x0A, // bInterval: 10mS + + /* Interface Descriptor (Mouse) */ + 0x09, // bLength + 0x04, // bDescriptorType + 0x01, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x01, // bNumEndpoints + 0x03, // bInterfaceClass + 0x01, // bInterfaceSubClass + 0x02, // bInterfaceProtocol: Mouse + 0x00, // iInterface + + /* HID Descriptor (Mouse) */ + 0x09, // bLength + 0x21, // bDescriptorType + 0x10, 0x01, // bcdHID + 0x00, // bCountryCode + 0x01, // bNumDescriptors + 0x22, // bDescriptorType + 0x34, 0x00, // wDescriptorLength + + /* Endpoint Descriptor (Mouse) */ + 0x07, // bLength + 0x05, // bDescriptorType + 0x82, // bEndpointAddress: IN Endpoint 2 + 0x03, // bmAttributes + 0x08, 0x00, // wMaxPacketSize + 0x01 // bInterval: 1mS +}; + + + +/* Keyboard Report Descriptor */ +static const uint8_t KeyRepDesc[ ] = +{ + 0x05, 0x01, // Usage Page (Generic Desktop) + 0x09, 0x06, // Usage (Keyboard) + 0xA1, 0x01, // Collection (Application) + 0x05, 0x07, // Usage Page (Key Codes) + 0x19, 0xE0, // Usage Minimum (224) + 0x29, 0xE7, // Usage Maximum (231) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x08, // Report Count (8) + 0x81, 0x02, // Input (Data,Variable,Absolute) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x01, // Input (Constant) + 0x95, 0x03, // Report Count (3) + 0x75, 0x01, // Report Size (1) + 0x05, 0x08, // Usage Page (LEDs) + 0x19, 0x01, // Usage Minimum (1) + 0x29, 0x03, // Usage Maximum (3) + 0x91, 0x02, // Output (Data,Variable,Absolute) + 0x95, 0x05, // Report Count (5) + 0x75, 0x01, // Report Size (1) + 0x91, 0x01, // Output (Constant,Array,Absolute) + 0x95, 0x06, // Report Count (6) + 0x75, 0x08, // Report Size (8) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x05, 0x07, // Usage Page (Key Codes) + 0x19, 0x00, // Usage Minimum (0) + 0x29, 0x91, // Usage Maximum (145) + 0x81, 0x00, // Input(Data,Array,Absolute) + 0xC0 // End Collection +}; + +/* Mouse Report Descriptor */ +static const uint8_t MouseRepDesc[ ] = +{ + 0x05, 0x01, // Usage Page (Generic Desktop) + 0x09, 0x02, // Usage (Mouse) + 0xA1, 0x01, // Collection (Application) + 0x09, 0x01, // Usage (Pointer) + 0xA1, 0x00, // Collection (Physical) + 0x05, 0x09, // Usage Page (Button) + 0x19, 0x01, // Usage Minimum (Button 1) + 0x29, 0x03, // Usage Maximum (Button 3) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x03, // Report Count (3) + 0x81, 0x02, // Input (Data,Variable,Absolute) + 0x75, 0x05, // Report Size (5) + 0x95, 0x01, // Report Count (1) + 0x81, 0x01, // Input (Constant,Array,Absolute) + 0x05, 0x01, // Usage Page (Generic Desktop) + 0x09, 0x30, // Usage (X) + 0x09, 0x31, // Usage (Y) + 0x09, 0x38, // Usage (Wheel) + 0x15, 0x81, // Logical Minimum (-127) + 0x25, 0x7F, // Logical Maximum (127) + 0x75, 0x08, // Report Size (8) + 0x95, 0x03, // Report Count (3) + 0x81, 0x06, // Input (Data,Variable,Relative) + 0xC0, // End Collection + 0xC0 // End Collection +}; + + +#define STR_MANUFACTURER u"WCH" +#define STR_PRODUCT u"CH32X035 Custom Device" +#define STR_SERIAL u"CUSTOMDEVICE000" + +struct usb_string_descriptor_struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wString[]; +}; +const static struct usb_string_descriptor_struct string0 __attribute__((section(".rodata"))) = { + 4, + 3, + {0x0409} +}; +const static struct usb_string_descriptor_struct string1 __attribute__((section(".rodata"))) = { + sizeof(STR_MANUFACTURER), + 3, + STR_MANUFACTURER +}; +const static struct usb_string_descriptor_struct string2 __attribute__((section(".rodata"))) = { + sizeof(STR_PRODUCT), + 3, + STR_PRODUCT +}; +const static struct usb_string_descriptor_struct string3 __attribute__((section(".rodata"))) = { + sizeof(STR_SERIAL), + 3, + STR_SERIAL +}; + +// This table defines which descriptor data is sent for each specific +// request from the host (in wValue and wIndex). +const static struct descriptor_list_struct { + uint32_t lIndexValue; + const uint8_t *addr; + uint8_t length; +} descriptor_list[] = { + {0x00000100, device_descriptor, sizeof(device_descriptor)}, + {0x00000200, config_descriptor, sizeof(config_descriptor)}, + // interface number // 2200 for hid descriptors. + {0x00002200, KeyRepDesc, sizeof(KeyRepDesc)}, + {0x00012200, MouseRepDesc, sizeof(MouseRepDesc)}, + {0x00002100, config_descriptor + 18, 9 }, // Not sure why, this seems to be useful for Windows + Android. + + {0x00000300, (const uint8_t *)&string0, 4}, + {0x04090301, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)}, + {0x04090302, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}, + {0x04090303, (const uint8_t *)&string3, sizeof(STR_SERIAL)} +}; +#define DESCRIPTOR_LIST_ENTRIES ((sizeof(descriptor_list))/(sizeof(struct descriptor_list_struct)) ) + + +#endif + diff --git a/examples_x035/usbdevice.incomplete/usb_defines.h b/examples_x035/usbdevice.incomplete/usb_defines.h new file mode 100644 index 00000000..4fd18b68 --- /dev/null +++ b/examples_x035/usbdevice.incomplete/usb_defines.h @@ -0,0 +1,833 @@ + +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/** \ingroup group_usb_definitions + * \defgroup USBDef_Type USB Types + * @{ */ + +// Cribbed from the WCH x035 example code, but originally from USB IF. + +#ifndef _TUSB_TYPES_H_ +#define _TUSB_TYPES_H_ + +#include +#include + + +/*------------------------------------------------------------------*/ +/* From Linux + *------------------------------------------------------------------*/ + + +#define USB_DIR_OUT 0 /* to device */ +#define USB_DIR_IN 0x80 /* to host */ + +#define USB_TYPE_MASK (0x03 << 5) +#define USB_TYPE_STANDARD (0x00 << 5) +#define USB_TYPE_CLASS (0x01 << 5) +#define USB_TYPE_VENDOR (0x02 << 5) +#define USB_TYPE_RESERVED (0x03 << 5) + + +/* + * USB recipients, the third of three bRequestType fields + */ +#define USB_RECIP_MASK 0x1f +#define USB_RECIP_DEVICE 0x00 +#define USB_RECIP_INTERFACE 0x01 +#define USB_RECIP_ENDPOINT 0x02 +#define USB_RECIP_OTHER 0x03 +/* From Wireless USB 1.0 */ +#define USB_RECIP_PORT 0x04 +#define USB_RECIP_RPIPE 0x05 + +#define TU_ATTR_PACKED __attribute__((packed)) +#ifndef TU_BIT +#define TU_BIT(n) (1U << (n)) +#endif +#define TU_STRCAT(a, b) a##b ///< concat without expand +#define TU_XSTRCAT(a, b) TU_STRCAT(a, b) ///< expand then concat +// Compile-time Assert +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define TU_VERIFY_STATIC _Static_assert +#elif defined (__cplusplus) && __cplusplus >= 201103L + #define TU_VERIFY_STATIC static_assert +#else + #define TU_VERIFY_STATIC(const_expr, _mess) enum { TU_XSTRCAT(_verify_static_, _TU_COUNTER_) = 1/(!!(const_expr)) } +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/*------------------------------------------------------------------*/ +/* CONSTANTS + *------------------------------------------------------------------*/ + +/// defined base on EHCI specs value for Endpoint Speed +typedef enum +{ + TUSB_SPEED_FULL = 0, + TUSB_SPEED_LOW , + TUSB_SPEED_HIGH, + TUSB_SPEED_INVALID = 0xff, +}tusb_speed_t; + +/// defined base on USB Specs Endpoint's bmAttributes +typedef enum +{ + TUSB_XFER_CONTROL = 0 , + TUSB_XFER_ISOCHRONOUS , + TUSB_XFER_BULK , + TUSB_XFER_INTERRUPT +}tusb_xfer_type_t; + +typedef enum +{ + TUSB_DIR_OUT = 0, + TUSB_DIR_IN = 1, + + TUSB_DIR_IN_MASK = 0x80 +}tusb_dir_t; + +/// USB Descriptor Types +typedef enum +{ + TUSB_DESC_DEVICE = 0x01, + TUSB_DESC_CONFIGURATION = 0x02, + TUSB_DESC_STRING = 0x03, + TUSB_DESC_INTERFACE = 0x04, + TUSB_DESC_ENDPOINT = 0x05, + TUSB_DESC_DEVICE_QUALIFIER = 0x06, + TUSB_DESC_OTHER_SPEED_CONFIG = 0x07, + TUSB_DESC_INTERFACE_POWER = 0x08, + TUSB_DESC_OTG = 0x09, + TUSB_DESC_DEBUG = 0x0A, + TUSB_DESC_INTERFACE_ASSOCIATION = 0x0B, + + TUSB_DESC_BOS = 0x0F, + TUSB_DESC_DEVICE_CAPABILITY = 0x10, + + TUSB_DESC_FUNCTIONAL = 0x21, + + // Class Specific Descriptor + TUSB_DESC_CS_DEVICE = 0x21, + TUSB_DESC_CS_CONFIGURATION = 0x22, + TUSB_DESC_CS_STRING = 0x23, + TUSB_DESC_CS_INTERFACE = 0x24, + TUSB_DESC_CS_ENDPOINT = 0x25, + + TUSB_DESC_SUPERSPEED_ENDPOINT_COMPANION = 0x30, + TUSB_DESC_SUPERSPEED_ISO_ENDPOINT_COMPANION = 0x31 +}tusb_desc_type_t; + +typedef enum +{ + TUSB_REQ_GET_STATUS = 0 , + TUSB_REQ_CLEAR_FEATURE = 1 , + TUSB_REQ_RESERVED = 2 , + TUSB_REQ_SET_FEATURE = 3 , + TUSB_REQ_RESERVED2 = 4 , + TUSB_REQ_SET_ADDRESS = 5 , + TUSB_REQ_GET_DESCRIPTOR = 6 , + TUSB_REQ_SET_DESCRIPTOR = 7 , + TUSB_REQ_GET_CONFIGURATION = 8 , + TUSB_REQ_SET_CONFIGURATION = 9 , + TUSB_REQ_GET_INTERFACE = 10 , + TUSB_REQ_SET_INTERFACE = 11 , + TUSB_REQ_SYNCH_FRAME = 12 +}tusb_request_code_t; + +typedef enum +{ + TUSB_REQ_FEATURE_EDPT_HALT = 0, + TUSB_REQ_FEATURE_REMOTE_WAKEUP = 1, + TUSB_REQ_FEATURE_TEST_MODE = 2 +}tusb_request_feature_selector_t; + +typedef enum +{ + TUSB_REQ_TYPE_STANDARD = 0, + TUSB_REQ_TYPE_CLASS, + TUSB_REQ_TYPE_VENDOR, + TUSB_REQ_TYPE_INVALID +} tusb_request_type_t; + +typedef enum +{ + TUSB_REQ_RCPT_DEVICE =0, + TUSB_REQ_RCPT_INTERFACE, + TUSB_REQ_RCPT_ENDPOINT, + TUSB_REQ_RCPT_OTHER +} tusb_request_recipient_t; + +// https://www.usb.org/defined-class-codes +typedef enum +{ + TUSB_CLASS_UNSPECIFIED = 0 , + TUSB_CLASS_AUDIO = 1 , + TUSB_CLASS_CDC = 2 , + TUSB_CLASS_HID = 3 , + TUSB_CLASS_RESERVED_4 = 4 , + TUSB_CLASS_PHYSICAL = 5 , + TUSB_CLASS_IMAGE = 6 , + TUSB_CLASS_PRINTER = 7 , + TUSB_CLASS_MSC = 8 , + TUSB_CLASS_HUB = 9 , + TUSB_CLASS_CDC_DATA = 10 , + TUSB_CLASS_SMART_CARD = 11 , + TUSB_CLASS_RESERVED_12 = 12 , + TUSB_CLASS_CONTENT_SECURITY = 13 , + TUSB_CLASS_VIDEO = 14 , + TUSB_CLASS_PERSONAL_HEALTHCARE = 15 , + TUSB_CLASS_AUDIO_VIDEO = 16 , + + TUSB_CLASS_DIAGNOSTIC = 0xDC , + TUSB_CLASS_WIRELESS_CONTROLLER = 0xE0 , + TUSB_CLASS_MISC = 0xEF , + TUSB_CLASS_APPLICATION_SPECIFIC = 0xFE , + TUSB_CLASS_VENDOR_SPECIFIC = 0xFF +}tusb_class_code_t; + +typedef enum +{ + MISC_SUBCLASS_COMMON = 2 +}misc_subclass_type_t; + +typedef enum +{ + MISC_PROTOCOL_IAD = 1 +}misc_protocol_type_t; + +typedef enum +{ + APP_SUBCLASS_USBTMC = 0x03, + APP_SUBCLASS_DFU_RUNTIME = 0x01 +} app_subclass_type_t; + +typedef enum +{ + DEVICE_CAPABILITY_WIRELESS_USB = 0x01, + DEVICE_CAPABILITY_USB20_EXTENSION = 0x02, + DEVICE_CAPABILITY_SUPERSPEED_USB = 0x03, + DEVICE_CAPABILITY_CONTAINER_id = 0x04, + DEVICE_CAPABILITY_PLATFORM = 0x05, + DEVICE_CAPABILITY_POWER_DELIVERY = 0x06, + DEVICE_CAPABILITY_BATTERY_INFO = 0x07, + DEVICE_CAPABILITY_PD_CONSUMER_PORT = 0x08, + DEVICE_CAPABILITY_PD_PROVIDER_PORT = 0x09, + DEVICE_CAPABILITY_SUPERSPEED_PLUS = 0x0A, + DEVICE_CAPABILITY_PRECESION_TIME_MEASUREMENT = 0x0B, + DEVICE_CAPABILITY_WIRELESS_USB_EXT = 0x0C, + DEVICE_CAPABILITY_BILLBOARD = 0x0D, + DEVICE_CAPABILITY_AUTHENTICATION = 0x0E, + DEVICE_CAPABILITY_BILLBOARD_EX = 0x0F, + DEVICE_CAPABILITY_CONFIGURATION_SUMMARY = 0x10 +}device_capability_type_t; + +enum { + TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP = TU_BIT(5), + TUSB_DESC_CONFIG_ATT_SELF_POWERED = TU_BIT(6), +}; + +#define TUSB_DESC_CONFIG_POWER_MA(x) ((x)/2) + +/// Device State TODO remove +typedef enum +{ + TUSB_DEVICE_STATE_UNPLUG = 0 , + TUSB_DEVICE_STATE_CONFIGURED , + TUSB_DEVICE_STATE_SUSPENDED , +}tusb_device_state_t; + +typedef enum +{ + XFER_RESULT_SUCCESS, + XFER_RESULT_FAILED, + XFER_RESULT_STALLED, +}xfer_result_t; + +enum // TODO remove +{ + DESC_OFFSET_LEN = 0, + DESC_OFFSET_TYPE = 1 +}; + +enum +{ + INTERFACE_INVALID_NUMBER = 0xff +}; + + +typedef enum +{ + MS_OS_20_SET_HEADER_DESCRIPTOR = 0x00, + MS_OS_20_SUBSET_HEADER_CONFIGURATION = 0x01, + MS_OS_20_SUBSET_HEADER_FUNCTION = 0x02, + MS_OS_20_FEATURE_COMPATBLE_ID = 0x03, + MS_OS_20_FEATURE_REG_PROPERTY = 0x04, + MS_OS_20_FEATURE_MIN_RESUME_TIME = 0x05, + MS_OS_20_FEATURE_MODEL_ID = 0x06, + MS_OS_20_FEATURE_CCGP_DEVICE = 0x07, + MS_OS_20_FEATURE_VENDOR_REVISION = 0x08 +} microsoft_os_20_type_t; + +enum +{ + CONTROL_STAGE_SETUP, + CONTROL_STAGE_DATA, + CONTROL_STAGE_ACK +}; + +//--------------------------------------------------------------------+ +// USB Descriptors +//--------------------------------------------------------------------+ + +/// USB Device Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType ; ///< DEVICE Descriptor Type. + uint16_t bcdUSB ; ///< BUSB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H). This field identifies the release of the USB Specification with which the device and its descriptors are compliant. + + uint8_t bDeviceClass ; ///< Class code (assigned by the USB-IF). \li If this field is reset to zero, each interface within a configuration specifies its own class information and the various interfaces operate independently. \li If this field is set to a value between 1 and FEH, the device supports different class specifications on different interfaces and the interfaces may not operate independently. This value identifies the class definition used for the aggregate interfaces. \li If this field is set to FFH, the device class is vendor-specific. + uint8_t bDeviceSubClass ; ///< Subclass code (assigned by the USB-IF). These codes are qualified by the value of the bDeviceClass field. \li If the bDeviceClass field is reset to zero, this field must also be reset to zero. \li If the bDeviceClass field is not set to FFH, all values are reserved for assignment by the USB-IF. + uint8_t bDeviceProtocol ; ///< Protocol code (assigned by the USB-IF). These codes are qualified by the value of the bDeviceClass and the bDeviceSubClass fields. If a device supports class-specific protocols on a device basis as opposed to an interface basis, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use class-specific protocols on a device basis. However, it may use classspecific protocols on an interface basis. \li If this field is set to FFH, the device uses a vendor-specific protocol on a device basis. + uint8_t bMaxPacketSize0 ; ///< Maximum packet size for endpoint zero (only 8, 16, 32, or 64 are valid). For HS devices is fixed to 64. + + uint16_t idVendor ; ///< Vendor ID (assigned by the USB-IF). + uint16_t idProduct ; ///< Product ID (assigned by the manufacturer). + uint16_t bcdDevice ; ///< Device release number in binary-coded decimal. + uint8_t iManufacturer ; ///< Index of string descriptor describing manufacturer. + uint8_t iProduct ; ///< Index of string descriptor describing product. + uint8_t iSerialNumber ; ///< Index of string descriptor describing the device's serial number. + + uint8_t bNumConfigurations ; ///< Number of possible configurations. +} tusb_desc_device_t; + +TU_VERIFY_STATIC( sizeof(tusb_desc_device_t) == 18, "size is not correct"); + +// USB Binary Device Object Store (BOS) Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes + uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type + uint16_t wTotalLength ; ///< Total length of data returned for this descriptor + uint8_t bNumDeviceCaps ; ///< Number of device capability descriptors in the BOS +} tusb_desc_bos_t; + +/// USB Configuration Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes + uint8_t bDescriptorType ; ///< CONFIGURATION Descriptor Type + uint16_t wTotalLength ; ///< Total length of data returned for this configuration. Includes the combined length of all descriptors (configuration, interface, endpoint, and class- or vendor-specific) returned for this configuration. + + uint8_t bNumInterfaces ; ///< Number of interfaces supported by this configuration + uint8_t bConfigurationValue ; ///< Value to use as an argument to the SetConfiguration() request to select this configuration. + uint8_t iConfiguration ; ///< Index of string descriptor describing this configuration + uint8_t bmAttributes ; ///< Configuration characteristics \n D7: Reserved (set to one)\n D6: Self-powered \n D5: Remote Wakeup \n D4...0: Reserved (reset to zero) \n D7 is reserved and must be set to one for historical reasons. \n A device configuration that uses power from the bus and a local source reports a non-zero value in bMaxPower to indicate the amount of bus power required and sets D6. The actual power source at runtime may be determined using the GetStatus(DEVICE) request (see USB 2.0 spec Section 9.4.5). \n If a device configuration supports remote wakeup, D5 is set to one. + uint8_t bMaxPower ; ///< Maximum power consumption of the USB device from the bus in this specific configuration when the device is fully operational. Expressed in 2 mA units (i.e., 50 = 100 mA). +} tusb_desc_configuration_t; + +/// USB Interface Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes + uint8_t bDescriptorType ; ///< INTERFACE Descriptor Type + + uint8_t bInterfaceNumber ; ///< Number of this interface. Zero-based value identifying the index in the array of concurrent interfaces supported by this configuration. + uint8_t bAlternateSetting ; ///< Value used to select this alternate setting for the interface identified in the prior field + uint8_t bNumEndpoints ; ///< Number of endpoints used by this interface (excluding endpoint zero). If this value is zero, this interface only uses the Default Control Pipe. + uint8_t bInterfaceClass ; ///< Class code (assigned by the USB-IF). \li A value of zero is reserved for future standardization. \li If this field is set to FFH, the interface class is vendor-specific. \li All other values are reserved for assignment by the USB-IF. + uint8_t bInterfaceSubClass ; ///< Subclass code (assigned by the USB-IF). \n These codes are qualified by the value of the bInterfaceClass field. \li If the bInterfaceClass field is reset to zero, this field must also be reset to zero. \li If the bInterfaceClass field is not set to FFH, all values are reserved for assignment by the USB-IF. + uint8_t bInterfaceProtocol ; ///< Protocol code (assigned by the USB). \n These codes are qualified by the value of the bInterfaceClass and the bInterfaceSubClass fields. If an interface supports class-specific requests, this code identifies the protocols that the device uses as defined by the specification of the device class. \li If this field is reset to zero, the device does not use a class-specific protocol on this interface. \li If this field is set to FFH, the device uses a vendor-specific protocol for this interface. + uint8_t iInterface ; ///< Index of string descriptor describing this interface +} tusb_desc_interface_t; + +/// USB Endpoint Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes + uint8_t bDescriptorType ; ///< ENDPOINT Descriptor Type + + uint8_t bEndpointAddress ; ///< The address of the endpoint on the USB device described by this descriptor. The address is encoded as follows: \n Bit 3...0: The endpoint number \n Bit 6...4: Reserved, reset to zero \n Bit 7: Direction, ignored for control endpoints 0 = OUT endpoint 1 = IN endpoint. + + struct TU_ATTR_PACKED { + uint8_t xfer : 2; + uint8_t sync : 2; + uint8_t usage : 2; + uint8_t : 2; + } bmAttributes ; ///< This field describes the endpoint's attributes when it is configured using the bConfigurationValue. \n Bits 1..0: Transfer Type \n- 00 = Control \n- 01 = Isochronous \n- 10 = Bulk \n- 11 = Interrupt \n If not an isochronous endpoint, bits 5..2 are reserved and must be set to zero. If isochronous, they are defined as follows: \n Bits 3..2: Synchronization Type \n- 00 = No Synchronization \n- 01 = Asynchronous \n- 10 = Adaptive \n- 11 = Synchronous \n Bits 5..4: Usage Type \n- 00 = Data endpoint \n- 01 = Feedback endpoint \n- 10 = Implicit feedback Data endpoint \n- 11 = Reserved \n Refer to Chapter 5 of USB 2.0 specification for more information. \n All other bits are reserved and must be reset to zero. Reserved bits must be ignored by the host. + + struct TU_ATTR_PACKED { + uint16_t size : 11; ///< Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. \n For isochronous endpoints, this value is used to reserve the bus time in the schedule, required for the per-(micro)frame data payloads. The pipe may, on an ongoing basis, actually use less bandwidth than that reserved. The device reports, if necessary, the actual bandwidth used via its normal, non-USB defined mechanisms. \n For all endpoints, bits 10..0 specify the maximum packet size (in bytes). \n For high-speed isochronous and interrupt endpoints: \n Bits 12..11 specify the number of additional transaction opportunities per microframe: \n- 00 = None (1 transaction per microframe) \n- 01 = 1 additional (2 per microframe) \n- 10 = 2 additional (3 per microframe) \n- 11 = Reserved \n Bits 15..13 are reserved and must be set to zero. + uint16_t hs_period_mult : 2; + uint16_t TU_RESERVED : 3; + }wMaxPacketSize; + + uint8_t bInterval ; ///< Interval for polling endpoint for data transfers. Expressed in frames or microframes depending on the device operating speed (i.e., either 1 millisecond or 125 us units). \n- For full-/high-speed isochronous endpoints, this value must be in the range from 1 to 16. The bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$). \n- For full-/low-speed interrupt endpoints, the value of this field may be from 1 to 255. \n- For high-speed interrupt endpoints, the bInterval value is used as the exponent for a \f$ 2^(bInterval-1) \f$ value; e.g., a bInterval of 4 means a period of 8 (\f$ 2^(4-1) \f$) . This value must be from 1 to 16. \n- For high-speed bulk/control OUT endpoints, the bInterval must specify the maximum NAK rate of the endpoint. A value of 0 indicates the endpoint never NAKs. Other values indicate at most 1 NAK each bInterval number of microframes. This value must be in the range from 0 to 255. \n Refer to Chapter 5 of USB 2.0 specification for more information. +} tusb_desc_endpoint_t; + +/// USB Other Speed Configuration Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Other_speed_Configuration Type + uint16_t wTotalLength ; ///< Total length of data returned + + uint8_t bNumInterfaces ; ///< Number of interfaces supported by this speed configuration + uint8_t bConfigurationValue ; ///< Value to use to select configuration + uint8_t IConfiguration ; ///< Index of string descriptor + uint8_t bmAttributes ; ///< Same as Configuration descriptor + uint8_t bMaxPower ; ///< Same as Configuration descriptor +} tusb_desc_other_speed_t; + +/// USB Device Qualifier Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Device Qualifier Type + uint16_t bcdUSB ; ///< USB specification version number (e.g., 0200H for V2.00) + + uint8_t bDeviceClass ; ///< Class Code + uint8_t bDeviceSubClass ; ///< SubClass Code + uint8_t bDeviceProtocol ; ///< Protocol Code + uint8_t bMaxPacketSize0 ; ///< Maximum packet size for other speed + uint8_t bNumConfigurations ; ///< Number of Other-speed Configurations + uint8_t bReserved ; ///< Reserved for future use, must be zero +} tusb_desc_device_qualifier_t; + +/// USB Interface Association Descriptor (IAD ECN) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Other_speed_Configuration Type + + uint8_t bFirstInterface ; ///< Index of the first associated interface. + uint8_t bInterfaceCount ; ///< Total number of associated interfaces. + + uint8_t bFunctionClass ; ///< Interface class ID. + uint8_t bFunctionSubClass ; ///< Interface subclass ID. + uint8_t bFunctionProtocol ; ///< Interface protocol ID. + + uint8_t iFunction ; ///< Index of the string descriptor describing the interface association. +} tusb_desc_interface_assoc_t; + +// USB String Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength ; ///< Size of this descriptor in bytes + uint8_t bDescriptorType ; ///< Descriptor Type + uint16_t unicode_string[]; +} tusb_desc_string_t; + +// USB Binary Device Object Store (BOS) +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength; + uint8_t bDescriptorType ; + uint8_t bDevCapabilityType; + uint8_t bReserved; + uint8_t PlatformCapabilityUUID[16]; + uint8_t CapabilityData[]; +} tusb_desc_bos_platform_t; + +// USB WebuSB URL Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bScheme; + char url[]; +} tusb_desc_webusb_url_t; + +/*------------------------------------------------------------------*/ +/* Types + *------------------------------------------------------------------*/ +typedef struct TU_ATTR_PACKED{ + union { + struct TU_ATTR_PACKED { + uint8_t recipient : 5; ///< Recipient type tusb_request_recipient_t. + uint8_t type : 2; ///< Request type tusb_request_type_t. + uint8_t direction : 1; ///< Direction type. tusb_dir_t + } bmRequestType_bit; + + uint8_t bmRequestType; + }; + + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} tusb_control_request_t; + +TU_VERIFY_STATIC( sizeof(tusb_control_request_t) == 8, "size is not correct"); + +// TODO move to somewhere suitable +static inline uint8_t bm_request_type(uint8_t direction, uint8_t type, uint8_t recipient) +{ + return ((uint8_t) (direction << 7)) | ((uint8_t) (type << 5)) | (recipient); +} + +//--------------------------------------------------------------------+ +// Endpoint helper +//--------------------------------------------------------------------+ + +// Get direction from Endpoint address +static inline tusb_dir_t tu_edpt_dir(uint8_t addr) +{ + return (addr & TUSB_DIR_IN_MASK) ? TUSB_DIR_IN : TUSB_DIR_OUT; +} + +// Get Endpoint number from address +static inline uint8_t tu_edpt_number(uint8_t addr) +{ + return (uint8_t)(addr & (~TUSB_DIR_IN_MASK)); +} + +static inline uint8_t tu_edpt_addr(uint8_t num, uint8_t dir) +{ + return (uint8_t)(num | (dir ? TUSB_DIR_IN_MASK : 0)); +} + +//--------------------------------------------------------------------+ +// Descriptor helper +//--------------------------------------------------------------------+ +static inline uint8_t const * tu_desc_next(void const* desc) +{ + uint8_t const* desc8 = (uint8_t const*) desc; + return desc8 + desc8[DESC_OFFSET_LEN]; +} + +static inline uint8_t tu_desc_type(void const* desc) +{ + return ((uint8_t const*) desc)[DESC_OFFSET_TYPE]; +} + +static inline uint8_t tu_desc_len(void const* desc) +{ + return ((uint8_t const*) desc)[DESC_OFFSET_LEN]; +} + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_TYPES_H_ */ + +/** @} */ + + +#if 0 + +/* USB Setup Request */ +typedef struct __attribute__((packed)) _USB_SETUP_REQ +{ + uint8_t bRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} USB_SETUP_REQ, *PUSB_SETUP_REQ; + +/* USB Device Descriptor */ +typedef struct __attribute__((packed)) _USB_DEVICE_DESCR +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; +} USB_DEV_DESCR, *PUSB_DEV_DESCR; + +/* USB Configuration Descriptor */ +typedef struct __attribute__((packed)) _USB_CONFIG_DESCR +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t MaxPower; +} USB_CFG_DESCR, *PUSB_CFG_DESCR; + +/* USB Interface Descriptor */ +typedef struct __attribute__((packed)) _USB_INTERF_DESCR +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; +} USB_ITF_DESCR, *PUSB_ITF_DESCR; + +/* USB Endpoint Descriptor */ +typedef struct __attribute__((packed)) _USB_ENDPOINT_DESCR +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint8_t wMaxPacketSizeL; + uint8_t wMaxPacketSizeH; + uint8_t bInterval; +} USB_ENDP_DESCR, *PUSB_ENDP_DESCR; + +/* USB Configuration Descriptor Set */ +typedef struct __attribute__((packed)) _USB_CONFIG_DESCR_LONG +{ + USB_CFG_DESCR cfg_descr; + USB_ITF_DESCR itf_descr; + USB_ENDP_DESCR endp_descr[ 1 ]; +} USB_CFG_DESCR_LONG, *PUSB_CFG_DESCR_LONG; + +/* USB HUB Descriptor */ +typedef struct __attribute__((packed)) _USB_HUB_DESCR +{ + uint8_t bDescLength; + uint8_t bDescriptorType; + uint8_t bNbrPorts; + uint8_t wHubCharacteristicsL; + uint8_t wHubCharacteristicsH; + uint8_t bPwrOn2PwrGood; + uint8_t bHubContrCurrent; + uint8_t DeviceRemovable; + uint8_t PortPwrCtrlMask; +} USB_HUB_DESCR, *PUSB_HUB_DESCR; + +/* USB HID Descriptor */ +typedef struct __attribute__((packed)) _USB_HID_DESCR +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdHID; + uint8_t bCountryCode; + uint8_t bNumDescriptors; + uint8_t bDescriptorTypeX; + uint8_t wDescriptorLengthL; + uint8_t wDescriptorLengthH; +} USB_HID_DESCR, *PUSB_HID_DESCR; + + +/*******************************************************************************/ +/* USB Communication Related Macro Definition */ + +/* USB PID */ +#ifndef USB_PID_SETUP +#define USB_PID_NULL 0x00 +#define USB_PID_SOF 0x05 +#define USB_PID_SETUP 0x0D +#define USB_PID_IN 0x09 +#define USB_PID_OUT 0x01 +#define USB_PID_NYET 0x06 +#define USB_PID_ACK 0x02 +#define USB_PID_NAK 0x0A +#define USB_PID_STALL 0x0E +#define USB_PID_DATA0 0x03 +#define USB_PID_DATA1 0x0B +#define USB_PID_PRE 0x0C +#endif + +/* USB standard device request code */ +#ifndef USB_GET_DESCRIPTOR +#define USB_GET_STATUS 0x00 +#define USB_CLEAR_FEATURE 0x01 +#define USB_SET_FEATURE 0x03 +#define USB_SET_ADDRESS 0x05 +#define USB_GET_DESCRIPTOR 0x06 +#define USB_SET_DESCRIPTOR 0x07 +#define USB_GET_CONFIGURATION 0x08 +#define USB_SET_CONFIGURATION 0x09 +#define USB_GET_INTERFACE 0x0A +#define USB_SET_INTERFACE 0x0B +#define USB_SYNCH_FRAME 0x0C +#endif + +#define DEF_STRING_DESC_LANG 0x00 +#define DEF_STRING_DESC_MANU 0x01 +#define DEF_STRING_DESC_PROD 0x02 +#define DEF_STRING_DESC_SERN 0x03 + +/* USB hub class request code */ +#ifndef HUB_GET_DESCRIPTOR +#define HUB_GET_STATUS 0x00 +#define HUB_CLEAR_FEATURE 0x01 +#define HUB_GET_STATE 0x02 +#define HUB_SET_FEATURE 0x03 +#define HUB_GET_DESCRIPTOR 0x06 +#define HUB_SET_DESCRIPTOR 0x07 +#endif + +/* USB HID class request code */ +#ifndef HID_GET_REPORT +#define HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0A +#define HID_SET_PROTOCOL 0x0B +#endif + +/* Bit Define for USB Request Type */ +#ifndef USB_REQ_TYP_MASK +#define USB_REQ_TYP_IN 0x80 +#define USB_REQ_TYP_OUT 0x00 +#define USB_REQ_TYP_READ 0x80 +#define USB_REQ_TYP_WRITE 0x00 +#define USB_REQ_TYP_MASK 0x60 +#define USB_REQ_TYP_STANDARD 0x00 +#define USB_REQ_TYP_CLASS 0x20 +#define USB_REQ_TYP_VENDOR 0x40 +#define USB_REQ_TYP_RESERVED 0x60 +#define USB_REQ_RECIP_MASK 0x1F +#define USB_REQ_RECIP_DEVICE 0x00 +#define USB_REQ_RECIP_INTERF 0x01 +#define USB_REQ_RECIP_ENDP 0x02 +#define USB_REQ_RECIP_OTHER 0x03 +#define USB_REQ_FEAT_REMOTE_WAKEUP 0x01 +#define USB_REQ_FEAT_ENDP_HALT 0x00 +#endif + +/* USB Descriptor Type */ +#ifndef USB_DESCR_TYP_DEVICE +#define USB_DESCR_TYP_DEVICE 0x01 +#define USB_DESCR_TYP_CONFIG 0x02 +#define USB_DESCR_TYP_STRING 0x03 +#define USB_DESCR_TYP_INTERF 0x04 +#define USB_DESCR_TYP_ENDP 0x05 +#define USB_DESCR_TYP_QUALIF 0x06 +#define USB_DESCR_TYP_SPEED 0x07 +#define USB_DESCR_TYP_OTG 0x09 +#define USB_DESCR_TYP_BOS 0X0F +#define USB_DESCR_TYP_HID 0x21 +#define USB_DESCR_TYP_REPORT 0x22 +#define USB_DESCR_TYP_PHYSIC 0x23 +#define USB_DESCR_TYP_CS_INTF 0x24 +#define USB_DESCR_TYP_CS_ENDP 0x25 +#define USB_DESCR_TYP_HUB 0x29 +#endif + +/* USB Device Class */ +#ifndef USB_DEV_CLASS_HUB +#define USB_DEV_CLASS_RESERVED 0x00 +#define USB_DEV_CLASS_AUDIO 0x01 +#define USB_DEV_CLASS_COMMUNIC 0x02 +#define USB_DEV_CLASS_HID 0x03 +#define USB_DEV_CLASS_MONITOR 0x04 +#define USB_DEV_CLASS_PHYSIC_IF 0x05 +#define USB_DEV_CLASS_POWER 0x06 +#define USB_DEV_CLASS_PRINTER 0x07 +#define USB_DEV_CLASS_STORAGE 0x08 +#define USB_DEV_CLASS_HUB 0x09 +#define USB_DEV_CLASS_VEN_SPEC 0xFF +#endif + +/* USB Hub Class Request */ +#ifndef HUB_GET_HUB_DESCRIPTOR +#define HUB_CLEAR_HUB_FEATURE 0x20 +#define HUB_CLEAR_PORT_FEATURE 0x23 +#define HUB_GET_BUS_STATE 0xA3 +#define HUB_GET_HUB_DESCRIPTOR 0xA0 +#define HUB_GET_HUB_STATUS 0xA0 +#define HUB_GET_PORT_STATUS 0xA3 +#define HUB_SET_HUB_DESCRIPTOR 0x20 +#define HUB_SET_HUB_FEATURE 0x20 +#define HUB_SET_PORT_FEATURE 0x23 +#endif + +/* Hub Class Feature Selectors */ +#ifndef HUB_PORT_RESET +#define HUB_C_HUB_LOCAL_POWER 0 +#define HUB_C_HUB_OVER_CURRENT 1 +#define HUB_PORT_CONNECTION 0 +#define HUB_PORT_ENABLE 1 +#define HUB_PORT_SUSPEND 2 +#define HUB_PORT_OVER_CURRENT 3 +#define HUB_PORT_RESET 4 +#define HUB_PORT_POWER 8 +#define HUB_PORT_LOW_SPEED 9 +#define HUB_C_PORT_CONNECTION 16 +#define HUB_C_PORT_ENABLE 17 +#define HUB_C_PORT_SUSPEND 18 +#define HUB_C_PORT_OVER_CURRENT 19 +#define HUB_C_PORT_RESET 20 +#endif + +/* USB HID Class Request Code */ +#ifndef HID_GET_REPORT +#define HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0A +#define HID_SET_PROTOCOL 0x0B +#endif + +/* USB UDisk */ +#ifndef USB_BO_CBW_SIZE +#define USB_BO_CBW_SIZE 0x1F +#define USB_BO_CSW_SIZE 0x0D +#endif +#ifndef USB_BO_CBW_SIG0 +#define USB_BO_CBW_SIG0 0x55 +#define USB_BO_CBW_SIG1 0x53 +#define USB_BO_CBW_SIG2 0x42 +#define USB_BO_CBW_SIG3 0x43 +#define USB_BO_CSW_SIG0 0x55 +#define USB_BO_CSW_SIG1 0x53 +#define USB_BO_CSW_SIG2 0x42 +#define USB_BO_CSW_SIG3 0x53 +#endif + +/* USB CDC Class request code */ +#ifndef CDC_GET_LINE_CODING +#define CDC_GET_LINE_CODING 0X21 /* This request allows the host to find out the currently configured line coding */ +#define CDC_SET_LINE_CODING 0x20 /* Configures DTE rate, stop-bits, parity, and number-of-character */ +#define CDC_SET_LINE_CTLSTE 0X22 /* This request generates RS-232/V.24 style control signals */ +#define CDC_SEND_BREAK 0X23 /* Sends special carrier modulation used to specify RS-232 style break */ +#endif +/*******************************************************************************/ + + + +#endif diff --git a/examples_x035/usbdevice.incomplete/usbdevice.c b/examples_x035/usbdevice.incomplete/usbdevice.c index 3dfd0251..2f3c3c1f 100644 --- a/examples_x035/usbdevice.incomplete/usbdevice.c +++ b/examples_x035/usbdevice.incomplete/usbdevice.c @@ -30,7 +30,6 @@ void USBFS_IRQHandler(); while(1) { printf( "%lu %08x %lu %d %d\n", USBDEBUG0, USBDEBUG1, USBDEBUG2, 0, 0 ); - USBFS_Poll(); int i; //printf( "!! %d %d %d\n", NUM_EP, USBFS_Endp_Busy[0], USBFS_Endp_Busy[1] ); for( i = 1; i < 3; i++ ) @@ -46,7 +45,19 @@ USBDEBUG0+= 100; // USBFSD_UEP_TX_CTRL( i ) = ( USBFSD_UEP_TX_CTRL( i ) & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_ACK; // USBFS_Endp_Busy[i] = 1; - char pbuf[16] = { 0x00, 1, 1 }; + char pbuf[16] = { 0xaa, 1, 1 }; +/* static iter; + if( i == 2 ) + { + iter++; + switch( (iter>>3) & 3 ) + { + case 0: pbuf[1] = 1; break; + case 1: pbuf[2] = 1; break; + case 2: pbuf[1] = -1; break; + case 3: pbuf[2] = -1; break; + } + }*/ uint8_t r = USBFS_Endp_DataUp( i, pbuf, (i==1)?8:4, DEF_UEP_CPY_LOAD); //USBDEBUG1+=r; } From 85a1f95b28afba82e058ae5b22acc11a77849a61 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sun, 21 Apr 2024 23:52:31 -0400 Subject: [PATCH 15/31] Working with DMA --- ch32v003fun/ch32v003fun.h | 2 - examples_x035/usbdevice.incomplete/fsusb.c | 375 ++++++------------ examples_x035/usbdevice.incomplete/fsusb.h | 69 ++-- .../usbdevice.incomplete/usbdevice.c | 51 +-- 4 files changed, 173 insertions(+), 324 deletions(-) diff --git a/ch32v003fun/ch32v003fun.h b/ch32v003fun/ch32v003fun.h index 844b74ed..28dd5e5e 100644 --- a/ch32v003fun/ch32v003fun.h +++ b/ch32v003fun/ch32v003fun.h @@ -1784,8 +1784,6 @@ typedef struct #define USBFSD_UEP_RX_EN 0x08 #define USBFSD_UEP_TX_EN 0x04 #define USBFSD_UEP_BUF_MOD 0x01 -#define DEF_UEP_DMA_LOAD 0 /* Direct the DMA address to the data to be processed */ -#define DEF_UEP_CPY_LOAD 1 /* Use memcpy to move data to a buffer */ #define USBFSD_UEP_MOD( N ) (*((volatile uint8_t *)( USBFSD_UEP_MOD_BASE + N ))) #define USBFSD_UEP_TX_CTRL( N ) (*((volatile uint8_t *)( USBFSD_UEP_CTL_BASE + N * 0x04 ))) #define USBFSD_UEP_RX_CTRL( N ) (*((volatile uint8_t *)( USBFSD_UEP_CTL_BASE + N * 0x04 ))) diff --git a/examples_x035/usbdevice.incomplete/fsusb.c b/examples_x035/usbdevice.incomplete/fsusb.c index d16530eb..1023b809 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.c +++ b/examples_x035/usbdevice.incomplete/fsusb.c @@ -5,6 +5,7 @@ uint32_t USBDEBUG0, USBDEBUG1, USBDEBUG2; +#define UEP_CTRL_H(n) (((uint16_t*)&USBFS->UEP0_CTRL_H)[n*2]) struct _USBState FSUSBCTX; @@ -29,9 +30,50 @@ struct _USBState FSUSBCTX; #define CUIS_TOKEN_IN 0x2 #define CUIS_TOKEN_SETUP 0x3 +#if 0 +static inline void fastcopy( uint8_t * dest, const uint8_t * src, int len ) +{ + src = ((intptr_t)src) & ~3; + asm volatile( "\ + add a3, %[src], %[len]\n\ +1:\n\ + lw a4, 0(%[src])\n\ + lw a5, 4(%[src])\n\ + lw s1, 8(%[src])\n\ + lw s2, 12(%[src])\n\ + addi %[src],%[src],16\n\ + sw a4, 0(%[dest])\n\ + sw a5, 4(%[dest])\n\ + sw s1, 8(%[dest])\n\ + sw s2, 12(%[dest])\n\ + addi %[dest],%[dest],16\n\ + bgtu a3,%[src],1b\n\ + " : [dest]"+r"(dest), [src]"+r"(src) : [len]"r"(len) : "memory", "a3", "a4", "a5", "s1", "s2" ); +} +#else +static inline void fastcopy( uint8_t * dest, const uint8_t * src, int len ) +{ + DMA1_Channel7->CFGR = 0; + DMA1_Channel7->MADDR = src; + DMA1_Channel7->PADDR = dest; + DMA1_Channel7->CNTR = (len+3)/4; + DMA1_Channel7->CFGR = + DMA_M2M_Enable | + DMA_DIR_PeripheralDST | + DMA_Priority_High | + DMA_MemoryDataSize_Word | + DMA_PeripheralDataSize_Word | + DMA_MemoryInc_Enable | + DMA_PeripheralInc_Enable | + DMA_Mode_Normal | DMA_CFGR1_EN; +//XXX TODO: It seems to work (unsafely) without this guard. + while( DMA1_Channel7->CNTR ); +} +#endif void USBFS_IRQHandler() __attribute__((section(".text.vector_handler"))) __attribute__((interrupt)); +void USBFS_InternalFinishSetup(); void USBFS_IRQHandler() { @@ -52,10 +94,18 @@ void USBFS_IRQHandler() switch ( token ) { case CUIS_TOKEN_IN: - switch( ep ) + if( ep ) { - /* end-point 0 data in interrupt */ - case DEF_UEP0: + if( ep < FUSB_CONFIG_EPS ) + { + UEP_CTRL_H(ep) = ( UEP_CTRL_H(ep) & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_NAK; + UEP_CTRL_H(ep) ^= USBFS_UEP_T_TOG; + ctx->USBFS_Endp_Busy[ ep ] = 0; + } + } + else + { + /* end-point 0 data in interrupt */ if( ctx->USBFS_SetupReqLen == 0 ) { USBFS->UEP0_CTRL_H = USBFS_UEP_R_TOG | USBFS_UEP_R_RES_ACK; @@ -71,11 +121,12 @@ void USBFS_IRQHandler() { case USB_GET_DESCRIPTOR: len = ctx->USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : ctx->USBFS_SetupReqLen; - memcpy( ctx->USBFS_EP_Buf[0], ctx->pUSBFS_Descr, len ); - ctx->USBFS_SetupReqLen -= len; - ctx->pUSBFS_Descr += len; + //memcpy( CTRL0BUFF, ctx->pUSBFS_Descr, len ); // FYI -> IS IT POSSIBLE TO DO THIS WITH DMA???? + fastcopy( CTRL0BUFF, ctx->pUSBFS_Descr, len ); // FYI -> Would need to do this if using DMA USBFS->UEP0_TX_LEN = len; USBFS->UEP0_CTRL_H ^= USBFS_UEP_T_TOG; + ctx->USBFS_SetupReqLen -= len; + ctx->pUSBFS_Descr += len; break; case USB_SET_ADDRESS: @@ -86,24 +137,6 @@ void USBFS_IRQHandler() break; } } - break; - - /* end-point 1 data in interrupt */ - case DEF_UEP1: - USBFS->UEP1_CTRL_H = ( USBFS->UEP1_CTRL_H & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_NAK; - USBFS->UEP1_CTRL_H ^= USBFS_UEP_T_TOG; - ctx->USBFS_Endp_Busy[ DEF_UEP1 ] = 0; - break; - - /* end-point 2 data in interrupt */ - case DEF_UEP2: - USBFS->UEP2_CTRL_H = ( USBFS->UEP2_CTRL_H & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_NAK; - USBFS->UEP2_CTRL_H ^= USBFS_UEP_T_TOG; - ctx->USBFS_Endp_Busy[ DEF_UEP2 ] = 0; - break; - - default : - break; } break; @@ -123,7 +156,6 @@ void USBFS_IRQHandler() { case HID_SET_REPORT: //KB_LED_Cur_Status = USBFS_EP0_Buf[ 0 ]; - // Do stuff... FSUSBCTX.USBFS_SetupReqLen = 0; break; default: @@ -184,7 +216,7 @@ void USBFS_IRQHandler() case HID_GET_IDLE: if( USBFS_SetupReqIndex < FUSB_HID_INTERFACES ) { - FSUSBCTX.USBFS_EP_Buf[0][0] = FSUSBCTX.USBFS_HidIdle[ USBFS_SetupReqIndex ]; + CTRL0BUFF[0] = FSUSBCTX.USBFS_HidIdle[ USBFS_SetupReqIndex ]; len = 1; } break; @@ -192,13 +224,13 @@ void USBFS_IRQHandler() case HID_GET_PROTOCOL: if( USBFS_SetupReqIndex < FUSB_HID_INTERFACES ) { - FSUSBCTX.USBFS_EP_Buf[0][0] = FSUSBCTX.USBFS_HidProtocol[ USBFS_SetupReqIndex ]; + CTRL0BUFF[0] = FSUSBCTX.USBFS_HidProtocol[ USBFS_SetupReqIndex ]; len = 1; } break; default: - goto reporterror; + goto sendstall; break; } } @@ -212,9 +244,8 @@ void USBFS_IRQHandler() /* get device/configuration/string/report/... descriptors */ case USB_GET_DESCRIPTOR: { - int match = USBFS_IndexValue; - struct descriptor_list_struct * e = descriptor_list; - struct descriptor_list_struct * e_end = e + DESCRIPTOR_LIST_ENTRIES; + const struct descriptor_list_struct * e = descriptor_list; + const struct descriptor_list_struct * e_end = e + DESCRIPTOR_LIST_ENTRIES; for( ; e != e_end; e++ ) { if( e->lIndexValue == USBFS_IndexValue ) @@ -226,7 +257,7 @@ void USBFS_IRQHandler() } if( e == e_end ) { - goto reporterror; + goto sendstall; } /* Copy Descriptors to Endp0 DMA buffer */ @@ -235,8 +266,13 @@ void USBFS_IRQHandler() USBFS_SetupReqLen = len; } len = ( USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ) ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen; - memcpy( ctx->USBFS_EP_Buf[0], ctx->pUSBFS_Descr, len ); + fastcopy( CTRL0BUFF, ctx->pUSBFS_Descr, len ); //memcpy( CTRL0BUFF, ctx->pUSBFS_Descr, len ); + //memcpy( CTRL0BUFF, ctx->pUSBFS_Descr, len ); ctx->pUSBFS_Descr += len; +// USBFS_SetupReqLen -= len; +// USBFS->UEP0_TX_LEN = len; +// USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK; +// goto replycomplete; break; } @@ -247,11 +283,9 @@ void USBFS_IRQHandler() /* Get usb configuration now set */ case USB_GET_CONFIGURATION: - ctx->USBFS_EP_Buf[0][0] = ctx->USBFS_DevConfig; + CTRL0BUFF[0] = ctx->USBFS_DevConfig; if( ctx->USBFS_SetupReqLen > 1 ) - { ctx->USBFS_SetupReqLen = 1; - } break; /* Set usb configuration to use */ @@ -262,6 +296,7 @@ void USBFS_IRQHandler() /* Clear or disable one usb feature */ case USB_CLEAR_FEATURE: +#if FUSB_SUPPORTS_SLEEP if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE ) { /* clear one device feature */ @@ -272,39 +307,33 @@ void USBFS_IRQHandler() } else { - goto reporterror; + goto sendstall; } } - else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) + else +#endif + if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) { if( (uint8_t)( USBFS_IndexValue & 0xFF ) == USB_REQ_FEAT_ENDP_HALT ) { /* Clear End-point Feature */ - switch( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) ) + if( ( USBFS_SetupReqIndex & DEF_UEP_IN ) && ep < FUSB_CONFIG_EPS ) { - case ( DEF_UEP_IN | DEF_UEP1 ): - /* Set End-point 1 OUT ACK */ - USBFS->UEP1_CTRL_H = USBFS_UEP_T_RES_NAK; - break; - - case ( DEF_UEP_IN | DEF_UEP2 ): - /* Set End-point 2 IN NAK */ - USBFS->UEP2_CTRL_H = USBFS_UEP_T_RES_NAK; - break; - - default: - goto reporterror; - break; + UEP_CTRL_H(ep) = USBFS_UEP_T_RES_NAK; + } + else + { + goto sendstall; } } else { - goto reporterror; + goto sendstall; } } else { - goto reporterror; + goto sendstall; } break; @@ -322,7 +351,7 @@ void USBFS_IRQHandler() else #endif { - goto reporterror; + goto sendstall; } } else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) @@ -330,39 +359,20 @@ void USBFS_IRQHandler() /* Set Endpoint Feature */ if( (uint8_t)( USBFS_IndexValue & 0xFF ) == USB_REQ_FEAT_ENDP_HALT ) { - switch( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) ) - { - case ( DEF_UEP_IN | DEF_UEP1 ): - USBFS->UEP1_CTRL_H = ( USBFS->UEP1_CTRL_H & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_STALL; - break; - - case ( DEF_UEP_IN | DEF_UEP2 ): - USBFS->UEP2_CTRL_H = ( USBFS->UEP2_CTRL_H & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_STALL; - break; - - default: - goto reporterror; - break; - } + if( ( USBFS_SetupReqIndex & DEF_UEP_IN ) && ep < FUSB_CONFIG_EPS ) + UEP_CTRL_H(ep) = ( UEP_CTRL_H(ep) & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_STALL; } else - { - goto reporterror; - } + goto sendstall; } else - { - goto reporterror; - } + goto sendstall; break; /* This request allows the host to select another setting for the specified interface */ case USB_GET_INTERFACE: - ctx->USBFS_EP_Buf[0][0] = 0x00; - if( USBFS_SetupReqLen > 1 ) - { - USBFS_SetupReqLen = 1; - } + CTRL0BUFF[0] = 0x00; + if( USBFS_SetupReqLen > 1 ) USBFS_SetupReqLen = 1; break; case USB_SET_INTERFACE: @@ -370,52 +380,31 @@ void USBFS_IRQHandler() /* host get status of specified device/interface/end-points */ case USB_GET_STATUS: - ctx->USBFS_EP_Buf[0][0] = 0x00; - ctx->USBFS_EP_Buf[0][1] = 0x00; + CTRL0BUFF[0] = 0x00; + CTRL0BUFF[1] = 0x00; if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE ) { - if( ctx->USBFS_DevSleepStatus & 0x01 ) - { - ctx->USBFS_EP_Buf[0][0] = 0x02; - } - else - { - ctx->USBFS_EP_Buf[0][0] = 0x00; - } +#if FUSB_SUPPORTS_SLEEP + CTRL0BUFF[0] = (ctx->USBFS_DevSleepStatus & 0x01)<<1; +#else + CTRL0BUFF[0] = 0x00; +#endif } else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) { - if( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) == ( DEF_UEP_IN | DEF_UEP1 ) ) - { - if( ( USBFS->UEP1_CTRL_H & USBFS_UEP_T_RES_MASK ) == USBFS_UEP_T_RES_STALL ) - { - ctx->USBFS_EP_Buf[0][0] = 0x01; - } - } - else if( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) == ( DEF_UEP_IN | DEF_UEP2 ) ) - { - if( ( USBFS->UEP2_CTRL_H & USBFS_UEP_T_RES_MASK ) == USBFS_UEP_T_RES_STALL ) - { - ctx->USBFS_EP_Buf[0][0] = 0x01; - } - } + if( ( USBFS_SetupReqIndex & DEF_UEP_IN ) && ep < FUSB_CONFIG_EPS ) + CTRL0BUFF[0] = ( UEP_CTRL_H(ep) & USBFS_UEP_T_RES_MASK ) == USBFS_UEP_T_RES_STALL; else - { - goto reporterror; - } + goto sendstall; } else - { - goto reporterror; - } + goto sendstall; if( USBFS_SetupReqLen > 2 ) - { USBFS_SetupReqLen = 2; - } break; default: - goto reporterror; + goto sendstall; break; } } @@ -447,9 +436,11 @@ void USBFS_IRQHandler() // This might look a little weird, for error handling but it saves a nontrivial amount of storage, and simplifies // control flow to hard-abort here. - reporterror: + sendstall: // if one request not support, return stall. Stall means permanent error. USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_STALL|USBFS_UEP_R_TOG | USBFS_UEP_R_RES_STALL; + replycomplete: + break; /* Sof pack processing */ case CUIS_TOKEN_SOF: @@ -470,7 +461,7 @@ void USBFS_IRQHandler() ctx->USBFS_DevEnumStatus = 0; USBFS->DEV_ADDR = 0; - USBFS_Device_Endp_Init( ); + USBFS_InternalFinishSetup( ); } else if( intfgst & CRB_UIF_SUSPEND ) { @@ -497,21 +488,18 @@ void USBFS_IRQHandler() GPIOA->BSHR = 1<<16; } -void USBFS_Device_Endp_Init() +void USBFS_InternalFinishSetup() { USBFS->UEP4_1_MOD = RB_UEP1_TX_EN; USBFS->UEP2_3_MOD = RB_UEP2_TX_EN; USBFS->UEP567_MOD = 0; + USBFS->UEP0_DMA = FSUSBCTX.EP0DMABuffer; - USBFS->UEP0_DMA = (intptr_t)FSUSBCTX.USBFS_EP_Buf[0]; - USBFS->UEP1_DMA = (intptr_t)FSUSBCTX.USBFS_EP_Buf[1]; - USBFS->UEP2_DMA = (intptr_t)FSUSBCTX.USBFS_EP_Buf[2]; - - USBFS->UEP0_CTRL_H = USBFS_UEP_R_RES_ACK | USBFS_UEP_T_RES_NAK; - USBFS->UEP1_CTRL_H = USBFS_UEP_T_RES_NAK; - USBFS->UEP2_CTRL_H = USBFS_UEP_T_RES_NAK; - - /* Clear End-points Busy Status */ + UEP_CTRL_H(0) = USBFS_UEP_R_RES_ACK | USBFS_UEP_T_RES_NAK; + int i; + for( i = 1; i < FUSB_CONFIG_EPS; i++ ) + UEP_CTRL_H(i) = USBFS_UEP_T_RES_NAK; + for(uint8_t i=0; i< sizeof(FSUSBCTX.USBFS_Endp_Busy)/sizeof(FSUSBCTX.USBFS_Endp_Busy[0]); i++ ) { FSUSBCTX.USBFS_Endp_Busy[ i ] = 0; @@ -521,7 +509,7 @@ void USBFS_Device_Endp_Init() int FSUSBSetup() { RCC->APB2PCENR |= RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOC; - RCC->AHBPCENR |= RCC_USBFS; + RCC->AHBPCENR |= RCC_USBFS | RCC_AHBPeriph_DMA1; NVIC_EnableIRQ( USBFS_IRQn ); @@ -530,7 +518,7 @@ int FSUSBSetup() USBFS->BASE_CTRL = RB_UC_RESET_SIE | RB_UC_CLR_ALL; USBFS->BASE_CTRL = 0x00; - USBFS_Device_Endp_Init(); + USBFS_InternalFinishSetup(); // Enter device mode. USBFS->INT_EN = RB_UIE_SUSPEND | RB_UIE_TRANSFER | RB_UIE_BUS_RST; @@ -539,6 +527,14 @@ int FSUSBSetup() USBFS->INT_FG = 0xff; USBFS->UDEV_CTRL = RB_UD_PD_DIS | RB_UD_PORT_EN; + char abuff[64]; + memset( abuff, 0xaa, 64 ); + char bbuff[64] = { 0 }; + //fastcopy( bbuff, abuff, 35 ); + USBDEBUG1 = bbuff[30]; + +//USBDEBUG0, USBDEBUG1, USBDEBUG2 + // Go on-bus. // From the TRM: @@ -558,7 +554,7 @@ int FSUSBSetup() // corresponding to CNF=01 selects the floating input. #if FUSB_5V_OPERATION - // XXX This is dubious, copied from x035 - checkme. + // XXX This is dubious, copied from x035 - checkme (UDP_PUE_10K) AFIO->CTLR = (AFIO->CTLR & ~(UDP_PUE_MASK | UDM_PUE_MASK | USB_PHY_V33)) | UDP_PUE_10K | USB_IOEN; #else AFIO->CTLR = (AFIO->CTLR & ~(UDP_PUE_MASK | UDM_PUE_MASK )) | USB_PHY_V33 | UDP_PUE_1K5 | USB_IOEN; @@ -578,126 +574,3 @@ int FSUSBSetup() - - -uint8_t USBFS_Endp_DataUp(uint8_t endp, uint8_t *pbuf, uint16_t len, uint8_t mod) -{ - uint8_t endp_mode; - uint8_t buf_load_offset; - - /* DMA config, endp_ctrl config, endp_len config */ - if( ( endp >= DEF_UEP1 ) && ( endp <= DEF_UEP7 ) ) - { - if( FSUSBCTX.USBFS_Endp_Busy[ endp ] == 0 ) - { - if( (endp == DEF_UEP1) || (endp == DEF_UEP4) ) - { - /* endp1/endp4 */ - endp_mode = USBFSD_UEP_MOD( 0 ); - if( endp == DEF_UEP1 ) - { - endp_mode = (uint8_t)( endp_mode >> 4 ); - } - } - else if( ( endp == DEF_UEP2 ) || ( endp == DEF_UEP3 ) ) - { - /* endp2/endp3 */ - endp_mode = USBFSD_UEP_MOD( 1 ); - if( endp == DEF_UEP3 ) - { - endp_mode = (uint8_t)( endp_mode >> 4 ); - } - } - else if( ( endp == DEF_UEP5 ) || ( endp == DEF_UEP6 ) ) - { - /* endp5/endp6 */ - endp_mode = USBFSD_UEP_MOD( 2 ); - if( endp == DEF_UEP6 ) - { - endp_mode = (uint8_t)( endp_mode >> 4 ); - } - } - else - { - /* endp7 */ - endp_mode = USBFSD_UEP_MOD( 3 ); - } - - if( endp_mode & USBFSD_UEP_TX_EN ) - { - if( endp_mode & USBFSD_UEP_RX_EN ) - { - if( endp_mode & USBFSD_UEP_BUF_MOD ) - { - if( USBFSD_UEP_TX_CTRL(endp) & USBFS_UEP_T_TOG ) - { - buf_load_offset = 192; - } - else - { - buf_load_offset = 128; - } - } - else - { - buf_load_offset = 64; - } - } - else - { - if( endp_mode & USBFSD_UEP_BUF_MOD ) - { - /* double tx buffer */ - if( USBFSD_UEP_TX_CTRL( endp ) & USBFS_UEP_T_TOG ) - { - buf_load_offset = 64; - } - else - { - buf_load_offset = 0; - } - } - else - { - buf_load_offset = 0; - } - } - if( buf_load_offset == 0 ) - { - if( mod == DEF_UEP_DMA_LOAD ) - { - /* DMA mode */ - USBFSD_UEP_DMA( endp ) = (uint16_t)(uint32_t)pbuf; - } - else - { - /* copy mode */ - memcpy( USBFSD_UEP_BUF( endp ), pbuf, len ); - } - } - else - { - memcpy( USBFSD_UEP_BUF( endp ) + buf_load_offset, pbuf, len ); - } - - /* tx length */ - USBFSD_UEP_TLEN( endp ) = len; - /* response ack */ - USBFSD_UEP_TX_CTRL( endp ) = ( USBFSD_UEP_TX_CTRL( endp ) & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_ACK; - /* Set end-point busy */ - FSUSBCTX.USBFS_Endp_Busy[ endp ] = 0x01; - } - } - else - { - return 1; - } - } - else - { - return 1; - } - return 0; -} - - diff --git a/examples_x035/usbdevice.incomplete/fsusb.h b/examples_x035/usbdevice.incomplete/fsusb.h index 3aca2ced..14048059 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.h +++ b/examples_x035/usbdevice.incomplete/fsusb.h @@ -1,6 +1,23 @@ #ifndef _FSUSB_H #define _FSUSB_H +/* Full speed USB infrastructure for CH32X035. + Based off of the official USB stack, but, with significant perf and space + reductions. + + Limitations: + * Limited to EPs 0..4. + * By default, functions are using dedicated buffers, not DMA (but there is no reason DMA could not be used instead) + * + + + General Notes: + * They seem to be using DMA->RX but TX via non-DMA (the opposite of what they should have done) + + */ + + + #include #include "ch32v003fun.h" #include "usb_defines.h" @@ -9,7 +26,10 @@ extern uint32_t USBDEBUG0, USBDEBUG1, USBDEBUG2; int FSUSBSetup(); -uint8_t USBFS_Endp_DataUp(uint8_t endp, uint8_t *pbuf, uint16_t len, uint8_t mod); +uint8_t USBFS_Endp_DataUp(uint8_t endp, const uint8_t *pbuf, uint16_t len, uint8_t mod); + +static inline uint8_t * USBFS_GetEPBufferIfAvailable( int endp ); +static inline void USBFS_SendEndpoint( int endp, int len ); struct _USBState @@ -26,45 +46,42 @@ struct _USBState volatile uint8_t USBFS_DevSleepStatus; volatile uint8_t USBFS_DevEnumStatus; - /* Endpoint Buffer */ - __attribute__ ((aligned(4))) uint8_t USBFS_EP_Buf[FUSB_CONFIG_EPS][64]; +// Endpoint buffers, only useful if using DMA. +// __attribute__ ((aligned(4))) uint8_t USBFS_EP_Buf[FUSB_CONFIG_EPS][64]; +// __attribute__ ((aligned(4))) uint8_t USBFS_EP_Buf[3][64]; +// #define pUSBFS_SetupReqPak ((tusb_control_request_t*)ctx->USBFS_EP_Buf[0]) +// #define CTRL0BUFF (FSUSBCTX.USBFS_EP_Buf[0]) - #define pUSBFS_SetupReqPak ((tusb_control_request_t*)ctx->USBFS_EP_Buf[0]) + uint8_t EP0DMABuffer[64]; + #define pUSBFS_SetupReqPak ((tusb_control_request_t*)USBFSD_UEP_BUF(0)) + #define CTRL0BUFF USBFSD_UEP_BUF(0) +#if FUSB_HID_INTERFACES > 0 uint8_t USBFS_HidIdle[FUSB_HID_INTERFACES]; uint8_t USBFS_HidProtocol[FUSB_HID_INTERFACES]; +#endif const uint8_t *pUSBFS_Descr; - - /* USB IN Endpoint Busy Flag */ volatile uint8_t USBFS_Endp_Busy[FUSB_CONFIG_EPS]; }; extern struct _USBState FSUSBCTX; +// To TX, you can use USBFS_GetEPBufferIfAvailable or USBFSD_UEP_DMA( endp ) -#if 0 -extern const uint8_t *pUSBFS_Descr; - -/* USB Device Status */ -extern volatile uint8_t USBFS_DevConfig; -extern volatile uint8_t USBFS_DevAddr; -extern volatile uint8_t USBFS_DevSleepStatus; -extern volatile uint8_t USBFS_DevEnumStatus; - -/* Endpoint Buffer */ -extern __attribute__ ((aligned(4))) uint8_t USBFS_EP0_Buf[]; -extern __attribute__ ((aligned(4))) uint8_t USBFS_EP2_Buf[]; - - -/* USB IN Endpoint Busy Flag */ -extern volatile uint8_t USBFS_Endp_Busy[ ]; - - -// ABOVE: TOOD: REWRITE! -#endif +static inline uint8_t * USBFS_GetEPBufferIfAvailable( int endp ) +{ + if( FSUSBCTX.USBFS_Endp_Busy[ endp ] ) return 0; + return USBFSD_UEP_BUF( endp ); +} +static inline void USBFS_SendEndpoint( int endp, int len ) +{ + USBFSD_UEP_TLEN( endp ) = len; + USBFSD_UEP_TX_CTRL( endp ) = ( USBFSD_UEP_TX_CTRL( endp ) & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_ACK; + FSUSBCTX.USBFS_Endp_Busy[ endp ] = 0x01; +} #endif diff --git a/examples_x035/usbdevice.incomplete/usbdevice.c b/examples_x035/usbdevice.incomplete/usbdevice.c index 2f3c3c1f..6ac12256 100644 --- a/examples_x035/usbdevice.incomplete/usbdevice.c +++ b/examples_x035/usbdevice.incomplete/usbdevice.c @@ -24,59 +24,20 @@ int main() FSUSBSetup(); - -void USBFS_IRQHandler(); -//extern int USBFS_IRQHandler; while(1) { - printf( "%lu %08x %lu %d %d\n", USBDEBUG0, USBDEBUG1, USBDEBUG2, 0, 0 ); + printf( "%lu %08lx %lu %d %d\n", USBDEBUG0, USBDEBUG1, USBDEBUG2, 0, 0 ); int i; - //printf( "!! %d %d %d\n", NUM_EP, USBFS_Endp_Busy[0], USBFS_Endp_Busy[1] ); for( i = 1; i < 3; i++ ) { - if( !FSUSBCTX.USBFS_Endp_Busy[i] ) - { - -/* -USBDEBUG0+= 100; - /* tx length */ - //memset( USBFSD_UEP_BUF( i ), 0xaa, 16 ); -// USBFSD_UEP_TLEN( i ) = 16; - // USBFSD_UEP_TX_CTRL( i ) = ( USBFSD_UEP_TX_CTRL( i ) & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_ACK; - // USBFS_Endp_Busy[i] = 1; - char pbuf[16] = { 0xaa, 1, 1 }; -/* static iter; - if( i == 2 ) - { - iter++; - switch( (iter>>3) & 3 ) - { - case 0: pbuf[1] = 1; break; - case 1: pbuf[2] = 1; break; - case 2: pbuf[1] = -1; break; - case 3: pbuf[2] = -1; break; - } - }*/ - uint8_t r = USBFS_Endp_DataUp( i, pbuf, (i==1)?8:4, DEF_UEP_CPY_LOAD); -//USBDEBUG1+=r; + uint32_t * buffer = (uint32_t*)USBFS_GetEPBufferIfAvailable( i ); + if( buffer ) + { + buffer[0] = 0x000101aa; + USBFS_SendEndpoint( i, (i==1)?8:4 ); } } } - -#if 0 - while(1) - { - GPIOA->BSHR = 1; // Turn on GPIOs - printf( "+%lu %lu\n", count++ ); - Delay_Ms(100); - int i; - for( i = 0; i < 10000; i++ ) - poll_input(); - GPIOA->BSHR = (1<<16); // Turn off GPIODs - printf( "-%lu[%c]\n", count++, last ); - Delay_Ms(100); - } -#endif } From 6466e3c5836fe8d9223ce33771c053aea0a149c7 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Mon, 22 Apr 2024 02:38:48 -0400 Subject: [PATCH 16/31] Things are working, but albeit with a bit of a cursed stint. --- examples_x035/usbdevice.incomplete/fsusb.c | 36 +++++++++------------- examples_x035/usbdevice.incomplete/fsusb.h | 14 ++------- 2 files changed, 17 insertions(+), 33 deletions(-) diff --git a/examples_x035/usbdevice.incomplete/fsusb.c b/examples_x035/usbdevice.incomplete/fsusb.c index 1023b809..3f842f10 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.c +++ b/examples_x035/usbdevice.incomplete/fsusb.c @@ -54,20 +54,20 @@ static inline void fastcopy( uint8_t * dest, const uint8_t * src, int len ) static inline void fastcopy( uint8_t * dest, const uint8_t * src, int len ) { DMA1_Channel7->CFGR = 0; - DMA1_Channel7->MADDR = src; - DMA1_Channel7->PADDR = dest; + DMA1_Channel7->MADDR = (uintptr_t)src; + DMA1_Channel7->PADDR = (uintptr_t)dest; DMA1_Channel7->CNTR = (len+3)/4; DMA1_Channel7->CFGR = DMA_M2M_Enable | DMA_DIR_PeripheralDST | - DMA_Priority_High | + DMA_Priority_Low | DMA_MemoryDataSize_Word | DMA_PeripheralDataSize_Word | DMA_MemoryInc_Enable | DMA_PeripheralInc_Enable | DMA_Mode_Normal | DMA_CFGR1_EN; -//XXX TODO: It seems to work (unsafely) without this guard. - while( DMA1_Channel7->CNTR ); + //XXX TODO: Somehow, it seems to work (unsafely) without this. + //while( DMA1_Channel7->CNTR ); } #endif @@ -78,7 +78,6 @@ void USBFS_InternalFinishSetup(); void USBFS_IRQHandler() { // Based on https://github.com/openwch/ch32x035/blob/main/EVT/EXAM/USB/USBFS/DEVICE/CompositeKM/User/ch32x035_usbfs_device.c - // Combined FG + ST flag. uint16_t intfgst = *(uint16_t*)(&USBFS->INT_FG); int len = 0; @@ -267,12 +266,10 @@ void USBFS_IRQHandler() } len = ( USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ) ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen; fastcopy( CTRL0BUFF, ctx->pUSBFS_Descr, len ); //memcpy( CTRL0BUFF, ctx->pUSBFS_Descr, len ); - //memcpy( CTRL0BUFF, ctx->pUSBFS_Descr, len ); + USBFS->UEP0_TX_LEN = len; + USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK; ctx->pUSBFS_Descr += len; -// USBFS_SetupReqLen -= len; -// USBFS->UEP0_TX_LEN = len; -// USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK; -// goto replycomplete; + goto replycomplete; break; } @@ -434,8 +431,8 @@ void USBFS_IRQHandler() } break; - // This might look a little weird, for error handling but it saves a nontrivial amount of storage, and simplifies - // control flow to hard-abort here. + // This might look a little weird, for error handling but it saves a nontrivial amount of storage, and simplifies + // control flow to hard-abort here. sendstall: // if one request not support, return stall. Stall means permanent error. USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_STALL|USBFS_UEP_R_TOG | USBFS_UEP_R_RES_STALL; @@ -493,7 +490,10 @@ void USBFS_InternalFinishSetup() USBFS->UEP4_1_MOD = RB_UEP1_TX_EN; USBFS->UEP2_3_MOD = RB_UEP2_TX_EN; USBFS->UEP567_MOD = 0; - USBFS->UEP0_DMA = FSUSBCTX.EP0DMABuffer; + + // This is really cursed. Somehow it doesn't explode. + // But, normally the USB wants a separate buffer here. + USBFS->UEP0_DMA = (uintptr_t)CTRL0BUFF; UEP_CTRL_H(0) = USBFS_UEP_R_RES_ACK | USBFS_UEP_T_RES_NAK; int i; @@ -527,14 +527,6 @@ int FSUSBSetup() USBFS->INT_FG = 0xff; USBFS->UDEV_CTRL = RB_UD_PD_DIS | RB_UD_PORT_EN; - char abuff[64]; - memset( abuff, 0xaa, 64 ); - char bbuff[64] = { 0 }; - //fastcopy( bbuff, abuff, 35 ); - USBDEBUG1 = bbuff[30]; - -//USBDEBUG0, USBDEBUG1, USBDEBUG2 - // Go on-bus. // From the TRM: diff --git a/examples_x035/usbdevice.incomplete/fsusb.h b/examples_x035/usbdevice.incomplete/fsusb.h index 14048059..beae51dc 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.h +++ b/examples_x035/usbdevice.incomplete/fsusb.h @@ -34,26 +34,18 @@ static inline void USBFS_SendEndpoint( int endp, int len ); struct _USBState { - /* Setup Request */ + // Setup Request volatile uint8_t USBFS_SetupReqCode; volatile uint8_t USBFS_SetupReqType; volatile uint16_t USBFS_SetupReqLen; volatile uint32_t USBFS_IndexValue; - /* USB Device Status */ + // USB Device Status volatile uint8_t USBFS_DevConfig; volatile uint8_t USBFS_DevAddr; volatile uint8_t USBFS_DevSleepStatus; volatile uint8_t USBFS_DevEnumStatus; -// Endpoint buffers, only useful if using DMA. -// __attribute__ ((aligned(4))) uint8_t USBFS_EP_Buf[FUSB_CONFIG_EPS][64]; -// __attribute__ ((aligned(4))) uint8_t USBFS_EP_Buf[3][64]; -// #define pUSBFS_SetupReqPak ((tusb_control_request_t*)ctx->USBFS_EP_Buf[0]) -// #define CTRL0BUFF (FSUSBCTX.USBFS_EP_Buf[0]) - - uint8_t EP0DMABuffer[64]; - #define pUSBFS_SetupReqPak ((tusb_control_request_t*)USBFSD_UEP_BUF(0)) #define CTRL0BUFF USBFSD_UEP_BUF(0) @@ -62,8 +54,8 @@ struct _USBState uint8_t USBFS_HidProtocol[FUSB_HID_INTERFACES]; #endif - const uint8_t *pUSBFS_Descr; volatile uint8_t USBFS_Endp_Busy[FUSB_CONFIG_EPS]; + const uint8_t *pUSBFS_Descr; }; extern struct _USBState FSUSBCTX; From 371d677f37369eb7feb9c103340ccab0e5879d36 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Mon, 22 Apr 2024 02:40:07 -0400 Subject: [PATCH 17/31] Hide the cursed junk behind other stuff. --- examples_x035/usbdevice.incomplete/fsusb.c | 5 ++++- examples_x035/usbdevice.incomplete/usb_config.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/examples_x035/usbdevice.incomplete/fsusb.c b/examples_x035/usbdevice.incomplete/fsusb.c index 3f842f10..8ebb3c7e 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.c +++ b/examples_x035/usbdevice.incomplete/fsusb.c @@ -67,7 +67,10 @@ static inline void fastcopy( uint8_t * dest, const uint8_t * src, int len ) DMA_PeripheralInc_Enable | DMA_Mode_Normal | DMA_CFGR1_EN; //XXX TODO: Somehow, it seems to work (unsafely) without this. - //while( DMA1_Channel7->CNTR ); +#if !( FUSB_CURSED_TURBO_DMA == 1 ) + while( DMA1_Channel7->CNTR ); +#endif + } #endif diff --git a/examples_x035/usbdevice.incomplete/usb_config.h b/examples_x035/usbdevice.incomplete/usb_config.h index 840c0123..fce35fde 100644 --- a/examples_x035/usbdevice.incomplete/usb_config.h +++ b/examples_x035/usbdevice.incomplete/usb_config.h @@ -8,6 +8,8 @@ #define FUSB_HID_INTERFACES 2 +#define FUSB_CURSED_TURBO_DMA 1 + //Taken from http://www.usbmadesimple.co.uk/ums_ms_desc_dev.htm static const uint8_t device_descriptor[] = { 18, //Length From 64866b912360855f69da4a8ac5fc2ea1e3db6421 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Mon, 22 Apr 2024 06:47:39 -0400 Subject: [PATCH 18/31] Bump! Almost working hid reports. --- examples_x035/usbdevice.incomplete/fsusb.c | 47 +- examples_x035/usbdevice.incomplete/fsusb.h | 12 + .../usbdevice.incomplete/testtop/Makefile | 8 + .../usbdevice.incomplete/testtop/os_generic.h | 521 +++++++ .../usbdevice.incomplete/testtop/testtop.c | 91 ++ .../usbdevice.incomplete/testtop/winbuild.bat | 1 + .../usbdevice.incomplete/usb_config.h | 25 +- .../usbdevice.incomplete/usb_defines.h | 1309 +++++++++++++---- .../usbdevice.incomplete/usbdevice.c | 51 +- 9 files changed, 1765 insertions(+), 300 deletions(-) create mode 100644 examples_x035/usbdevice.incomplete/testtop/Makefile create mode 100644 examples_x035/usbdevice.incomplete/testtop/os_generic.h create mode 100644 examples_x035/usbdevice.incomplete/testtop/testtop.c create mode 100644 examples_x035/usbdevice.incomplete/testtop/winbuild.bat diff --git a/examples_x035/usbdevice.incomplete/fsusb.c b/examples_x035/usbdevice.incomplete/fsusb.c index 8ebb3c7e..4c43708b 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.c +++ b/examples_x035/usbdevice.incomplete/fsusb.c @@ -115,7 +115,7 @@ void USBFS_IRQHandler() if ( ( ctx->USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) { - /* Non-standard request endpoint 0 Data upload, noted by official docs, but I don't think this would ever really be used. */ + // Handle other control requests here. } else { @@ -136,6 +136,17 @@ void USBFS_IRQHandler() break; default: +#if FUSB_HID_USER_REPORTS + len = ctx->USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : ctx->USBFS_SetupReqLen; + if( len ) + { + HandleHidUserReportDataIn( ctx, CTRL0BUFF, len ); + USBFS->UEP0_TX_LEN = len; + USBFS->UEP0_CTRL_H ^= USBFS_UEP_T_TOG; + ctx->USBFS_SetupReqLen -= len; + ctx->pUSBFS_Descr += len; + } +#endif break; } } @@ -150,32 +161,22 @@ void USBFS_IRQHandler() case DEF_UEP0: if( intfgst & CRB_UIS_TOG_OK ) { - if( ( FSUSBCTX.USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) + +#if FUSB_HID_USER_REPORTS + int r = HandleHidUserReportDataOut( ctx, CTRL0BUFF, USBFS->RX_LEN ); + if( r >= 0 ) { - if( ( FSUSBCTX.USBFS_SetupReqType & USB_REQ_TYP_MASK ) == USB_REQ_TYP_CLASS ) - { - switch( FSUSBCTX.USBFS_SetupReqCode ) - { - case HID_SET_REPORT: - //KB_LED_Cur_Status = USBFS_EP0_Buf[ 0 ]; - FSUSBCTX.USBFS_SetupReqLen = 0; - break; - default: - break; - } - } + USBFS->UEP0_TX_LEN = r; + USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK; } else +#endif + if( FSUSBCTX.USBFS_SetupReqLen == 0 ) { - /* Standard request end-point 0 Data download */ - /* Add your code here */ + USBFS->UEP0_TX_LEN = 0; + USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK; } } - if( FSUSBCTX.USBFS_SetupReqLen == 0 ) - { - USBFS->UEP0_TX_LEN = 0; - USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK; - } break; default: @@ -197,6 +198,10 @@ void USBFS_IRQHandler() if( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) { +#if FUSB_HID_USER_REPORTS + len = HandleHidUserReportSetup( ctx, pUSBFS_SetupReqPak ); + if( len < 0 ) goto sendstall; +#endif #if FUSB_HID_INTERFACES > 0 if( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) == USB_REQ_TYP_CLASS ) { diff --git a/examples_x035/usbdevice.incomplete/fsusb.h b/examples_x035/usbdevice.incomplete/fsusb.h index beae51dc..3eb4f21f 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.h +++ b/examples_x035/usbdevice.incomplete/fsusb.h @@ -25,6 +25,8 @@ extern uint32_t USBDEBUG0, USBDEBUG1, USBDEBUG2; +struct _USBState; + int FSUSBSetup(); uint8_t USBFS_Endp_DataUp(uint8_t endp, const uint8_t *pbuf, uint16_t len, uint8_t mod); @@ -32,6 +34,16 @@ static inline uint8_t * USBFS_GetEPBufferIfAvailable( int endp ); static inline void USBFS_SendEndpoint( int endp, int len ); +// Implement the following: +#if FUSB_HID_NONSTANDARD +int HandleHidUserReportSetup( struct _USBState * ctx, tusb_control_request_t * req ); +int HandleHidUserReportOut( struct _USBState * ctx, uint8_t * data, int len ); +void HandleHidUserReportIn( struct _USBState * ctx, uint8_t * data, int len ); +#endif + + + + struct _USBState { // Setup Request diff --git a/examples_x035/usbdevice.incomplete/testtop/Makefile b/examples_x035/usbdevice.incomplete/testtop/Makefile new file mode 100644 index 00000000..7094e41d --- /dev/null +++ b/examples_x035/usbdevice.incomplete/testtop/Makefile @@ -0,0 +1,8 @@ +all : testtop + +testtop : testtop.c + gcc -o $@ $^ -I../../../minichlink -ludev + +clean : + rm -rf *.o *~ testtop + diff --git a/examples_x035/usbdevice.incomplete/testtop/os_generic.h b/examples_x035/usbdevice.incomplete/testtop/os_generic.h new file mode 100644 index 00000000..6bd7c1e8 --- /dev/null +++ b/examples_x035/usbdevice.incomplete/testtop/os_generic.h @@ -0,0 +1,521 @@ +#ifndef _OS_GENERIC_H +#define _OS_GENERIC_H +/* + "osgeneric" Generic, platform independent tool for threads and time. + Geared around Windows and Linux. Designed for operation on MSVC, + TCC, GCC and clang. Others may work. + + It offers the following operations: + + Delay functions: + void OGSleep( int is ); + void OGUSleep( int ius ); + + Getting current time (may be time from program start, boot, or epoc) + double OGGetAbsoluteTime(); + double OGGetFileTime( const char * file ); + + Thread functions + og_thread_t OGCreateThread( void * (routine)( void * ), void * parameter ); + void * OGJoinThread( og_thread_t ot ); + void OGCancelThread( og_thread_t ot ); + + Mutex functions, used for protecting data structures. + (recursive on platforms where available.) + og_mutex_t OGCreateMutex(); + void OGLockMutex( og_mutex_t om ); + void OGUnlockMutex( og_mutex_t om ); + void OGDeleteMutex( og_mutex_t om ); + + Always a semaphore (not recursive) + og_sema_t OGCreateSema(); //Create a semaphore, comes locked initially. + NOTE: For platform compatibility, max count is 32767 + void OGLockSema( og_sema_t os ); + int OGGetSema( og_sema_t os ); //if <0 there was a failure. + void OGUnlockSema( og_sema_t os ); + void OGDeleteSema( og_sema_t os ); + + TLS (Thread-Local Storage) + og_tls_t OGCreateTLS(); + void OGDeleteTLS( og_tls_t tls ); + void OGSetTLS( og_tls_t tls, void * data ); + void * OGGetTLS( og_tls_t tls ); + + You can permute the operations of this file by the following means: + OSG_NO_IMPLEMENTATION + OSG_PREFIX + OSG_NOSTATIC + + The default behavior is to do static inline. + + Copyright (c) 2011-2012,2013,2016,2018,2019,2020 <>< Charles Lohr + + This file may be licensed under the MIT/x11 license, NewBSD or CC0 licenses + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of this file. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. + + Date Stamp: 2019-09-05 CNL: Allow for noninstantiation and added TLS. + Date Stamp: 2018-03-25 CNL: Switched to header-only format. +*/ + + +#if defined( OSG_NOSTATIC ) && OSG_NOSTATIC != 0 +#ifndef OSG_PREFIX +#define OSG_PREFIX +#endif +#ifndef OSG_NO_IMPLEMENTATION +#define OSG_NO_IMPLEMENTATION +#endif +#endif + +#ifndef OSG_PREFIX +#ifdef __wasm__ +#define OSG_PREFIX +#else +#define OSG_PREFIX static inline +#endif +#endif + +//In case you want to hook the closure of a thread, i.e. if your system has thread-local storage. +#ifndef OSG_TERM_THREAD_CODE +#define OSG_TERM_THREAD_CODE +#endif + +typedef void* og_thread_t; +typedef void* og_mutex_t; +typedef void* og_sema_t; +typedef void* og_tls_t; + +#ifdef __cplusplus +extern "C" { +#endif + +OSG_PREFIX void OGSleep( int is ); +OSG_PREFIX void OGUSleep( int ius ); +OSG_PREFIX double OGGetAbsoluteTime(); +OSG_PREFIX double OGGetFileTime( const char * file ); +OSG_PREFIX og_thread_t OGCreateThread( void * (routine)( void * ), void * parameter ); +OSG_PREFIX void * OGJoinThread( og_thread_t ot ); +OSG_PREFIX void OGCancelThread( og_thread_t ot ); +OSG_PREFIX og_mutex_t OGCreateMutex(); +OSG_PREFIX void OGLockMutex( og_mutex_t om ); +OSG_PREFIX void OGUnlockMutex( og_mutex_t om ); +OSG_PREFIX void OGDeleteMutex( og_mutex_t om ); +OSG_PREFIX og_sema_t OGCreateSema(); +OSG_PREFIX int OGGetSema( og_sema_t os ); +OSG_PREFIX void OGLockSema( og_sema_t os ); +OSG_PREFIX void OGUnlockSema( og_sema_t os ); +OSG_PREFIX void OGDeleteSema( og_sema_t os ); +OSG_PREFIX og_tls_t OGCreateTLS(); +OSG_PREFIX void OGDeleteTLS( og_tls_t key ); +OSG_PREFIX void * OGGetTLS( og_tls_t key ); +OSG_PREFIX void OGSetTLS( og_tls_t key, void * data ); + +#ifdef __cplusplus +}; +#endif + +#ifndef OSG_NO_IMPLEMENTATION + +#if defined( WIN32 ) || defined (WINDOWS) || defined( _WIN32) +#define USE_WINDOWS +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef USE_WINDOWS + +#include +#include + +OSG_PREFIX void OGSleep( int is ) +{ + Sleep( is*1000 ); +} + +OSG_PREFIX void OGUSleep( int ius ) +{ + Sleep( ius/1000 ); +} + +OSG_PREFIX double OGGetAbsoluteTime() +{ + static LARGE_INTEGER lpf; + LARGE_INTEGER li; + + if( !lpf.QuadPart ) + { + QueryPerformanceFrequency( &lpf ); + } + + QueryPerformanceCounter( &li ); + return (double)li.QuadPart / (double)lpf.QuadPart; +} + + +OSG_PREFIX double OGGetFileTime( const char * file ) +{ + FILETIME ft; + + HANDLE h = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + + if( h==INVALID_HANDLE_VALUE ) + return -1; + + GetFileTime( h, 0, 0, &ft ); + + CloseHandle( h ); + + return ft.dwHighDateTime + ft.dwLowDateTime; +} + + +OSG_PREFIX og_thread_t OGCreateThread( void * (routine)( void * ), void * parameter ) +{ + return (og_thread_t)CreateThread( 0, 0, (LPTHREAD_START_ROUTINE)routine, parameter, 0, 0 ); +} + +OSG_PREFIX void * OGJoinThread( og_thread_t ot ) +{ + WaitForSingleObject( ot, INFINITE ); + OSG_TERM_THREAD_CODE + CloseHandle( ot ); + return 0; +} + +OSG_PREFIX void OGCancelThread( og_thread_t ot ) +{ + OSG_TERM_THREAD_CODE + TerminateThread( ot, 0); + CloseHandle( ot ); +} + +OSG_PREFIX og_mutex_t OGCreateMutex() +{ + return CreateMutex( 0, 0, 0 ); +} + +OSG_PREFIX void OGLockMutex( og_mutex_t om ) +{ + WaitForSingleObject(om, INFINITE); +} + +OSG_PREFIX void OGUnlockMutex( og_mutex_t om ) +{ + ReleaseMutex(om); +} + +OSG_PREFIX void OGDeleteMutex( og_mutex_t om ) +{ + CloseHandle( om ); +} + + + +OSG_PREFIX og_sema_t OGCreateSema() +{ + HANDLE sem = CreateSemaphore( 0, 0, 32767, 0 ); + return (og_sema_t)sem; +} + +OSG_PREFIX int OGGetSema( og_sema_t os ) +{ + typedef LONG NTSTATUS; + HANDLE sem = (HANDLE)os; + typedef NTSTATUS (NTAPI *_NtQuerySemaphore)( + HANDLE SemaphoreHandle, + DWORD SemaphoreInformationClass, /* Would be SEMAPHORE_INFORMATION_CLASS */ + PVOID SemaphoreInformation, /* but this is to much to dump here */ + ULONG SemaphoreInformationLength, + PULONG ReturnLength OPTIONAL + ); + + typedef struct _SEMAPHORE_BASIC_INFORMATION { + ULONG CurrentCount; + ULONG MaximumCount; + } SEMAPHORE_BASIC_INFORMATION; + + + static _NtQuerySemaphore NtQuerySemaphore; + SEMAPHORE_BASIC_INFORMATION BasicInfo; + NTSTATUS Status; + + if( !NtQuerySemaphore ) + { + NtQuerySemaphore = (_NtQuerySemaphore)GetProcAddress (GetModuleHandle ("ntdll.dll"), "NtQuerySemaphore"); + if( !NtQuerySemaphore ) + { + return -1; + } + } + + + Status = NtQuerySemaphore (sem, 0 /*SemaphoreBasicInformation*/, + &BasicInfo, sizeof (SEMAPHORE_BASIC_INFORMATION), NULL); + + if (Status == ERROR_SUCCESS) + { + return BasicInfo.CurrentCount; + } + + return -2; +} + +OSG_PREFIX void OGLockSema( og_sema_t os ) +{ + WaitForSingleObject( (HANDLE)os, INFINITE ); +} + +OSG_PREFIX void OGUnlockSema( og_sema_t os ) +{ + ReleaseSemaphore( (HANDLE)os, 1, 0 ); +} + +OSG_PREFIX void OGDeleteSema( og_sema_t os ) +{ + CloseHandle( os ); +} + +OSG_PREFIX og_tls_t OGCreateTLS() +{ + return (og_tls_t)(intptr_t)TlsAlloc(); +} + +OSG_PREFIX void OGDeleteTLS( og_tls_t key ) +{ + TlsFree( (DWORD)(intptr_t)key ); +} + +OSG_PREFIX void * OGGetTLS( og_tls_t key ) +{ + return TlsGetValue( (DWORD)(intptr_t)key ); +} + +OSG_PREFIX void OGSetTLS( og_tls_t key, void * data ) +{ + TlsSetValue( (DWORD)(intptr_t)key, data ); +} + +#elif defined( __wasm__ ) + +//We don't actually have any function defintions here. +//The outside system will handle it. + +#else + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include + +OSG_PREFIX void OGSleep( int is ) +{ + sleep( is ); +} + +OSG_PREFIX void OGUSleep( int ius ) +{ + usleep( ius ); +} + +OSG_PREFIX double OGGetAbsoluteTime() +{ + struct timeval tv; + gettimeofday( &tv, 0 ); + return ((double)tv.tv_usec)/1000000. + (tv.tv_sec); +} + +OSG_PREFIX double OGGetFileTime( const char * file ) +{ + struct stat buff; + + int r = stat( file, &buff ); + + if( r < 0 ) + { + return -1; + } + + return buff.st_mtime; +} + + + +OSG_PREFIX og_thread_t OGCreateThread( void * (routine)( void * ), void * parameter ) +{ + pthread_t * ret = (pthread_t *)malloc( sizeof( pthread_t ) ); + if( !ret ) return 0; + int r = pthread_create( ret, 0, routine, parameter ); + if( r ) + { + free( ret ); + return 0; + } + return (og_thread_t)ret; +} + +OSG_PREFIX void * OGJoinThread( og_thread_t ot ) +{ + void * retval; + if( !ot ) + { + return 0; + } + pthread_join( *(pthread_t*)ot, &retval ); + OSG_TERM_THREAD_CODE + free( ot ); + return retval; +} + +OSG_PREFIX void OGCancelThread( og_thread_t ot ) +{ + if( !ot ) + { + return; + } +#ifdef ANDROID + pthread_kill( *(pthread_t*)ot, SIGTERM ); +#else + pthread_cancel( *(pthread_t*)ot ); +#endif + OSG_TERM_THREAD_CODE + free( ot ); +} + +OSG_PREFIX og_mutex_t OGCreateMutex() +{ + pthread_mutexattr_t mta; + og_mutex_t r = malloc( sizeof( pthread_mutex_t ) ); + if( !r ) return 0; + + pthread_mutexattr_init(&mta); + pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE); + + pthread_mutex_init( (pthread_mutex_t *)r, &mta ); + + return r; +} + +OSG_PREFIX void OGLockMutex( og_mutex_t om ) +{ + if( !om ) + { + return; + } + pthread_mutex_lock( (pthread_mutex_t*)om ); +} + +OSG_PREFIX void OGUnlockMutex( og_mutex_t om ) +{ + if( !om ) + { + return; + } + pthread_mutex_unlock( (pthread_mutex_t*)om ); +} + +OSG_PREFIX void OGDeleteMutex( og_mutex_t om ) +{ + if( !om ) + { + return; + } + + pthread_mutex_destroy( (pthread_mutex_t*)om ); + free( om ); +} + + + + +OSG_PREFIX og_sema_t OGCreateSema() +{ + sem_t * sem = (sem_t *)malloc( sizeof( sem_t ) ); + if( !sem ) return 0; + sem_init( sem, 0, 0 ); + return (og_sema_t)sem; +} + +OSG_PREFIX int OGGetSema( og_sema_t os ) +{ + int valp; + sem_getvalue( (sem_t*)os, &valp ); + return valp; +} + + +OSG_PREFIX void OGLockSema( og_sema_t os ) +{ + sem_wait( (sem_t*)os ); +} + +OSG_PREFIX void OGUnlockSema( og_sema_t os ) +{ + sem_post( (sem_t*)os ); +} + +OSG_PREFIX void OGDeleteSema( og_sema_t os ) +{ + sem_destroy( (sem_t*)os ); + free(os); +} + +OSG_PREFIX og_tls_t OGCreateTLS() +{ + pthread_key_t ret = 0; + pthread_key_create(&ret, 0); + return (og_tls_t)(intptr_t)ret; +} + +OSG_PREFIX void OGDeleteTLS( og_tls_t key ) +{ + pthread_key_delete( (pthread_key_t)(intptr_t)key ); +} + +OSG_PREFIX void * OGGetTLS( og_tls_t key ) +{ + return pthread_getspecific( (pthread_key_t)(intptr_t)key ); +} + +OSG_PREFIX void OGSetTLS( og_tls_t key, void * data ) +{ + pthread_setspecific( (pthread_key_t)(intptr_t)key, data ); +} + +#endif + +#ifdef __cplusplus +}; +#endif + +#endif //OSG_NO_IMPLEMENTATION + +#endif //_OS_GENERIC_H + + diff --git a/examples_x035/usbdevice.incomplete/testtop/testtop.c b/examples_x035/usbdevice.incomplete/testtop/testtop.c new file mode 100644 index 00000000..87f8ef8b --- /dev/null +++ b/examples_x035/usbdevice.incomplete/testtop/testtop.c @@ -0,0 +1,91 @@ +#include +#include +#include + +// We borrow the combined hidapi.c from minichlink. +// +// This is for total perf testing. + +#include "hidapi.c" + +#include "os_generic.h" + +int main() +{ + hid_device * hd = hid_open( 0xaaaa, 0xd004, L"CUSTOMDEVICE000"); // third parameter is "serial" + if( !hd ) + { + fprintf( stderr, "Error: Failed to open device.\n" ); + return -4; + } + + // Size of buffers must match the report descriptor size in the special_hid_desc + // NOTE: You are permitted to have multiple entries. + uint8_t buffer0[255] = { 0 }; // NOTE: This must be ONE MORE THAN what is in the hid descriptor. + uint8_t buffer1[255] = { 0 }; + int r; + int i; + int j; + int retries = 0; + double dStart = OGGetAbsoluteTime(); + double dSecond = dStart; + double dStartSend = 0.0; + double dSendTotal = 0; + double dRecvTotal = 0; + for( j = 0; ; j++ ) + { + buffer0[0] = 0xaa; // First byte must match the ID. + + // But we can fill in random for the rest. + for( i = 1; i < sizeof( buffer0 ); i ++ ) + buffer0[i] = 0xbb;//rand(); + + if( buffer0[1] == 0xa4 ) buffer0[1]++; + + retrysend: + + dStartSend = OGGetAbsoluteTime(); + r = hid_send_feature_report( hd, buffer0, sizeof(buffer0) ); + dSendTotal += OGGetAbsoluteTime() - dStartSend; + if( r != sizeof(buffer0) ) + { + fprintf( stderr, "Warning: HID Send fault (%d) Retrying\n", r ); + retries++; + if( retries > 10 ) break; + goto retrysend; + } + + retries = 0; + printf( "<" ); // Print this out meaning we sent the data. + + memset( buffer1, 0xff, sizeof( buffer1 ) ); + buffer1[0] = 0xaa; // First byte must be ID. + + double dStartRecv = OGGetAbsoluteTime(); + r = hid_get_feature_report( hd, buffer1, sizeof(buffer1) ); + dRecvTotal += OGGetAbsoluteTime() - dStartRecv; + + printf( ">" ); fflush( stdout); + + if( r != sizeof( buffer1 ) && r != sizeof( buffer1 ) + 1) { printf( "Got %d\n", r ); break; } + + // Validate the scratches matched. + if( memcmp( buffer0, buffer1, sizeof( buffer0 ) ) != 0 ) + { + printf( "%d: ", r ); + for( i = 0; i < r; i++ ) + printf( "[%d] %02x>%02x %s", i, buffer0[i], buffer1[i], (buffer1[i] != buffer0[i])?"MISMATCH ":"" ); + printf( "\n" ); + break; + } + + if( dStartRecv - dSecond > 1.0 ) + { + printf( "\n%2.3f KB/s PC->003 / %2.3f KB/s 003->PC\n", j * .249 / dSendTotal, j * .249 / dRecvTotal ); + dSecond++; + } + } + + hid_close( hd ); +} + diff --git a/examples_x035/usbdevice.incomplete/testtop/winbuild.bat b/examples_x035/usbdevice.incomplete/testtop/winbuild.bat new file mode 100644 index 00000000..250ad79e --- /dev/null +++ b/examples_x035/usbdevice.incomplete/testtop/winbuild.bat @@ -0,0 +1 @@ +tcc testtop.c -I../../ch32v003fun/minichlink -lsetupapi diff --git a/examples_x035/usbdevice.incomplete/usb_config.h b/examples_x035/usbdevice.incomplete/usb_config.h index fce35fde..310d5255 100644 --- a/examples_x035/usbdevice.incomplete/usb_config.h +++ b/examples_x035/usbdevice.incomplete/usb_config.h @@ -4,11 +4,12 @@ #define FUSB_5V_OPERATION 0 #define FUSB_CONFIG_EPS 3 // Include EP0 in this count #define FUSB_SUPPORTS_SLEEP 0 - #define FUSB_HID_INTERFACES 2 +#define FUSB_CURSED_TURBO_DMA 1 +#define FUSB_HID_NONSTANDARD 1 -#define FUSB_CURSED_TURBO_DMA 1 +#include "usb_defines.h" //Taken from http://www.usbmadesimple.co.uk/ums_ms_desc_dev.htm static const uint8_t device_descriptor[] = { @@ -136,6 +137,22 @@ static const uint8_t KeyRepDesc[ ] = 0x29, 0x91, // Usage Maximum (145) 0x81, 0x00, // Input(Data,Array,Absolute) 0xC0 // End Collection +, + // TODO - Figure out how to work this in. + HID_USAGE_PAGE ( 0xff ), // Vendor-defined page. + HID_USAGE ( 0x00 ), + HID_REPORT_SIZE ( 8 ), + HID_COLLECTION ( HID_COLLECTION_LOGICAL ), + HID_REPORT_COUNT ( 254 ), + HID_REPORT_ID ( 0xaa ) + HID_USAGE ( 0x01 ), + HID_FEATURE ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) , + HID_REPORT_COUNT ( 63 ), // For use with `hidapitester --vidpid 1209/D003 --open --read-feature 171` + HID_REPORT_ID ( 0xab ) + HID_USAGE ( 0x01 ), + HID_FEATURE ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) , + HID_COLLECTION_END, + }; /* Mouse Report Descriptor */ @@ -171,8 +188,8 @@ static const uint8_t MouseRepDesc[ ] = }; -#define STR_MANUFACTURER u"WCH" -#define STR_PRODUCT u"CH32X035 Custom Device" +#define STR_MANUFACTURER u"WCH-TEST" +#define STR_PRODUCT u"ch32v003fun ch32x035 test" #define STR_SERIAL u"CUSTOMDEVICE000" struct usb_string_descriptor_struct { diff --git a/examples_x035/usbdevice.incomplete/usb_defines.h b/examples_x035/usbdevice.incomplete/usb_defines.h index 4fd18b68..3abf670c 100644 --- a/examples_x035/usbdevice.incomplete/usb_defines.h +++ b/examples_x035/usbdevice.incomplete/usb_defines.h @@ -538,296 +538,1057 @@ static inline uint8_t tu_desc_len(void const* desc) } #endif -#endif /* _TUSB_TYPES_H_ */ - -/** @} */ +// from tinyusb_hid.h -#if 0 - -/* USB Setup Request */ -typedef struct __attribute__((packed)) _USB_SETUP_REQ -{ - uint8_t bRequestType; - uint8_t bRequest; - uint16_t wValue; - uint16_t wIndex; - uint16_t wLength; -} USB_SETUP_REQ, *PUSB_SETUP_REQ; - -/* USB Device Descriptor */ -typedef struct __attribute__((packed)) _USB_DEVICE_DESCR -{ - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdUSB; - uint8_t bDeviceClass; - uint8_t bDeviceSubClass; - uint8_t bDeviceProtocol; - uint8_t bMaxPacketSize0; - uint16_t idVendor; - uint16_t idProduct; - uint16_t bcdDevice; - uint8_t iManufacturer; - uint8_t iProduct; - uint8_t iSerialNumber; - uint8_t bNumConfigurations; -} USB_DEV_DESCR, *PUSB_DEV_DESCR; - -/* USB Configuration Descriptor */ -typedef struct __attribute__((packed)) _USB_CONFIG_DESCR -{ - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t wTotalLength; - uint8_t bNumInterfaces; - uint8_t bConfigurationValue; - uint8_t iConfiguration; - uint8_t bmAttributes; - uint8_t MaxPower; -} USB_CFG_DESCR, *PUSB_CFG_DESCR; - -/* USB Interface Descriptor */ -typedef struct __attribute__((packed)) _USB_INTERF_DESCR -{ - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bInterfaceNumber; - uint8_t bAlternateSetting; - uint8_t bNumEndpoints; - uint8_t bInterfaceClass; - uint8_t bInterfaceSubClass; - uint8_t bInterfaceProtocol; - uint8_t iInterface; -} USB_ITF_DESCR, *PUSB_ITF_DESCR; - -/* USB Endpoint Descriptor */ -typedef struct __attribute__((packed)) _USB_ENDPOINT_DESCR -{ - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bEndpointAddress; - uint8_t bmAttributes; - uint8_t wMaxPacketSizeL; - uint8_t wMaxPacketSizeH; - uint8_t bInterval; -} USB_ENDP_DESCR, *PUSB_ENDP_DESCR; - -/* USB Configuration Descriptor Set */ -typedef struct __attribute__((packed)) _USB_CONFIG_DESCR_LONG -{ - USB_CFG_DESCR cfg_descr; - USB_ITF_DESCR itf_descr; - USB_ENDP_DESCR endp_descr[ 1 ]; -} USB_CFG_DESCR_LONG, *PUSB_CFG_DESCR_LONG; - -/* USB HUB Descriptor */ -typedef struct __attribute__((packed)) _USB_HUB_DESCR -{ - uint8_t bDescLength; - uint8_t bDescriptorType; - uint8_t bNbrPorts; - uint8_t wHubCharacteristicsL; - uint8_t wHubCharacteristicsH; - uint8_t bPwrOn2PwrGood; - uint8_t bHubContrCurrent; - uint8_t DeviceRemovable; - uint8_t PortPwrCtrlMask; -} USB_HUB_DESCR, *PUSB_HUB_DESCR; - -/* USB HID Descriptor */ -typedef struct __attribute__((packed)) _USB_HID_DESCR -{ - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdHID; - uint8_t bCountryCode; - uint8_t bNumDescriptors; - uint8_t bDescriptorTypeX; - uint8_t wDescriptorLengthL; - uint8_t wDescriptorLengthH; -} USB_HID_DESCR, *PUSB_HID_DESCR; - - -/*******************************************************************************/ -/* USB Communication Related Macro Definition */ - -/* USB PID */ -#ifndef USB_PID_SETUP -#define USB_PID_NULL 0x00 -#define USB_PID_SOF 0x05 -#define USB_PID_SETUP 0x0D -#define USB_PID_IN 0x09 -#define USB_PID_OUT 0x01 -#define USB_PID_NYET 0x06 -#define USB_PID_ACK 0x02 -#define USB_PID_NAK 0x0A -#define USB_PID_STALL 0x0E -#define USB_PID_DATA0 0x03 -#define USB_PID_DATA1 0x0B -#define USB_PID_PRE 0x0C +#ifdef __cplusplus + extern "C" { #endif -/* USB standard device request code */ -#ifndef USB_GET_DESCRIPTOR -#define USB_GET_STATUS 0x00 -#define USB_CLEAR_FEATURE 0x01 -#define USB_SET_FEATURE 0x03 -#define USB_SET_ADDRESS 0x05 -#define USB_GET_DESCRIPTOR 0x06 -#define USB_SET_DESCRIPTOR 0x07 -#define USB_GET_CONFIGURATION 0x08 -#define USB_SET_CONFIGURATION 0x09 -#define USB_GET_INTERFACE 0x0A -#define USB_SET_INTERFACE 0x0B -#define USB_SYNCH_FRAME 0x0C -#endif +#define TU_U16_HIGH(u16) ((uint8_t) (((u16) >> 8) & 0x00ff)) +#define TU_U16_LOW(u16) ((uint8_t) ((u16) & 0x00ff)) +#define U16_TO_U8S_BE(u16) TU_U16_HIGH(u16), TU_U16_LOW(u16) +#define U16_TO_U8S_LE(u16) TU_U16_LOW(u16), TU_U16_HIGH(u16) -#define DEF_STRING_DESC_LANG 0x00 -#define DEF_STRING_DESC_MANU 0x01 -#define DEF_STRING_DESC_PROD 0x02 -#define DEF_STRING_DESC_SERN 0x03 - -/* USB hub class request code */ -#ifndef HUB_GET_DESCRIPTOR -#define HUB_GET_STATUS 0x00 -#define HUB_CLEAR_FEATURE 0x01 -#define HUB_GET_STATE 0x02 -#define HUB_SET_FEATURE 0x03 -#define HUB_GET_DESCRIPTOR 0x06 -#define HUB_SET_DESCRIPTOR 0x07 +#ifndef TU_ATTR_PACKED +#define TU_ATTR_PACKED __attribute__((packed)) #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 +#ifndef TU_BIT +#define TU_BIT( x ) (1<<(x)) #endif -/* Bit Define for USB Request Type */ -#ifndef USB_REQ_TYP_MASK -#define USB_REQ_TYP_IN 0x80 -#define USB_REQ_TYP_OUT 0x00 -#define USB_REQ_TYP_READ 0x80 -#define USB_REQ_TYP_WRITE 0x00 -#define USB_REQ_TYP_MASK 0x60 -#define USB_REQ_TYP_STANDARD 0x00 -#define USB_REQ_TYP_CLASS 0x20 -#define USB_REQ_TYP_VENDOR 0x40 -#define USB_REQ_TYP_RESERVED 0x60 -#define USB_REQ_RECIP_MASK 0x1F -#define USB_REQ_RECIP_DEVICE 0x00 -#define USB_REQ_RECIP_INTERF 0x01 -#define USB_REQ_RECIP_ENDP 0x02 -#define USB_REQ_RECIP_OTHER 0x03 -#define USB_REQ_FEAT_REMOTE_WAKEUP 0x01 -#define USB_REQ_FEAT_ENDP_HALT 0x00 -#endif +//--------------------------------------------------------------------+ +// Common Definitions +//--------------------------------------------------------------------+ +/** \defgroup ClassDriver_HID_Common Common Definitions + * @{ */ -/* USB Descriptor Type */ -#ifndef USB_DESCR_TYP_DEVICE -#define USB_DESCR_TYP_DEVICE 0x01 -#define USB_DESCR_TYP_CONFIG 0x02 -#define USB_DESCR_TYP_STRING 0x03 -#define USB_DESCR_TYP_INTERF 0x04 -#define USB_DESCR_TYP_ENDP 0x05 -#define USB_DESCR_TYP_QUALIF 0x06 -#define USB_DESCR_TYP_SPEED 0x07 -#define USB_DESCR_TYP_OTG 0x09 -#define USB_DESCR_TYP_BOS 0X0F -#define USB_DESCR_TYP_HID 0x21 -#define USB_DESCR_TYP_REPORT 0x22 -#define USB_DESCR_TYP_PHYSIC 0x23 -#define USB_DESCR_TYP_CS_INTF 0x24 -#define USB_DESCR_TYP_CS_ENDP 0x25 -#define USB_DESCR_TYP_HUB 0x29 -#endif + /// USB HID Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength; /**< Numeric expression that is the total size of the HID descriptor */ + uint8_t bDescriptorType; /**< Constant name specifying type of HID descriptor. */ -/* 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 -#endif + uint16_t bcdHID; /**< Numeric expression identifying the HID Class Specification release */ + uint8_t bCountryCode; /**< Numeric expression identifying country code of the localized hardware. */ + uint8_t bNumDescriptors; /**< Numeric expression specifying the number of class descriptors */ -/* USB Hub Class Request */ -#ifndef HUB_GET_HUB_DESCRIPTOR -#define HUB_CLEAR_HUB_FEATURE 0x20 -#define HUB_CLEAR_PORT_FEATURE 0x23 -#define HUB_GET_BUS_STATE 0xA3 -#define HUB_GET_HUB_DESCRIPTOR 0xA0 -#define HUB_GET_HUB_STATUS 0xA0 -#define HUB_GET_PORT_STATUS 0xA3 -#define HUB_SET_HUB_DESCRIPTOR 0x20 -#define HUB_SET_HUB_FEATURE 0x20 -#define HUB_SET_PORT_FEATURE 0x23 -#endif + uint8_t bReportType; /**< Type of HID class report. */ + uint16_t wReportLength; /**< the total size of the Report descriptor. */ +} tusb_hid_descriptor_hid_t; -/* Hub Class Feature Selectors */ -#ifndef HUB_PORT_RESET -#define HUB_C_HUB_LOCAL_POWER 0 -#define HUB_C_HUB_OVER_CURRENT 1 -#define HUB_PORT_CONNECTION 0 -#define HUB_PORT_ENABLE 1 -#define HUB_PORT_SUSPEND 2 -#define HUB_PORT_OVER_CURRENT 3 -#define HUB_PORT_RESET 4 -#define HUB_PORT_POWER 8 -#define HUB_PORT_LOW_SPEED 9 -#define HUB_C_PORT_CONNECTION 16 -#define HUB_C_PORT_ENABLE 17 -#define HUB_C_PORT_SUSPEND 18 -#define HUB_C_PORT_OVER_CURRENT 19 -#define HUB_C_PORT_RESET 20 -#endif +/// HID Subclass +typedef enum +{ + HID_SUBCLASS_NONE = 0, ///< No Subclass + HID_SUBCLASS_BOOT = 1 ///< Boot Interface Subclass +}hid_subclass_type_t; -/* 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 +/// HID Protocol +typedef enum +{ + HID_PROTOCOL_NONE = 0, ///< None + HID_PROTOCOL_KEYBOARD = 1, ///< Keyboard + HID_PROTOCOL_MOUSE = 2 ///< Mouse +}hid_protocol_type_t; -/* USB UDisk */ -#ifndef USB_BO_CBW_SIZE -#define USB_BO_CBW_SIZE 0x1F -#define USB_BO_CSW_SIZE 0x0D -#endif -#ifndef USB_BO_CBW_SIG0 -#define USB_BO_CBW_SIG0 0x55 -#define USB_BO_CBW_SIG1 0x53 -#define USB_BO_CBW_SIG2 0x42 -#define USB_BO_CBW_SIG3 0x43 -#define USB_BO_CSW_SIG0 0x55 -#define USB_BO_CSW_SIG1 0x53 -#define USB_BO_CSW_SIG2 0x42 -#define USB_BO_CSW_SIG3 0x53 -#endif +/// HID Descriptor Type +typedef enum +{ + HID_DESC_TYPE_HID = 0x21, ///< HID Descriptor + HID_DESC_TYPE_REPORT = 0x22, ///< Report Descriptor + HID_DESC_TYPE_PHYSICAL = 0x23 ///< Physical Descriptor +}hid_descriptor_type_t; -/* USB CDC Class request code */ -#ifndef CDC_GET_LINE_CODING -#define CDC_GET_LINE_CODING 0X21 /* This request allows the host to find out the currently configured line coding */ -#define CDC_SET_LINE_CODING 0x20 /* Configures DTE rate, stop-bits, parity, and number-of-character */ -#define CDC_SET_LINE_CTLSTE 0X22 /* This request generates RS-232/V.24 style control signals */ -#define CDC_SEND_BREAK 0X23 /* Sends special carrier modulation used to specify RS-232 style break */ -#endif -/*******************************************************************************/ +/// HID Request Report Type +typedef enum +{ + HID_REPORT_TYPE_INVALID = 0, + HID_REPORT_TYPE_INPUT, ///< Input + HID_REPORT_TYPE_OUTPUT, ///< Output + HID_REPORT_TYPE_FEATURE ///< Feature +}hid_report_type_t; +/// HID Class Specific Control Request +typedef enum +{ + HID_REQ_CONTROL_GET_REPORT = 0x01, ///< Get Report + HID_REQ_CONTROL_GET_IDLE = 0x02, ///< Get Idle + HID_REQ_CONTROL_GET_PROTOCOL = 0x03, ///< Get Protocol + HID_REQ_CONTROL_SET_REPORT = 0x09, ///< Set Report + HID_REQ_CONTROL_SET_IDLE = 0x0a, ///< Set Idle + HID_REQ_CONTROL_SET_PROTOCOL = 0x0b ///< Set Protocol +}hid_request_type_t; + +/// HID Country Code +typedef enum +{ + HID_LOCAL_NotSupported = 0 , ///< NotSupported + HID_LOCAL_Arabic , ///< Arabic + HID_LOCAL_Belgian , ///< Belgian + HID_LOCAL_Canadian_Bilingual , ///< Canadian_Bilingual + HID_LOCAL_Canadian_French , ///< Canadian_French + HID_LOCAL_Czech_Republic , ///< Czech_Republic + HID_LOCAL_Danish , ///< Danish + HID_LOCAL_Finnish , ///< Finnish + HID_LOCAL_French , ///< French + HID_LOCAL_German , ///< German + HID_LOCAL_Greek , ///< Greek + HID_LOCAL_Hebrew , ///< Hebrew + HID_LOCAL_Hungary , ///< Hungary + HID_LOCAL_International , ///< International + HID_LOCAL_Italian , ///< Italian + HID_LOCAL_Japan_Katakana , ///< Japan_Katakana + HID_LOCAL_Korean , ///< Korean + HID_LOCAL_Latin_American , ///< Latin_American + HID_LOCAL_Netherlands_Dutch , ///< Netherlands/Dutch + HID_LOCAL_Norwegian , ///< Norwegian + HID_LOCAL_Persian_Farsi , ///< Persian (Farsi) + HID_LOCAL_Poland , ///< Poland + HID_LOCAL_Portuguese , ///< Portuguese + HID_LOCAL_Russia , ///< Russia + HID_LOCAL_Slovakia , ///< Slovakia + HID_LOCAL_Spanish , ///< Spanish + HID_LOCAL_Swedish , ///< Swedish + HID_LOCAL_Swiss_French , ///< Swiss/French + HID_LOCAL_Swiss_German , ///< Swiss/German + HID_LOCAL_Switzerland , ///< Switzerland + HID_LOCAL_Taiwan , ///< Taiwan + HID_LOCAL_Turkish_Q , ///< Turkish-Q + HID_LOCAL_UK , ///< UK + HID_LOCAL_US , ///< US + HID_LOCAL_Yugoslavia , ///< Yugoslavia + HID_LOCAL_Turkish_F ///< Turkish-F +} hid_country_code_t; + +/** @} */ +//--------------------------------------------------------------------+ +// GAMEPAD +//--------------------------------------------------------------------+ +/** \addtogroup ClassDriver_HID_Gamepad Gamepad + * @{ */ + +/* From https://www.kernel.org/doc/html/latest/input/gamepad.html + ____________________________ __ + / [__ZL__] [__ZR__] \ | + / [__ TL __] [__ TR __] \ | Front Triggers + __/________________________________\__ __| + / _ \ | + / /\ __ (N) \ | + / || __ |MO| __ _ _ \ | Main Pad + | <===DP===> |SE| |ST| (W) -|- (E) | | + \ || ___ ___ _ / | + /\ \/ / \ / \ (S) /\ __| + / \________ | LS | ____ | RS | ________/ \ | +| / \ \___/ / \ \___/ / \ | | Control Sticks +| / \_____/ \_____/ \ | __| +| / \ | + \_____/ \_____/ + + |________|______| |______|___________| + D-Pad Left Right Action Pad + Stick Stick + + |_____________| + Menu Pad + + Most gamepads have the following features: + - Action-Pad 4 buttons in diamonds-shape (on the right side) NORTH, SOUTH, WEST and EAST. + - D-Pad (Direction-pad) 4 buttons (on the left side) that point up, down, left and right. + - Menu-Pad Different constellations, but most-times 2 buttons: SELECT - START. + - Analog-Sticks provide freely moveable sticks to control directions, Analog-sticks may also + provide a digital button if you press them. + - Triggers are located on the upper-side of the pad in vertical direction. The upper buttons + are normally named Left- and Right-Triggers, the lower buttons Z-Left and Z-Right. + - Rumble Many devices provide force-feedback features. But are mostly just simple rumble motors. + */ + +/// HID Gamepad Protocol Report. +typedef struct TU_ATTR_PACKED +{ + int8_t x; ///< Delta x movement of left analog-stick + int8_t y; ///< Delta y movement of left analog-stick + int8_t z; ///< Delta z movement of right analog-joystick + int8_t rz; ///< Delta Rz movement of right analog-joystick + int8_t rx; ///< Delta Rx movement of analog left trigger + int8_t ry; ///< Delta Ry movement of analog right trigger + uint8_t hat; ///< Buttons mask for currently pressed buttons in the DPad/hat + uint16_t buttons; ///< Buttons mask for currently pressed buttons +}hid_gamepad_report_t; + +/// HID Switch Gamepad Protocol Report. +typedef struct TU_ATTR_PACKED +{ + uint16_t buttons; ///< Buttons mask for currently pressed buttons + uint8_t hat; ///< Buttons mask for currently pressed buttons in the DPad/hat + int8_t x; ///< Delta x movement of left analog-stick + int8_t y; ///< Delta y movement of left analog-stick + int8_t rx; ///< Delta Rx movement of analog left trigger + int8_t ry; ///< Delta Ry movement of analog right trigger + int8_t z; ///< Delta z movement of right analog-joystick + int8_t rz; ///< Delta Rz movement of right analog-joystick +}hid_gamepad_ns_report_t; + +/// Standard Gamepad Buttons Bitmap (from Linux input event codes) +typedef enum +{ + GAMEPAD_BUTTON_A = TU_BIT(0), ///< A/South button + GAMEPAD_BUTTON_B = TU_BIT(1), ///< B/East button + GAMEPAD_BUTTON_C = TU_BIT(2), ///< C button + GAMEPAD_BUTTON_X = TU_BIT(3), ///< X/North button + GAMEPAD_BUTTON_Y = TU_BIT(4), ///< Y/West button + GAMEPAD_BUTTON_Z = TU_BIT(5), ///< Z button + GAMEPAD_BUTTON_TL = TU_BIT(6), ///< L1 button + GAMEPAD_BUTTON_TR = TU_BIT(7), ///< R1 button + GAMEPAD_BUTTON_TL2 = TU_BIT(8), ///< L2 button + GAMEPAD_BUTTON_TR2 = TU_BIT(9), ///< R2 button + GAMEPAD_BUTTON_SELECT = TU_BIT(10), ///< Select button + GAMEPAD_BUTTON_START = TU_BIT(11), ///< Start button + GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button + GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button + GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button +//GAMEPAD_BUTTON_ = TU_BIT(15), ///< Undefined button +}hid_gamepad_button_bm_t; + +/// Switch Gamepad Buttons Bitmap +typedef enum +{ + GAMEPAD_NS_BUTTON_Y = 0x01, + GAMEPAD_NS_BUTTON_B = 0x02, + GAMEPAD_NS_BUTTON_A = 0x04, + GAMEPAD_NS_BUTTON_X = 0x08, + GAMEPAD_NS_BUTTON_TL = 0x10, + GAMEPAD_NS_BUTTON_TR = 0x20, + GAMEPAD_NS_BUTTON_TL2 = 0x40, + GAMEPAD_NS_BUTTON_TR2 = 0x80, + GAMEPAD_NS_BUTTON_MINUS = 0x100, + GAMEPAD_NS_BUTTON_PLUS = 0x200, + GAMEPAD_NS_BUTTON_THUMBL = 0x400, + GAMEPAD_NS_BUTTON_THUMBR = 0x800, + GAMEPAD_NS_BUTTON_HOME = 0x1000, + GAMEPAD_NS_BUTTON_CAPTURE = 0x2000, + GAMEPAD_NS_BUTTON_Z = 0x4000, ///UNUSED? +}hid_gamepad_ns_button_bm_t; + +/// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes) +typedef enum +{ + GAMEPAD_HAT_CENTERED = 0, ///< DPAD_CENTERED + GAMEPAD_HAT_UP = 1, ///< DPAD_UP + GAMEPAD_HAT_UP_RIGHT = 2, ///< DPAD_UP_RIGHT + GAMEPAD_HAT_RIGHT = 3, ///< DPAD_RIGHT + GAMEPAD_HAT_DOWN_RIGHT = 4, ///< DPAD_DOWN_RIGHT + GAMEPAD_HAT_DOWN = 5, ///< DPAD_DOWN + GAMEPAD_HAT_DOWN_LEFT = 6, ///< DPAD_DOWN_LEFT + GAMEPAD_HAT_LEFT = 7, ///< DPAD_LEFT + GAMEPAD_HAT_UP_LEFT = 8, ///< DPAD_UP_LEFT +}hid_gamepad_hat_t; + +/// Switch Gamepad HAT/DPAD Buttons (from Linux input event codes) +typedef enum +{ + GAMEPAD_NS_HAT_CENTERED = 8, ///< DPAD_CENTERED + GAMEPAD_NS_HAT_UP = 0, ///< DPAD_UP + GAMEPAD_NS_HAT_UP_RIGHT = 1, ///< DPAD_UP_RIGHT + GAMEPAD_NS_HAT_RIGHT = 2, ///< DPAD_RIGHT + GAMEPAD_NS_HAT_DOWN_RIGHT = 3, ///< DPAD_DOWN_RIGHT + GAMEPAD_NS_HAT_DOWN = 4, ///< DPAD_DOWN + GAMEPAD_NS_HAT_DOWN_LEFT = 5, ///< DPAD_DOWN_LEFT + GAMEPAD_NS_HAT_LEFT = 6, ///< DPAD_LEFT + GAMEPAD_NS_HAT_UP_LEFT = 7, ///< DPAD_UP_LEFT +}hid_gamepad_ns_hat_t; + +/// @} + +//--------------------------------------------------------------------+ +// MOUSE +//--------------------------------------------------------------------+ +/** \addtogroup ClassDriver_HID_Mouse Mouse + * @{ */ + +/// Standard HID Boot Protocol Mouse Report. +typedef struct TU_ATTR_PACKED +{ + uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */ + int8_t x; /**< Current delta x movement of the mouse. */ + int8_t y; /**< Current delta y movement on the mouse. */ + int8_t wheel; /**< Current delta wheel movement on the mouse. */ + int8_t pan; // using AC Pan +} hid_mouse_report_t; + +/// Standard Mouse Buttons Bitmap +typedef enum +{ + MOUSE_BUTTON_LEFT = TU_BIT(0), ///< Left button + MOUSE_BUTTON_RIGHT = TU_BIT(1), ///< Right button + MOUSE_BUTTON_MIDDLE = TU_BIT(2), ///< Middle button + MOUSE_BUTTON_BACKWARD = TU_BIT(3), ///< Backward button, + MOUSE_BUTTON_FORWARD = TU_BIT(4), ///< Forward button, +}hid_mouse_button_bm_t; + +/// @} + +//--------------------------------------------------------------------+ +// Keyboard +//--------------------------------------------------------------------+ +/** \addtogroup ClassDriver_HID_Keyboard Keyboard + * @{ */ + +/// Standard HID Boot Protocol Keyboard Report. +typedef struct TU_ATTR_PACKED +{ + uint8_t modifier; /**< Keyboard modifier (KEYBOARD_MODIFIER_* masks). */ + uint8_t reserved; /**< Reserved for OEM use, always set to 0. */ + uint8_t keycode[6]; /**< Key codes of the currently pressed keys. */ +} hid_keyboard_report_t; + +/// Keyboard modifier codes bitmap +typedef enum +{ + KEYBOARD_MODIFIER_LEFTCTRL = TU_BIT(0), ///< Left Control + KEYBOARD_MODIFIER_LEFTSHIFT = TU_BIT(1), ///< Left Shift + KEYBOARD_MODIFIER_LEFTALT = TU_BIT(2), ///< Left Alt + KEYBOARD_MODIFIER_LEFTGUI = TU_BIT(3), ///< Left Window + KEYBOARD_MODIFIER_RIGHTCTRL = TU_BIT(4), ///< Right Control + KEYBOARD_MODIFIER_RIGHTSHIFT = TU_BIT(5), ///< Right Shift + KEYBOARD_MODIFIER_RIGHTALT = TU_BIT(6), ///< Right Alt + KEYBOARD_MODIFIER_RIGHTGUI = TU_BIT(7) ///< Right Window +}hid_keyboard_modifier_bm_t; +typedef enum +{ + KEYBOARD_LED_NUMLOCK = TU_BIT(0), ///< Num Lock LED + KEYBOARD_LED_CAPSLOCK = TU_BIT(1), ///< Caps Lock LED + KEYBOARD_LED_SCROLLLOCK = TU_BIT(2), ///< Scroll Lock LED + KEYBOARD_LED_COMPOSE = TU_BIT(3), ///< Composition Mode + KEYBOARD_LED_KANA = TU_BIT(4) ///< Kana mode +}hid_keyboard_led_bm_t; + +/// @} + +//--------------------------------------------------------------------+ +// HID KEYCODE +//--------------------------------------------------------------------+ +#define HID_KEY_NONE 0x00 +#define HID_KEY_A 0x04 +#define HID_KEY_B 0x05 +#define HID_KEY_C 0x06 +#define HID_KEY_D 0x07 +#define HID_KEY_E 0x08 +#define HID_KEY_F 0x09 +#define HID_KEY_G 0x0A +#define HID_KEY_H 0x0B +#define HID_KEY_I 0x0C +#define HID_KEY_J 0x0D +#define HID_KEY_K 0x0E +#define HID_KEY_L 0x0F +#define HID_KEY_M 0x10 +#define HID_KEY_N 0x11 +#define HID_KEY_O 0x12 +#define HID_KEY_P 0x13 +#define HID_KEY_Q 0x14 +#define HID_KEY_R 0x15 +#define HID_KEY_S 0x16 +#define HID_KEY_T 0x17 +#define HID_KEY_U 0x18 +#define HID_KEY_V 0x19 +#define HID_KEY_W 0x1A +#define HID_KEY_X 0x1B +#define HID_KEY_Y 0x1C +#define HID_KEY_Z 0x1D +#define HID_KEY_1 0x1E +#define HID_KEY_2 0x1F +#define HID_KEY_3 0x20 +#define HID_KEY_4 0x21 +#define HID_KEY_5 0x22 +#define HID_KEY_6 0x23 +#define HID_KEY_7 0x24 +#define HID_KEY_8 0x25 +#define HID_KEY_9 0x26 +#define HID_KEY_0 0x27 +#define HID_KEY_ENTER 0x28 +#define HID_KEY_ESCAPE 0x29 +#define HID_KEY_BACKSPACE 0x2A +#define HID_KEY_TAB 0x2B +#define HID_KEY_SPACE 0x2C +#define HID_KEY_MINUS 0x2D +#define HID_KEY_EQUAL 0x2E +#define HID_KEY_BRACKET_LEFT 0x2F +#define HID_KEY_BRACKET_RIGHT 0x30 +#define HID_KEY_BACKSLASH 0x31 +#define HID_KEY_EUROPE_1 0x32 +#define HID_KEY_SEMICOLON 0x33 +#define HID_KEY_APOSTROPHE 0x34 +#define HID_KEY_GRAVE 0x35 +#define HID_KEY_COMMA 0x36 +#define HID_KEY_PERIOD 0x37 +#define HID_KEY_SLASH 0x38 +#define HID_KEY_CAPS_LOCK 0x39 +#define HID_KEY_F1 0x3A +#define HID_KEY_F2 0x3B +#define HID_KEY_F3 0x3C +#define HID_KEY_F4 0x3D +#define HID_KEY_F5 0x3E +#define HID_KEY_F6 0x3F +#define HID_KEY_F7 0x40 +#define HID_KEY_F8 0x41 +#define HID_KEY_F9 0x42 +#define HID_KEY_F10 0x43 +#define HID_KEY_F11 0x44 +#define HID_KEY_F12 0x45 +#define HID_KEY_PRINT_SCREEN 0x46 +#define HID_KEY_SCROLL_LOCK 0x47 +#define HID_KEY_PAUSE 0x48 +#define HID_KEY_INSERT 0x49 +#define HID_KEY_HOME 0x4A +#define HID_KEY_PAGE_UP 0x4B +#define HID_KEY_DELETE 0x4C +#define HID_KEY_END 0x4D +#define HID_KEY_PAGE_DOWN 0x4E +#define HID_KEY_ARROW_RIGHT 0x4F +#define HID_KEY_ARROW_LEFT 0x50 +#define HID_KEY_ARROW_DOWN 0x51 +#define HID_KEY_ARROW_UP 0x52 +#define HID_KEY_NUM_LOCK 0x53 +#define HID_KEY_KEYPAD_DIVIDE 0x54 +#define HID_KEY_KEYPAD_MULTIPLY 0x55 +#define HID_KEY_KEYPAD_SUBTRACT 0x56 +#define HID_KEY_KEYPAD_ADD 0x57 +#define HID_KEY_KEYPAD_ENTER 0x58 +#define HID_KEY_KEYPAD_1 0x59 +#define HID_KEY_KEYPAD_2 0x5A +#define HID_KEY_KEYPAD_3 0x5B +#define HID_KEY_KEYPAD_4 0x5C +#define HID_KEY_KEYPAD_5 0x5D +#define HID_KEY_KEYPAD_6 0x5E +#define HID_KEY_KEYPAD_7 0x5F +#define HID_KEY_KEYPAD_8 0x60 +#define HID_KEY_KEYPAD_9 0x61 +#define HID_KEY_KEYPAD_0 0x62 +#define HID_KEY_KEYPAD_DECIMAL 0x63 +#define HID_KEY_EUROPE_2 0x64 +#define HID_KEY_APPLICATION 0x65 +#define HID_KEY_POWER 0x66 +#define HID_KEY_KEYPAD_EQUAL 0x67 +#define HID_KEY_F13 0x68 +#define HID_KEY_F14 0x69 +#define HID_KEY_F15 0x6A +#define HID_KEY_F16 0x6B +#define HID_KEY_F17 0x6C +#define HID_KEY_F18 0x6D +#define HID_KEY_F19 0x6E +#define HID_KEY_F20 0x6F +#define HID_KEY_F21 0x70 +#define HID_KEY_F22 0x71 +#define HID_KEY_F23 0x72 +#define HID_KEY_F24 0x73 +#define HID_KEY_EXECUTE 0x74 +#define HID_KEY_HELP 0x75 +#define HID_KEY_MENU 0x76 +#define HID_KEY_SELECT 0x77 +#define HID_KEY_STOP 0x78 +#define HID_KEY_AGAIN 0x79 +#define HID_KEY_UNDO 0x7A +#define HID_KEY_CUT 0x7B +#define HID_KEY_COPY 0x7C +#define HID_KEY_PASTE 0x7D +#define HID_KEY_FIND 0x7E +#define HID_KEY_MUTE 0x7F +#define HID_KEY_VOLUME_UP 0x80 +#define HID_KEY_VOLUME_DOWN 0x81 +#define HID_KEY_LOCKING_CAPS_LOCK 0x82 +#define HID_KEY_LOCKING_NUM_LOCK 0x83 +#define HID_KEY_LOCKING_SCROLL_LOCK 0x84 +#define HID_KEY_KEYPAD_COMMA 0x85 +#define HID_KEY_KEYPAD_EQUAL_SIGN 0x86 +#define HID_KEY_KANJI1 0x87 +#define HID_KEY_KANJI2 0x88 +#define HID_KEY_KANJI3 0x89 +#define HID_KEY_KANJI4 0x8A +#define HID_KEY_KANJI5 0x8B +#define HID_KEY_KANJI6 0x8C +#define HID_KEY_KANJI7 0x8D +#define HID_KEY_KANJI8 0x8E +#define HID_KEY_KANJI9 0x8F +#define HID_KEY_LANG1 0x90 +#define HID_KEY_LANG2 0x91 +#define HID_KEY_LANG3 0x92 +#define HID_KEY_LANG4 0x93 +#define HID_KEY_LANG5 0x94 +#define HID_KEY_LANG6 0x95 +#define HID_KEY_LANG7 0x96 +#define HID_KEY_LANG8 0x97 +#define HID_KEY_LANG9 0x98 +#define HID_KEY_ALTERNATE_ERASE 0x99 +#define HID_KEY_SYSREQ_ATTENTION 0x9A +#define HID_KEY_CANCEL 0x9B +#define HID_KEY_CLEAR 0x9C +#define HID_KEY_PRIOR 0x9D +#define HID_KEY_RETURN 0x9E +#define HID_KEY_SEPARATOR 0x9F +#define HID_KEY_OUT 0xA0 +#define HID_KEY_OPER 0xA1 +#define HID_KEY_CLEAR_AGAIN 0xA2 +#define HID_KEY_CRSEL_PROPS 0xA3 +#define HID_KEY_EXSEL 0xA4 +// RESERVED 0xA5-DF +#define HID_KEY_CONTROL_LEFT 0xE0 +#define HID_KEY_SHIFT_LEFT 0xE1 +#define HID_KEY_ALT_LEFT 0xE2 +#define HID_KEY_GUI_LEFT 0xE3 +#define HID_KEY_CONTROL_RIGHT 0xE4 +#define HID_KEY_SHIFT_RIGHT 0xE5 +#define HID_KEY_ALT_RIGHT 0xE6 +#define HID_KEY_GUI_RIGHT 0xE7 + + +//--------------------------------------------------------------------+ +// REPORT DESCRIPTOR +//--------------------------------------------------------------------+ +//------------- ITEM & TAG -------------// +#define HID_REPORT_DATA_0(data) +#define HID_REPORT_DATA_1(data) , data +#define HID_REPORT_DATA_2(data) , U16_TO_U8S_LE(data) +#define HID_REPORT_DATA_3(data) , U32_TO_U8S_LE(data) + +#define HID_REPORT_ITEM(data, tag, type, size) \ + (((tag) << 4) | ((type) << 2) | (size)) HID_REPORT_DATA_##size(data) + +#define RI_TYPE_MAIN 0 +#define RI_TYPE_GLOBAL 1 +#define RI_TYPE_LOCAL 2 + +//------------- MAIN ITEMS 6.2.2.4 -------------// +#define HID_INPUT(x) HID_REPORT_ITEM(x, 8, RI_TYPE_MAIN, 1) +#define HID_OUTPUT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_MAIN, 1) +#define HID_COLLECTION(x) HID_REPORT_ITEM(x, 10, RI_TYPE_MAIN, 1) +#define HID_FEATURE(x) HID_REPORT_ITEM(x, 11, RI_TYPE_MAIN, 1) +#define HID_COLLECTION_END HID_REPORT_ITEM(x, 12, RI_TYPE_MAIN, 0) + +//------------- INPUT, OUTPUT, FEATURE 6.2.2.5 -------------// +#define HID_DATA (0<<0) +#define HID_CONSTANT (1<<0) + +#define HID_ARRAY (0<<1) +#define HID_VARIABLE (1<<1) + +#define HID_ABSOLUTE (0<<2) +#define HID_RELATIVE (1<<2) + +#define HID_WRAP_NO (0<<3) +#define HID_WRAP (1<<3) + +#define HID_LINEAR (0<<4) +#define HID_NONLINEAR (1<<4) + +#define HID_PREFERRED_STATE (0<<5) +#define HID_PREFERRED_NO (1<<5) + +#define HID_NO_NULL_POSITION (0<<6) +#define HID_NULL_STATE (1<<6) + +#define HID_NON_VOLATILE (0<<7) +#define HID_VOLATILE (1<<7) + +#define HID_BITFIELD (0<<8) +#define HID_BUFFERED_BYTES (1<<8) + +//------------- COLLECTION ITEM 6.2.2.6 -------------// +enum { + HID_COLLECTION_PHYSICAL = 0, + HID_COLLECTION_APPLICATION, + HID_COLLECTION_LOGICAL, + HID_COLLECTION_REPORT, + HID_COLLECTION_NAMED_ARRAY, + HID_COLLECTION_USAGE_SWITCH, + HID_COLLECTION_USAGE_MODIFIER +}; + +//------------- GLOBAL ITEMS 6.2.2.7 -------------// +#define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, 1) +#define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, n) + +#define HID_LOGICAL_MIN(x) HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, 1) +#define HID_LOGICAL_MIN_N(x, n) HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, n) + +#define HID_LOGICAL_MAX(x) HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, 1) +#define HID_LOGICAL_MAX_N(x, n) HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, n) + +#define HID_PHYSICAL_MIN(x) HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, 1) +#define HID_PHYSICAL_MIN_N(x, n) HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, n) + +#define HID_PHYSICAL_MAX(x) HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, 1) +#define HID_PHYSICAL_MAX_N(x, n) HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, n) + +#define HID_UNIT_EXPONENT(x) HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, 1) +#define HID_UNIT_EXPONENT_N(x, n) HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, n) + +#define HID_UNIT(x) HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, 1) +#define HID_UNIT_N(x, n) HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, n) + +#define HID_REPORT_SIZE(x) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, 1) +#define HID_REPORT_SIZE_N(x, n) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, n) + +#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, 1), +#define HID_REPORT_ID_N(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, n), + +#define HID_REPORT_COUNT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, 1) +#define HID_REPORT_COUNT_N(x, n) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, n) + +#define HID_PUSH HID_REPORT_ITEM(x, 10, RI_TYPE_GLOBAL, 0) +#define HID_POP HID_REPORT_ITEM(x, 11, RI_TYPE_GLOBAL, 0) + +//------------- LOCAL ITEMS 6.2.2.8 -------------// +#define HID_USAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, 1) +#define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, n) + +#define HID_USAGE_MIN(x) HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, 1) +#define HID_USAGE_MIN_N(x, n) HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, n) + +#define HID_USAGE_MAX(x) HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, 1) +#define HID_USAGE_MAX_N(x, n) HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, n) + +//--------------------------------------------------------------------+ +// Usage Table +//--------------------------------------------------------------------+ + +/// HID Usage Table - Table 1: Usage Page Summary +enum { + HID_USAGE_PAGE_DESKTOP = 0x01, + HID_USAGE_PAGE_SIMULATE = 0x02, + HID_USAGE_PAGE_VIRTUAL_REALITY = 0x03, + HID_USAGE_PAGE_SPORT = 0x04, + HID_USAGE_PAGE_GAME = 0x05, + HID_USAGE_PAGE_GENERIC_DEVICE = 0x06, + HID_USAGE_PAGE_KEYBOARD = 0x07, + HID_USAGE_PAGE_LED = 0x08, + HID_USAGE_PAGE_BUTTON = 0x09, + HID_USAGE_PAGE_ORDINAL = 0x0a, + HID_USAGE_PAGE_TELEPHONY = 0x0b, + HID_USAGE_PAGE_CONSUMER = 0x0c, + HID_USAGE_PAGE_DIGITIZER = 0x0d, + HID_USAGE_PAGE_PID = 0x0f, + HID_USAGE_PAGE_UNICODE = 0x10, + HID_USAGE_PAGE_ALPHA_DISPLAY = 0x14, + HID_USAGE_PAGE_MEDICAL = 0x40, + HID_USAGE_PAGE_MONITOR = 0x80, //0x80 - 0x83 + HID_USAGE_PAGE_POWER = 0x84, // 0x084 - 0x87 + HID_USAGE_PAGE_BARCODE_SCANNER = 0x8c, + HID_USAGE_PAGE_SCALE = 0x8d, + HID_USAGE_PAGE_MSR = 0x8e, + HID_USAGE_PAGE_CAMERA = 0x90, + HID_USAGE_PAGE_ARCADE = 0x91, + HID_USAGE_PAGE_VENDOR = 0xFF00 // 0xFF00 - 0xFFFF +}; + +/// HID Usage Table - Table 6: Generic Desktop Page +enum { + HID_USAGE_DESKTOP_POINTER = 0x01, + HID_USAGE_DESKTOP_MOUSE = 0x02, + HID_USAGE_DESKTOP_JOYSTICK = 0x04, + HID_USAGE_DESKTOP_GAMEPAD = 0x05, + HID_USAGE_DESKTOP_KEYBOARD = 0x06, + HID_USAGE_DESKTOP_KEYPAD = 0x07, + HID_USAGE_DESKTOP_MULTI_AXIS_CONTROLLER = 0x08, + HID_USAGE_DESKTOP_TABLET_PC_SYSTEM = 0x09, + HID_USAGE_DESKTOP_X = 0x30, + HID_USAGE_DESKTOP_Y = 0x31, + HID_USAGE_DESKTOP_Z = 0x32, + HID_USAGE_DESKTOP_RX = 0x33, + HID_USAGE_DESKTOP_RY = 0x34, + HID_USAGE_DESKTOP_RZ = 0x35, + HID_USAGE_DESKTOP_SLIDER = 0x36, + HID_USAGE_DESKTOP_DIAL = 0x37, + HID_USAGE_DESKTOP_WHEEL = 0x38, + HID_USAGE_DESKTOP_HAT_SWITCH = 0x39, + HID_USAGE_DESKTOP_COUNTED_BUFFER = 0x3a, + HID_USAGE_DESKTOP_BYTE_COUNT = 0x3b, + HID_USAGE_DESKTOP_MOTION_WAKEUP = 0x3c, + HID_USAGE_DESKTOP_START = 0x3d, + HID_USAGE_DESKTOP_SELECT = 0x3e, + HID_USAGE_DESKTOP_VX = 0x40, + HID_USAGE_DESKTOP_VY = 0x41, + HID_USAGE_DESKTOP_VZ = 0x42, + HID_USAGE_DESKTOP_VBRX = 0x43, + HID_USAGE_DESKTOP_VBRY = 0x44, + HID_USAGE_DESKTOP_VBRZ = 0x45, + HID_USAGE_DESKTOP_VNO = 0x46, + HID_USAGE_DESKTOP_FEATURE_NOTIFICATION = 0x47, + HID_USAGE_DESKTOP_RESOLUTION_MULTIPLIER = 0x48, + HID_USAGE_DESKTOP_SYSTEM_CONTROL = 0x80, + HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN = 0x81, + HID_USAGE_DESKTOP_SYSTEM_SLEEP = 0x82, + HID_USAGE_DESKTOP_SYSTEM_WAKE_UP = 0x83, + HID_USAGE_DESKTOP_SYSTEM_CONTEXT_MENU = 0x84, + HID_USAGE_DESKTOP_SYSTEM_MAIN_MENU = 0x85, + HID_USAGE_DESKTOP_SYSTEM_APP_MENU = 0x86, + HID_USAGE_DESKTOP_SYSTEM_MENU_HELP = 0x87, + HID_USAGE_DESKTOP_SYSTEM_MENU_EXIT = 0x88, + HID_USAGE_DESKTOP_SYSTEM_MENU_SELECT = 0x89, + HID_USAGE_DESKTOP_SYSTEM_MENU_RIGHT = 0x8A, + HID_USAGE_DESKTOP_SYSTEM_MENU_LEFT = 0x8B, + HID_USAGE_DESKTOP_SYSTEM_MENU_UP = 0x8C, + HID_USAGE_DESKTOP_SYSTEM_MENU_DOWN = 0x8D, + HID_USAGE_DESKTOP_SYSTEM_COLD_RESTART = 0x8E, + HID_USAGE_DESKTOP_SYSTEM_WARM_RESTART = 0x8F, + HID_USAGE_DESKTOP_DPAD_UP = 0x90, + HID_USAGE_DESKTOP_DPAD_DOWN = 0x91, + HID_USAGE_DESKTOP_DPAD_RIGHT = 0x92, + HID_USAGE_DESKTOP_DPAD_LEFT = 0x93, + HID_USAGE_DESKTOP_SYSTEM_DOCK = 0xA0, + HID_USAGE_DESKTOP_SYSTEM_UNDOCK = 0xA1, + HID_USAGE_DESKTOP_SYSTEM_SETUP = 0xA2, + HID_USAGE_DESKTOP_SYSTEM_BREAK = 0xA3, + HID_USAGE_DESKTOP_SYSTEM_DEBUGGER_BREAK = 0xA4, + HID_USAGE_DESKTOP_APPLICATION_BREAK = 0xA5, + HID_USAGE_DESKTOP_APPLICATION_DEBUGGER_BREAK = 0xA6, + HID_USAGE_DESKTOP_SYSTEM_SPEAKER_MUTE = 0xA7, + HID_USAGE_DESKTOP_SYSTEM_HIBERNATE = 0xA8, + HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INVERT = 0xB0, + HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INTERNAL = 0xB1, + HID_USAGE_DESKTOP_SYSTEM_DISPLAY_EXTERNAL = 0xB2, + HID_USAGE_DESKTOP_SYSTEM_DISPLAY_BOTH = 0xB3, + HID_USAGE_DESKTOP_SYSTEM_DISPLAY_DUAL = 0xB4, + HID_USAGE_DESKTOP_SYSTEM_DISPLAY_TOGGLE_INT_EXT = 0xB5, + HID_USAGE_DESKTOP_SYSTEM_DISPLAY_SWAP_PRIMARY_SECONDARY = 0xB6, + HID_USAGE_DESKTOP_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7 +}; + + +/// HID Usage Table: Consumer Page (0x0C) +/// Only contains controls that supported by Windows (whole list is too long) +enum +{ + // Generic Control + HID_USAGE_CONSUMER_CONTROL = 0x0001, + + // Power Control + HID_USAGE_CONSUMER_POWER = 0x0030, + HID_USAGE_CONSUMER_RESET = 0x0031, + HID_USAGE_CONSUMER_SLEEP = 0x0032, + + // Screen Brightness + HID_USAGE_CONSUMER_BRIGHTNESS_INCREMENT = 0x006F, + HID_USAGE_CONSUMER_BRIGHTNESS_DECREMENT = 0x0070, + + // These HID usages operate only on mobile systems (battery powered) and + // require Windows 8 (build 8302 or greater). + HID_USAGE_CONSUMER_WIRELESS_RADIO_CONTROLS = 0x000C, + HID_USAGE_CONSUMER_WIRELESS_RADIO_BUTTONS = 0x00C6, + HID_USAGE_CONSUMER_WIRELESS_RADIO_LED = 0x00C7, + HID_USAGE_CONSUMER_WIRELESS_RADIO_SLIDER_SWITCH = 0x00C8, + + // Media Control + HID_USAGE_CONSUMER_PLAY_PAUSE = 0x00CD, + HID_USAGE_CONSUMER_SCAN_NEXT = 0x00B5, + HID_USAGE_CONSUMER_SCAN_PREVIOUS = 0x00B6, + HID_USAGE_CONSUMER_STOP = 0x00B7, + HID_USAGE_CONSUMER_VOLUME = 0x00E0, + HID_USAGE_CONSUMER_MUTE = 0x00E2, + HID_USAGE_CONSUMER_BASS = 0x00E3, + HID_USAGE_CONSUMER_TREBLE = 0x00E4, + HID_USAGE_CONSUMER_BASS_BOOST = 0x00E5, + HID_USAGE_CONSUMER_VOLUME_INCREMENT = 0x00E9, + HID_USAGE_CONSUMER_VOLUME_DECREMENT = 0x00EA, + HID_USAGE_CONSUMER_BASS_INCREMENT = 0x0152, + HID_USAGE_CONSUMER_BASS_DECREMENT = 0x0153, + HID_USAGE_CONSUMER_TREBLE_INCREMENT = 0x0154, + HID_USAGE_CONSUMER_TREBLE_DECREMENT = 0x0155, + + // Application Launcher + HID_USAGE_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION = 0x0183, + HID_USAGE_CONSUMER_AL_EMAIL_READER = 0x018A, + HID_USAGE_CONSUMER_AL_CALCULATOR = 0x0192, + HID_USAGE_CONSUMER_AL_LOCAL_BROWSER = 0x0194, + + // Browser/Explorer Specific + HID_USAGE_CONSUMER_AC_SEARCH = 0x0221, + HID_USAGE_CONSUMER_AC_HOME = 0x0223, + HID_USAGE_CONSUMER_AC_BACK = 0x0224, + HID_USAGE_CONSUMER_AC_FORWARD = 0x0225, + HID_USAGE_CONSUMER_AC_STOP = 0x0226, + HID_USAGE_CONSUMER_AC_REFRESH = 0x0227, + HID_USAGE_CONSUMER_AC_BOOKMARKS = 0x022A, + + // Mouse Horizontal scroll + HID_USAGE_CONSUMER_AC_PAN = 0x0238, +}; + +/*-------------------------------------------------------------------- + * ASCII to KEYCODE Conversion + * Expand to array of [128][2] (shift, keycode) + * + * Usage: example to convert input chr into keyboard report (modifier + keycode) + * + * uint8_t const conv_table[128][2] = { HID_ASCII_TO_KEYCODE }; + * + * uint8_t keycode[6] = { 0 }; + * uint8_t modifier = 0; + * + * if ( conv_table[chr][0] ) modifier = KEYBOARD_MODIFIER_LEFTSHIFT; + * keycode[0] = conv_table[chr][1]; + * tud_hid_keyboard_report(report_id, modifier, keycode); + * + *--------------------------------------------------------------------*/ +#define HID_ASCII_TO_KEYCODE \ + {0, 0 }, /* 0x00 Null */ \ + {0, 0 }, /* 0x01 */ \ + {0, 0 }, /* 0x02 */ \ + {0, 0 }, /* 0x03 */ \ + {0, 0 }, /* 0x04 */ \ + {0, 0 }, /* 0x05 */ \ + {0, 0 }, /* 0x06 */ \ + {0, 0 }, /* 0x07 */ \ + {0, HID_KEY_BACKSPACE }, /* 0x08 Backspace */ \ + {0, HID_KEY_TAB }, /* 0x09 Tab */ \ + {0, HID_KEY_RETURN }, /* 0x0A Line Feed */ \ + {0, 0 }, /* 0x0B */ \ + {0, 0 }, /* 0x0C */ \ + {0, HID_KEY_RETURN }, /* 0x0D CR */ \ + {0, 0 }, /* 0x0E */ \ + {0, 0 }, /* 0x0F */ \ + {0, 0 }, /* 0x10 */ \ + {0, 0 }, /* 0x11 */ \ + {0, 0 }, /* 0x12 */ \ + {0, 0 }, /* 0x13 */ \ + {0, 0 }, /* 0x14 */ \ + {0, 0 }, /* 0x15 */ \ + {0, 0 }, /* 0x16 */ \ + {0, 0 }, /* 0x17 */ \ + {0, 0 }, /* 0x18 */ \ + {0, 0 }, /* 0x19 */ \ + {0, 0 }, /* 0x1A */ \ + {0, HID_KEY_ESCAPE }, /* 0x1B Escape */ \ + {0, 0 }, /* 0x1C */ \ + {0, 0 }, /* 0x1D */ \ + {0, 0 }, /* 0x1E */ \ + {0, 0 }, /* 0x1F */ \ + \ + {0, HID_KEY_SPACE }, /* 0x20 */ \ + {1, HID_KEY_1 }, /* 0x21 ! */ \ + {1, HID_KEY_APOSTROPHE }, /* 0x22 " */ \ + {1, HID_KEY_3 }, /* 0x23 # */ \ + {1, HID_KEY_4 }, /* 0x24 $ */ \ + {1, HID_KEY_5 }, /* 0x25 % */ \ + {1, HID_KEY_7 }, /* 0x26 & */ \ + {0, HID_KEY_APOSTROPHE }, /* 0x27 ' */ \ + {1, HID_KEY_9 }, /* 0x28 ( */ \ + {1, HID_KEY_0 }, /* 0x29 ) */ \ + {1, HID_KEY_8 }, /* 0x2A * */ \ + {1, HID_KEY_EQUAL }, /* 0x2B + */ \ + {0, HID_KEY_COMMA }, /* 0x2C , */ \ + {0, HID_KEY_MINUS }, /* 0x2D - */ \ + {0, HID_KEY_PERIOD }, /* 0x2E . */ \ + {0, HID_KEY_SLASH }, /* 0x2F / */ \ + {0, HID_KEY_0 }, /* 0x30 0 */ \ + {0, HID_KEY_1 }, /* 0x31 1 */ \ + {0, HID_KEY_2 }, /* 0x32 2 */ \ + {0, HID_KEY_3 }, /* 0x33 3 */ \ + {0, HID_KEY_4 }, /* 0x34 4 */ \ + {0, HID_KEY_5 }, /* 0x35 5 */ \ + {0, HID_KEY_6 }, /* 0x36 6 */ \ + {0, HID_KEY_7 }, /* 0x37 7 */ \ + {0, HID_KEY_8 }, /* 0x38 8 */ \ + {0, HID_KEY_9 }, /* 0x39 9 */ \ + {1, HID_KEY_SEMICOLON }, /* 0x3A : */ \ + {0, HID_KEY_SEMICOLON }, /* 0x3B ; */ \ + {1, HID_KEY_COMMA }, /* 0x3C < */ \ + {0, HID_KEY_EQUAL }, /* 0x3D = */ \ + {1, HID_KEY_PERIOD }, /* 0x3E > */ \ + {1, HID_KEY_SLASH }, /* 0x3F ? */ \ + \ + {1, HID_KEY_2 }, /* 0x40 @ */ \ + {1, HID_KEY_A }, /* 0x41 A */ \ + {1, HID_KEY_B }, /* 0x42 B */ \ + {1, HID_KEY_C }, /* 0x43 C */ \ + {1, HID_KEY_D }, /* 0x44 D */ \ + {1, HID_KEY_E }, /* 0x45 E */ \ + {1, HID_KEY_F }, /* 0x46 F */ \ + {1, HID_KEY_G }, /* 0x47 G */ \ + {1, HID_KEY_H }, /* 0x48 H */ \ + {1, HID_KEY_I }, /* 0x49 I */ \ + {1, HID_KEY_J }, /* 0x4A J */ \ + {1, HID_KEY_K }, /* 0x4B K */ \ + {1, HID_KEY_L }, /* 0x4C L */ \ + {1, HID_KEY_M }, /* 0x4D M */ \ + {1, HID_KEY_N }, /* 0x4E N */ \ + {1, HID_KEY_O }, /* 0x4F O */ \ + {1, HID_KEY_P }, /* 0x50 P */ \ + {1, HID_KEY_Q }, /* 0x51 Q */ \ + {1, HID_KEY_R }, /* 0x52 R */ \ + {1, HID_KEY_S }, /* 0x53 S */ \ + {1, HID_KEY_T }, /* 0x55 T */ \ + {1, HID_KEY_U }, /* 0x55 U */ \ + {1, HID_KEY_V }, /* 0x56 V */ \ + {1, HID_KEY_W }, /* 0x57 W */ \ + {1, HID_KEY_X }, /* 0x58 X */ \ + {1, HID_KEY_Y }, /* 0x59 Y */ \ + {1, HID_KEY_Z }, /* 0x5A Z */ \ + {0, HID_KEY_BRACKET_LEFT }, /* 0x5B [ */ \ + {0, HID_KEY_BACKSLASH }, /* 0x5C '\' */ \ + {0, HID_KEY_BRACKET_RIGHT }, /* 0x5D ] */ \ + {1, HID_KEY_6 }, /* 0x5E ^ */ \ + {1, HID_KEY_MINUS }, /* 0x5F _ */ \ + \ + {0, HID_KEY_GRAVE }, /* 0x60 ` */ \ + {0, HID_KEY_A }, /* 0x61 a */ \ + {0, HID_KEY_B }, /* 0x62 b */ \ + {0, HID_KEY_C }, /* 0x63 c */ \ + {0, HID_KEY_D }, /* 0x66 d */ \ + {0, HID_KEY_E }, /* 0x65 e */ \ + {0, HID_KEY_F }, /* 0x66 f */ \ + {0, HID_KEY_G }, /* 0x67 g */ \ + {0, HID_KEY_H }, /* 0x68 h */ \ + {0, HID_KEY_I }, /* 0x69 i */ \ + {0, HID_KEY_J }, /* 0x6A j */ \ + {0, HID_KEY_K }, /* 0x6B k */ \ + {0, HID_KEY_L }, /* 0x6C l */ \ + {0, HID_KEY_M }, /* 0x6D m */ \ + {0, HID_KEY_N }, /* 0x6E n */ \ + {0, HID_KEY_O }, /* 0x6F o */ \ + {0, HID_KEY_P }, /* 0x70 p */ \ + {0, HID_KEY_Q }, /* 0x71 q */ \ + {0, HID_KEY_R }, /* 0x72 r */ \ + {0, HID_KEY_S }, /* 0x73 s */ \ + {0, HID_KEY_T }, /* 0x75 t */ \ + {0, HID_KEY_U }, /* 0x75 u */ \ + {0, HID_KEY_V }, /* 0x76 v */ \ + {0, HID_KEY_W }, /* 0x77 w */ \ + {0, HID_KEY_X }, /* 0x78 x */ \ + {0, HID_KEY_Y }, /* 0x79 y */ \ + {0, HID_KEY_Z }, /* 0x7A z */ \ + {1, HID_KEY_BRACKET_LEFT }, /* 0x7B { */ \ + {1, HID_KEY_BACKSLASH }, /* 0x7C | */ \ + {1, HID_KEY_BRACKET_RIGHT }, /* 0x7D } */ \ + {1, HID_KEY_GRAVE }, /* 0x7E ~ */ \ + {0, HID_KEY_DELETE } /* 0x7F Delete */ \ + +/*-------------------------------------------------------------------- + * KEYCODE to Ascii Conversion + * Expand to array of [128][2] (ascii without shift, ascii with shift) + * + * Usage: example to convert ascii from keycode (key) and shift modifier (shift). + * Here we assume key < 128 ( printable ) + * + * uint8_t const conv_table[128][2] = { HID_KEYCODE_TO_ASCII }; + * char ch = shift ? conv_table[chr][1] : conv_table[chr][0]; + * + *--------------------------------------------------------------------*/ +#define HID_KEYCODE_TO_ASCII \ + {0 , 0 }, /* 0x00 */ \ + {0 , 0 }, /* 0x01 */ \ + {0 , 0 }, /* 0x02 */ \ + {0 , 0 }, /* 0x03 */ \ + {'a' , 'A' }, /* 0x04 */ \ + {'b' , 'B' }, /* 0x05 */ \ + {'c' , 'C' }, /* 0x06 */ \ + {'d' , 'D' }, /* 0x07 */ \ + {'e' , 'E' }, /* 0x08 */ \ + {'f' , 'F' }, /* 0x09 */ \ + {'g' , 'G' }, /* 0x0a */ \ + {'h' , 'H' }, /* 0x0b */ \ + {'i' , 'I' }, /* 0x0c */ \ + {'j' , 'J' }, /* 0x0d */ \ + {'k' , 'K' }, /* 0x0e */ \ + {'l' , 'L' }, /* 0x0f */ \ + {'m' , 'M' }, /* 0x10 */ \ + {'n' , 'N' }, /* 0x11 */ \ + {'o' , 'O' }, /* 0x12 */ \ + {'p' , 'P' }, /* 0x13 */ \ + {'q' , 'Q' }, /* 0x14 */ \ + {'r' , 'R' }, /* 0x15 */ \ + {'s' , 'S' }, /* 0x16 */ \ + {'t' , 'T' }, /* 0x17 */ \ + {'u' , 'U' }, /* 0x18 */ \ + {'v' , 'V' }, /* 0x19 */ \ + {'w' , 'W' }, /* 0x1a */ \ + {'x' , 'X' }, /* 0x1b */ \ + {'y' , 'Y' }, /* 0x1c */ \ + {'z' , 'Z' }, /* 0x1d */ \ + {'1' , '!' }, /* 0x1e */ \ + {'2' , '@' }, /* 0x1f */ \ + {'3' , '#' }, /* 0x20 */ \ + {'4' , '$' }, /* 0x21 */ \ + {'5' , '%' }, /* 0x22 */ \ + {'6' , '^' }, /* 0x23 */ \ + {'7' , '&' }, /* 0x24 */ \ + {'8' , '*' }, /* 0x25 */ \ + {'9' , '(' }, /* 0x26 */ \ + {'0' , ')' }, /* 0x27 */ \ + {'\r' , '\r' }, /* 0x28 */ \ + {'\x1b', '\x1b' }, /* 0x29 */ \ + {'\b' , '\b' }, /* 0x2a */ \ + {'\t' , '\t' }, /* 0x2b */ \ + {' ' , ' ' }, /* 0x2c */ \ + {'-' , '_' }, /* 0x2d */ \ + {'=' , '+' }, /* 0x2e */ \ + {'[' , '{' }, /* 0x2f */ \ + {']' , '}' }, /* 0x30 */ \ + {'\\' , '|' }, /* 0x31 */ \ + {'#' , '~' }, /* 0x32 */ \ + {';' , ':' }, /* 0x33 */ \ + {'\'' , '\"' }, /* 0x34 */ \ + {'`' , '~' }, /* 0x35 */ \ + {',' , '<' }, /* 0x36 */ \ + {'.' , '>' }, /* 0x37 */ \ + {'/' , '?' }, /* 0x38 */ \ + \ + {0 , 0 }, /* 0x39 */ \ + {0 , 0 }, /* 0x3a */ \ + {0 , 0 }, /* 0x3b */ \ + {0 , 0 }, /* 0x3c */ \ + {0 , 0 }, /* 0x3d */ \ + {0 , 0 }, /* 0x3e */ \ + {0 , 0 }, /* 0x3f */ \ + {0 , 0 }, /* 0x40 */ \ + {0 , 0 }, /* 0x41 */ \ + {0 , 0 }, /* 0x42 */ \ + {0 , 0 }, /* 0x43 */ \ + {0 , 0 }, /* 0x44 */ \ + {0 , 0 }, /* 0x45 */ \ + {0 , 0 }, /* 0x46 */ \ + {0 , 0 }, /* 0x47 */ \ + {0 , 0 }, /* 0x48 */ \ + {0 , 0 }, /* 0x49 */ \ + {0 , 0 }, /* 0x4a */ \ + {0 , 0 }, /* 0x4b */ \ + {0 , 0 }, /* 0x4c */ \ + {0 , 0 }, /* 0x4d */ \ + {0 , 0 }, /* 0x4e */ \ + {0 , 0 }, /* 0x4f */ \ + {0 , 0 }, /* 0x50 */ \ + {0 , 0 }, /* 0x51 */ \ + {0 , 0 }, /* 0x52 */ \ + {0 , 0 }, /* 0x53 */ \ + \ + {'/' , '/' }, /* 0x54 */ \ + {'*' , '*' }, /* 0x55 */ \ + {'-' , '-' }, /* 0x56 */ \ + {'+' , '+' }, /* 0x57 */ \ + {'\r' , '\r' }, /* 0x58 */ \ + {'1' , 0 }, /* 0x59 */ \ + {'2' , 0 }, /* 0x5a */ \ + {'3' , 0 }, /* 0x5b */ \ + {'4' , 0 }, /* 0x5c */ \ + {'5' , '5' }, /* 0x5d */ \ + {'6' , 0 }, /* 0x5e */ \ + {'7' , 0 }, /* 0x5f */ \ + {'8' , 0 }, /* 0x60 */ \ + {'9' , 0 }, /* 0x61 */ \ + {'0' , 0 }, /* 0x62 */ \ + {'0' , 0 }, /* 0x63 */ \ + {'=' , '=' }, /* 0x67 */ \ + + +#ifdef __cplusplus + } #endif + + + + + +#endif /* _TUSB_TYPES_H_ */ + + diff --git a/examples_x035/usbdevice.incomplete/usbdevice.c b/examples_x035/usbdevice.incomplete/usbdevice.c index 6ac12256..4478a55d 100644 --- a/examples_x035/usbdevice.incomplete/usbdevice.c +++ b/examples_x035/usbdevice.incomplete/usbdevice.c @@ -14,6 +14,55 @@ void handle_debug_input( int numbytes, uint8_t * data ) count += numbytes; } +int HandleHidNonStandardSetup( struct _USBState * ctx, tusb_control_request_t * req ) +{ + +/* + int USBFS_SetupReqType = FSUSBCTX.USBFS_SetupReqType = pUSBFS_SetupReqPak->bmRequestType; + int USBFS_SetupReqCode = FSUSBCTX.USBFS_SetupReqCode = pUSBFS_SetupReqPak->bRequest; + int USBFS_SetupReqLen = FSUSBCTX.USBFS_SetupReqLen = pUSBFS_SetupReqPak->wLength; + int USBFS_SetupReqIndex = pUSBFS_SetupReqPak->wIndex; + int USBFS_IndexValue = FSUSBCTX.USBFS_IndexValue = ( pUSBFS_SetupReqPak->wIndex << 16 ) | pUSBFS_SetupReqPak->wValue; + len = 0; + USBDEBUG1++; +*/ + int id = req->wValue & 0xff; + if( id == 0xaa ) + { + if( req->bRequest == HID_REQ_CONTROL_SET_REPORT ) + { + //int i; + //for( i = 0; i < 64; i++ ) + //{ + // printf( "%02x ", CTRL0BUFF[i] ); + //} + //printf( "\n" ); + } + else + { + } + } + return 0; +} + +int HandleHidNonStandardDataOut( struct _USBState * ctx, uint8_t * data, int len ) +{ + int i; + for( i = 0; i < len; i++ ) + { +// printf( "%02x ", data[i] ); + } +// printf( "\n" ); + printf( "OUT\n" ); + return 0; +} + +void HandleHidNonStandardDataIn( struct _USBState * ctx, uint8_t * data, int len ) +{ + memset( data, 0xcc, len ); +} + + int main() { SystemInit(); @@ -34,7 +83,7 @@ int main() uint32_t * buffer = (uint32_t*)USBFS_GetEPBufferIfAvailable( i ); if( buffer ) { - buffer[0] = 0x000101aa; + buffer[0] = 0x000000aa; USBFS_SendEndpoint( i, (i==1)?8:4 ); } } From 623eda38e256e1347b12696e2180b758d4edf2c6 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Mon, 22 Apr 2024 06:52:36 -0400 Subject: [PATCH 19/31] I am just chasing my tail --- examples_x035/usbdevice.incomplete/usb_config.h | 2 +- examples_x035/usbdevice.incomplete/usbdevice.c | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/examples_x035/usbdevice.incomplete/usb_config.h b/examples_x035/usbdevice.incomplete/usb_config.h index 310d5255..5ed6ce3f 100644 --- a/examples_x035/usbdevice.incomplete/usb_config.h +++ b/examples_x035/usbdevice.incomplete/usb_config.h @@ -6,7 +6,7 @@ #define FUSB_SUPPORTS_SLEEP 0 #define FUSB_HID_INTERFACES 2 #define FUSB_CURSED_TURBO_DMA 1 -#define FUSB_HID_NONSTANDARD 1 +#define FUSB_HID_USER_REPORTS 1 #include "usb_defines.h" diff --git a/examples_x035/usbdevice.incomplete/usbdevice.c b/examples_x035/usbdevice.incomplete/usbdevice.c index 4478a55d..cfaa4f1f 100644 --- a/examples_x035/usbdevice.incomplete/usbdevice.c +++ b/examples_x035/usbdevice.incomplete/usbdevice.c @@ -3,6 +3,7 @@ #include "ch32v003fun.h" #include +#include #include "fsusb.h" uint32_t count; @@ -14,7 +15,7 @@ void handle_debug_input( int numbytes, uint8_t * data ) count += numbytes; } -int HandleHidNonStandardSetup( struct _USBState * ctx, tusb_control_request_t * req ) +int HandleHidUserReportSetup( struct _USBState * ctx, tusb_control_request_t * req ) { /* @@ -45,7 +46,7 @@ int HandleHidNonStandardSetup( struct _USBState * ctx, tusb_control_request_t * return 0; } -int HandleHidNonStandardDataOut( struct _USBState * ctx, uint8_t * data, int len ) +int HandleHidUserReportDataOut( struct _USBState * ctx, uint8_t * data, int len ) { int i; for( i = 0; i < len; i++ ) @@ -57,7 +58,7 @@ int HandleHidNonStandardDataOut( struct _USBState * ctx, uint8_t * data, int len return 0; } -void HandleHidNonStandardDataIn( struct _USBState * ctx, uint8_t * data, int len ) +void HandleHidUserReportDataIn( struct _USBState * ctx, uint8_t * data, int len ) { memset( data, 0xcc, len ); } From c612d10440b19bb01777c409d6ed79e591ed5e6f Mon Sep 17 00:00:00 2001 From: cnlohr Date: Tue, 23 Apr 2024 14:45:15 -0400 Subject: [PATCH 20/31] Cleanup forgot to commit last night --- ch32v003fun/ch32v003fun.c | 27 +- ch32v003fun/ch32v003fun.h | 193 +------------- examples/blink/blink.bin | Bin 564 -> 560 bytes .../usbdevice.incomplete/usbdevice.c | 93 ------- .../Makefile | 3 +- .../fsusb.c | 251 ++++++++++++------ .../fsusb.h | 59 ++-- .../funconfig.h | 0 .../testtop.hidapi}/Makefile | 0 .../testtop.hidapi}/os_generic.h | 0 .../testtop.hidapi}/testtop.c | 2 +- .../testtop.hidapi}/winbuild.bat | 0 .../usb_config.h | 5 +- .../usb_defines.h | 185 +++++++++++++ examples_x035/usbdevice/usbdevice.c | 87 ++++++ 15 files changed, 508 insertions(+), 397 deletions(-) delete mode 100644 examples_x035/usbdevice.incomplete/usbdevice.c rename examples_x035/{usbdevice.incomplete => usbdevice}/Makefile (81%) rename examples_x035/{usbdevice.incomplete => usbdevice}/fsusb.c (71%) rename examples_x035/{usbdevice.incomplete => usbdevice}/fsusb.h (52%) rename examples_x035/{usbdevice.incomplete => usbdevice}/funconfig.h (100%) rename examples_x035/{usbdevice.incomplete/testtop => usbdevice/testtop.hidapi}/Makefile (100%) rename examples_x035/{usbdevice.incomplete/testtop => usbdevice/testtop.hidapi}/os_generic.h (100%) rename examples_x035/{usbdevice.incomplete/testtop => usbdevice/testtop.hidapi}/testtop.c (98%) rename examples_x035/{usbdevice.incomplete/testtop => usbdevice/testtop.hidapi}/winbuild.bat (100%) rename examples_x035/{usbdevice.incomplete => usbdevice}/usb_config.h (98%) rename examples_x035/{usbdevice.incomplete => usbdevice}/usb_defines.h (91%) create mode 100644 examples_x035/usbdevice/usbdevice.c diff --git a/ch32v003fun/ch32v003fun.c b/ch32v003fun/ch32v003fun.c index 5e59a986..c7a75ecc 100644 --- a/ch32v003fun/ch32v003fun.c +++ b/ch32v003fun/ch32v003fun.c @@ -896,7 +896,7 @@ void InterruptVectorDefault() .word NMI_Handler /* NMI Handler */ \n\ .word HardFault_Handler /* Hard Fault Handler */ \n\ .word 0\n" -#if !defined(CH32X03x) +#if defined(CH32X03x) " .word Ecall_M_Mode_Handler /* Ecall M Mode */ \n\ .word 0 \n\ .word 0 \n\ @@ -975,9 +975,17 @@ void handle_reset() ".option arch, +zicsr\n" #endif // Setup the interrupt vector, processor status and INTSYSCR. + +#if FUNCONF_ENABLE_HPE // Enabled nested and hardware (HPE) stack, since it's really good on the x035. +" li t0, 0x88\n\ + csrs mstatus, t0\n" +" li t0, 0x0b\n\ + csrw 0x804, t0\n" +#else " li a0, 0x80\n\ - csrw mstatus, a0\n\ - li a3, 0x3\n\ + csrw mstatus, a0\n" +#endif +" li a3, 0x3\n\ la a0, InterruptVector\n\ or a0, a0, a3\n\ csrw mtvec, a0\n" @@ -1255,14 +1263,19 @@ void handle_reset( void ) asm volatile( " li t0, 0x1f\n\ csrw 0xbc0, t0\n" -#if defined(CH32V20x) || defined(CH32X03x) - // Enabled nested and hardware stack + +//XXX TODO: CHECKME - TEST ON 203!!! +#if FUNCONF_ENABLE_HPE // Enabled nested and hardware (HPE) stack, since it's really good on the x035. " li t0, 0x88\n\ csrs mstatus, t0\n" -#elif defined(CH32V30x) - // Enable nested and hardware stack " li t0, 0x0b\n\ csrw 0x804, t0\n" +#else +" li a0, 0x80\n\ + csrw mstatus, a0\n" +#endif + +#if defined(CH32V30x) // Enable floating point and interrupt " li t0, 0x688\n\ csrs mstatus, t0\n" diff --git a/ch32v003fun/ch32v003fun.h b/ch32v003fun/ch32v003fun.h index 28dd5e5e..6146f89b 100644 --- a/ch32v003fun/ch32v003fun.h +++ b/ch32v003fun/ch32v003fun.h @@ -55,6 +55,7 @@ #define FUNCONF_TINYVECTOR 0 // If enabled, Does not allow normal interrupts. #define FUNCONF_UART_PRINTF_BAUD 115200 // Only used if FUNCONF_USE_UARTPRINTF is set. #define FUNCONF_DEBUGPRINTF_TIMEOUT 160000 // Arbitrary time units +#define FUNCONF_ENABLE_HPE 1 // Enable hardware interrupt stack. Very good on QingKeV4, i.e. x035, v10x, v20x, v30x, but questionable on 003. */ // Sanity check for when porting old code. @@ -101,6 +102,14 @@ #error No PLL on the X03x #endif +#ifndef FUNCONF_ENABLE_HPE + #if defined( CH32V003 ) + #define FUNCONF_ENABLE_HPE 0 + #else + #define FUNCONF_ENABLE_HPE 1 + #endif +#endif + #if !defined( FUNCONF_USE_CLK_SEC ) #define FUNCONF_USE_CLK_SEC 1// use clock security system by default @@ -11548,190 +11557,6 @@ typedef volatile unsigned long *PUINT32V; #define R16_UEP7_T_LEN (*((PUINT16V)(0x4002344c))) // endpoint 7 transmittal length(16-bits for ch32v10x) #define R8_UEP7_CTRL (*((PUINT8V)(0x4002344e))) // endpoint 7 control -/* USB constant and structure define */ - -/* USB PID */ -#ifndef USB_PID_SETUP - #define USB_PID_NULL 0x00 /* reserved PID */ - #define USB_PID_SOF 0x05 - #define USB_PID_SETUP 0x0D - #define USB_PID_IN 0x09 - #define USB_PID_OUT 0x01 - #define USB_PID_ACK 0x02 - #define USB_PID_NAK 0x0A - #define USB_PID_STALL 0x0E - #define USB_PID_DATA0 0x03 - #define USB_PID_DATA1 0x0B - #define USB_PID_PRE 0x0C -#endif - -/* USB standard device request code */ -#ifndef USB_GET_DESCRIPTOR - #define USB_GET_STATUS 0x00 - #define USB_CLEAR_FEATURE 0x01 - #define USB_SET_FEATURE 0x03 - #define USB_SET_ADDRESS 0x05 - #define USB_GET_DESCRIPTOR 0x06 - #define USB_SET_DESCRIPTOR 0x07 - #define USB_GET_CONFIGURATION 0x08 - #define USB_SET_CONFIGURATION 0x09 - #define USB_GET_INTERFACE 0x0A - #define USB_SET_INTERFACE 0x0B - #define USB_SYNCH_FRAME 0x0C -#endif - -/* USB hub class request code */ -#ifndef HUB_GET_DESCRIPTOR - #define HUB_GET_STATUS 0x00 - #define HUB_CLEAR_FEATURE 0x01 - #define HUB_GET_STATE 0x02 - #define HUB_SET_FEATURE 0x03 - #define HUB_GET_DESCRIPTOR 0x06 - #define HUB_SET_DESCRIPTOR 0x07 -#endif - -/* USB HID class request code */ -#ifndef HID_GET_REPORT - #define HID_GET_REPORT 0x01 - #define HID_GET_IDLE 0x02 - #define HID_GET_PROTOCOL 0x03 - #define HID_SET_REPORT 0x09 - #define HID_SET_IDLE 0x0A - #define HID_SET_PROTOCOL 0x0B -#endif - -/* USB CDC Class request code */ -#ifndef CDC_GET_LINE_CODING -#define CDC_GET_LINE_CODING 0X21 /* This request allows the host to find out the currently configured line coding */ -#define CDC_SET_LINE_CODING 0x20 /* Configures DTE rate, stop-bits, parity, and number-of-character */ -#define CDC_SET_LINE_CTLSTE 0X22 /* This request generates RS-232/V.24 style control signals */ -#define CDC_SEND_BREAK 0X23 /* Sends special carrier modulation used to specify RS-232 style break */ -#endif - -/* 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 */ - #define USB_REQ_RECIP_DEVICE 0x00 - #define USB_REQ_RECIP_INTERF 0x01 - #define USB_REQ_RECIP_ENDP 0x02 - #define USB_REQ_RECIP_OTHER 0x03 - #define USB_REQ_FEAT_REMOTE_WAKEUP 0x01 - #define USB_REQ_FEAT_ENDP_HALT 0x00 -#endif - -/* USB request type for hub class request */ -#ifndef HUB_GET_HUB_DESCRIPTOR - #define HUB_CLEAR_HUB_FEATURE 0x20 - #define HUB_CLEAR_PORT_FEATURE 0x23 - #define HUB_GET_BUS_STATE 0xA3 - #define HUB_GET_HUB_DESCRIPTOR 0xA0 - #define HUB_GET_HUB_STATUS 0xA0 - #define HUB_GET_PORT_STATUS 0xA3 - #define HUB_SET_HUB_DESCRIPTOR 0x20 - #define HUB_SET_HUB_FEATURE 0x20 - #define HUB_SET_PORT_FEATURE 0x23 -#endif - -/* Hub class feature selectors */ -#ifndef HUB_PORT_RESET - #define HUB_C_HUB_LOCAL_POWER 0 - #define HUB_C_HUB_OVER_CURRENT 1 - #define HUB_PORT_CONNECTION 0 - #define HUB_PORT_ENABLE 1 - #define HUB_PORT_SUSPEND 2 - #define HUB_PORT_OVER_CURRENT 3 - #define HUB_PORT_RESET 4 - #define HUB_PORT_POWER 8 - #define HUB_PORT_LOW_SPEED 9 - #define HUB_C_PORT_CONNECTION 16 - #define HUB_C_PORT_ENABLE 17 - #define HUB_C_PORT_SUSPEND 18 - #define HUB_C_PORT_OVER_CURRENT 19 - #define HUB_C_PORT_RESET 20 -#endif - -/* USB 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 -#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_IMAGE 0x06 - #define USB_DEV_CLASS_PRINTER 0x07 - #define USB_DEV_CLASS_STORAGE 0x08 - #define USB_DEV_CLASS_HUB 0x09 - #define USB_DEV_CLASS_VEN_SPEC 0xFF -#endif - -/* USB 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 -#endif - -#ifndef USB_DEVICE_ADDR - #define USB_DEVICE_ADDR 0x02 -#endif -#ifndef DEFAULT_ENDP0_SIZE - #define DEFAULT_ENDP0_SIZE 8 /* default maximum packet size for endpoint 0 */ -#endif -#ifndef MAX_PACKET_SIZE - #define MAX_PACKET_SIZE 64 /* maximum packet size */ -#endif -#ifndef USB_BO_CBW_SIZE - #define USB_BO_CBW_SIZE 0x1F - #define USB_BO_CSW_SIZE 0x0D -#endif -#ifndef USB_BO_CBW_SIG0 - #define USB_BO_CBW_SIG0 0x55 - #define USB_BO_CBW_SIG1 0x53 - #define USB_BO_CBW_SIG2 0x42 - #define USB_BO_CBW_SIG3 0x43 - #define USB_BO_CSW_SIG0 0x55 - #define USB_BO_CSW_SIG1 0x53 - #define USB_BO_CSW_SIG2 0x42 - #define USB_BO_CSW_SIG3 0x53 -#endif - -#define DEF_STRING_DESC_LANG 0x00 -#define DEF_STRING_DESC_MANU 0x01 -#define DEF_STRING_DESC_PROD 0x02 -#define DEF_STRING_DESC_SERN 0x03 - /* ch32v10x_usb_host.h -----------------------------------------------------------*/ #define ERR_SUCCESS 0x00 diff --git a/examples/blink/blink.bin b/examples/blink/blink.bin index c4ae5e0476d01db8c9adede2e3af224eff6ec4c4..23614187313a10492587efeb0091524a302f18e1 100755 GIT binary patch delta 257 zcmdnOvVmp76Gn!KPqi5pCJQo3>8dk1u)5DUyj`5h!JM6gQF#$NgD|@|$Be_~?DH9B z9N*5yz+?`TlX3pq|MmXl2u7KDKq5UvE(2|dT#Y+2uG$TZG zhV%AkVhoep*vue0XB?i)&gNkLo#BD9?TT~;B6Gn%LPqi5jOcrF6(iLZNFlXmrR9?i+Aj~e#G2?Kno4GoZgUDfX_W2Am zj++DJWt=BZOJ{g|m+jx=2u7Lu$?fg@$_v;TwzD%lnB4BpFU-yW)YjAxD9Cms(;lqB z-<<8^|5~xh&%>Ez&TkiIbeP=E?l8l7yBMQ`xhSK9<80w{afTU(XE?JuA9O10cT5ZH z2l33=7(UjD74`#ZMzDwzROO-V&%_wazXR=SV{ -#include -#include "fsusb.h" - -uint32_t count; - -int last = 0; -void handle_debug_input( int numbytes, uint8_t * data ) -{ - last = data[0]; - count += numbytes; -} - -int HandleHidUserReportSetup( struct _USBState * ctx, tusb_control_request_t * req ) -{ - -/* - int USBFS_SetupReqType = FSUSBCTX.USBFS_SetupReqType = pUSBFS_SetupReqPak->bmRequestType; - int USBFS_SetupReqCode = FSUSBCTX.USBFS_SetupReqCode = pUSBFS_SetupReqPak->bRequest; - int USBFS_SetupReqLen = FSUSBCTX.USBFS_SetupReqLen = pUSBFS_SetupReqPak->wLength; - int USBFS_SetupReqIndex = pUSBFS_SetupReqPak->wIndex; - int USBFS_IndexValue = FSUSBCTX.USBFS_IndexValue = ( pUSBFS_SetupReqPak->wIndex << 16 ) | pUSBFS_SetupReqPak->wValue; - len = 0; - USBDEBUG1++; -*/ - int id = req->wValue & 0xff; - if( id == 0xaa ) - { - if( req->bRequest == HID_REQ_CONTROL_SET_REPORT ) - { - //int i; - //for( i = 0; i < 64; i++ ) - //{ - // printf( "%02x ", CTRL0BUFF[i] ); - //} - //printf( "\n" ); - } - else - { - } - } - return 0; -} - -int HandleHidUserReportDataOut( struct _USBState * ctx, uint8_t * data, int len ) -{ - int i; - for( i = 0; i < len; i++ ) - { -// printf( "%02x ", data[i] ); - } -// printf( "\n" ); - printf( "OUT\n" ); - return 0; -} - -void HandleHidUserReportDataIn( struct _USBState * ctx, uint8_t * data, int len ) -{ - memset( data, 0xcc, len ); -} - - -int main() -{ - SystemInit(); - - funGpioInitAll(); - - funPinMode( PA0, GPIO_CFGLR_OUT_10Mhz_PP ); - - FSUSBSetup(); - - while(1) - { - printf( "%lu %08lx %lu %d %d\n", USBDEBUG0, USBDEBUG1, USBDEBUG2, 0, 0 ); - int i; - for( i = 1; i < 3; i++ ) - { - - uint32_t * buffer = (uint32_t*)USBFS_GetEPBufferIfAvailable( i ); - if( buffer ) - { - buffer[0] = 0x000000aa; - USBFS_SendEndpoint( i, (i==1)?8:4 ); - } - } - } -} - diff --git a/examples_x035/usbdevice.incomplete/Makefile b/examples_x035/usbdevice/Makefile similarity index 81% rename from examples_x035/usbdevice.incomplete/Makefile rename to examples_x035/usbdevice/Makefile index e28de11d..27b389bc 100644 --- a/examples_x035/usbdevice.incomplete/Makefile +++ b/examples_x035/usbdevice/Makefile @@ -2,8 +2,7 @@ all : flash TARGET:=usbdevice TARGET_MCU:=CH32X035 -ADDITIONAL_C_FILES:=fsusb.c - +ADDITIONAL_C_FILES:= include ../../ch32v003fun/ch32v003fun.mk flash : cv_flash diff --git a/examples_x035/usbdevice.incomplete/fsusb.c b/examples_x035/usbdevice/fsusb.c similarity index 71% rename from examples_x035/usbdevice.incomplete/fsusb.c rename to examples_x035/usbdevice/fsusb.c index 4c43708b..c67dfb4a 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.c +++ b/examples_x035/usbdevice/fsusb.c @@ -30,29 +30,9 @@ struct _USBState FSUSBCTX; #define CUIS_TOKEN_IN 0x2 #define CUIS_TOKEN_SETUP 0x3 -#if 0 -static inline void fastcopy( uint8_t * dest, const uint8_t * src, int len ) -{ - src = ((intptr_t)src) & ~3; - asm volatile( "\ - add a3, %[src], %[len]\n\ -1:\n\ - lw a4, 0(%[src])\n\ - lw a5, 4(%[src])\n\ - lw s1, 8(%[src])\n\ - lw s2, 12(%[src])\n\ - addi %[src],%[src],16\n\ - sw a4, 0(%[dest])\n\ - sw a5, 4(%[dest])\n\ - sw s1, 8(%[dest])\n\ - sw s2, 12(%[dest])\n\ - addi %[dest],%[dest],16\n\ - bgtu a3,%[src],1b\n\ - " : [dest]"+r"(dest), [src]"+r"(src) : [len]"r"(len) : "memory", "a3", "a4", "a5", "s1", "s2" ); -} -#else -static inline void fastcopy( uint8_t * dest, const uint8_t * src, int len ) +static inline void DMA7FastCopy( uint8_t * dest, const uint8_t * src, int len ) { + while( DMA1_Channel7->CNTR ); DMA1_Channel7->CFGR = 0; DMA1_Channel7->MADDR = (uintptr_t)src; DMA1_Channel7->PADDR = (uintptr_t)dest; @@ -66,26 +46,35 @@ static inline void fastcopy( uint8_t * dest, const uint8_t * src, int len ) DMA_MemoryInc_Enable | DMA_PeripheralInc_Enable | DMA_Mode_Normal | DMA_CFGR1_EN; - //XXX TODO: Somehow, it seems to work (unsafely) without this. #if !( FUSB_CURSED_TURBO_DMA == 1 ) + // Somehow, it seems to work (unsafely) without this. + // Really, though, it's probably fine. while( DMA1_Channel7->CNTR ); #endif - } -#endif -void USBFS_IRQHandler() __attribute__((section(".text.vector_handler"))) __attribute__((interrupt)); +static inline void DMA7FastCopyComplete() { while( DMA1_Channel7->CNTR ); } + +#if FUSB_USE_HPE +void USBFS_IRQHandler() __attribute__((section(".text.vector_handler"))) __attribute((naked)); +#else +void USBFS_IRQHandler() __attribute__((section(".text.vector_handler"))) __attribute((interrupt)); +#endif void USBFS_InternalFinishSetup(); void USBFS_IRQHandler() { +#if FUSB_IO_PROFILE + GPIOA->BSHR = 1; +#endif + // Based on https://github.com/openwch/ch32x035/blob/main/EVT/EXAM/USB/USBFS/DEVICE/CompositeKM/User/ch32x035_usbfs_device.c // Combined FG + ST flag. uint16_t intfgst = *(uint16_t*)(&USBFS->INT_FG); int len = 0; struct _USBState * ctx = &FSUSBCTX; - GPIOA->BSHR = 1; + uint8_t * ctrl0buff = CTRL0BUFF; // TODO: Check if needs to be do-while to re-check. if( intfgst & CRB_UIF_TRANSFER ) @@ -113,22 +102,40 @@ void USBFS_IRQHandler() USBFS->UEP0_CTRL_H = USBFS_UEP_R_TOG | USBFS_UEP_R_RES_ACK; } - if ( ( ctx->USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) + if( ctx->pCtrlPayloadPtr ) + { + // Shortcut mechanism, for descriptors or if the user wants it. + len = ctx->USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : ctx->USBFS_SetupReqLen; + DMA7FastCopy( ctrl0buff, ctx->pCtrlPayloadPtr, len ); // FYI -> Would need to do this if using DMA + ctx->USBFS_SetupReqLen -= len; + if( ctx->USBFS_SetupReqLen > 0 ) + ctx->pCtrlPayloadPtr += len; + else + ctx->pCtrlPayloadPtr = 0; + + USBFS->UEP0_TX_LEN = len; + USBFS->UEP0_CTRL_H ^= USBFS_UEP_T_TOG; + } + else if ( ( ctx->USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) { - // Handle other control requests here. + +#if FUSB_HID_USER_REPORTS + len = ctx->USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : ctx->USBFS_SetupReqLen; + if( len && FSUSBCTX.USBFS_SetupReqCode == HID_GET_REPORT ) + { + len = HandleHidUserReportDataIn( ctx, ctrl0buff, len ); + USBFS->UEP0_TX_LEN = len; + USBFS->UEP0_CTRL_H ^= USBFS_UEP_T_TOG; + ctx->USBFS_SetupReqLen -= len; + ctx->pCtrlPayloadPtr += len; + } +#endif } else { switch( FSUSBCTX.USBFS_SetupReqCode ) { case USB_GET_DESCRIPTOR: - len = ctx->USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : ctx->USBFS_SetupReqLen; - //memcpy( CTRL0BUFF, ctx->pUSBFS_Descr, len ); // FYI -> IS IT POSSIBLE TO DO THIS WITH DMA???? - fastcopy( CTRL0BUFF, ctx->pUSBFS_Descr, len ); // FYI -> Would need to do this if using DMA - USBFS->UEP0_TX_LEN = len; - USBFS->UEP0_CTRL_H ^= USBFS_UEP_T_TOG; - ctx->USBFS_SetupReqLen -= len; - ctx->pUSBFS_Descr += len; break; case USB_SET_ADDRESS: @@ -136,17 +143,6 @@ void USBFS_IRQHandler() break; default: -#if FUSB_HID_USER_REPORTS - len = ctx->USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : ctx->USBFS_SetupReqLen; - if( len ) - { - HandleHidUserReportDataIn( ctx, CTRL0BUFF, len ); - USBFS->UEP0_TX_LEN = len; - USBFS->UEP0_CTRL_H ^= USBFS_UEP_T_TOG; - ctx->USBFS_SetupReqLen -= len; - ctx->pUSBFS_Descr += len; - } -#endif break; } } @@ -161,20 +157,42 @@ void USBFS_IRQHandler() case DEF_UEP0: if( intfgst & CRB_UIS_TOG_OK ) { - #if FUSB_HID_USER_REPORTS - int r = HandleHidUserReportDataOut( ctx, CTRL0BUFF, USBFS->RX_LEN ); - if( r >= 0 ) + int len = USBFS->RX_LEN; + uint8_t * cptr = ctx->pCtrlPayloadPtr; + if( !cptr ) { - USBFS->UEP0_TX_LEN = r; - USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK; + HandleHidUserReportDataOut( ctx, ctrl0buff, len ); } else + { + int remain = ctx->USBFS_SetupReqLen - len; + if( remain < 0 ) + { + len += remain; + remain = 0; + } + DMA7FastCopy( cptr, ctrl0buff, len ); + ctx->USBFS_SetupReqLen = remain; + if( remain > 0 ) + ctx->pCtrlPayloadPtr = cptr + len; + else + ctx->pCtrlPayloadPtr = 0; + } #endif - if( FSUSBCTX.USBFS_SetupReqLen == 0 ) + + if( ctx->USBFS_SetupReqLen == 0 ) { - USBFS->UEP0_TX_LEN = 0; + USBFS->UEP0_TX_LEN = 0; USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK; +#if FUSB_HID_USER_REPORTS + DMA7FastCopyComplete(); + HandleHidUserReportOutComplete( ctx ); +#endif + } + else + { + USBFS->UEP0_CTRL_H ^= USBFS_UEP_R_TOG; } } break; @@ -186,22 +204,19 @@ void USBFS_IRQHandler() /* Setup stage processing */ case CUIS_TOKEN_SETUP: + USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG|USBFS_UEP_T_RES_NAK|USBFS_UEP_R_TOG|USBFS_UEP_R_RES_NAK; /* Store All Setup Values */ int USBFS_SetupReqType = FSUSBCTX.USBFS_SetupReqType = pUSBFS_SetupReqPak->bmRequestType; int USBFS_SetupReqCode = FSUSBCTX.USBFS_SetupReqCode = pUSBFS_SetupReqPak->bRequest; - int USBFS_SetupReqLen = FSUSBCTX.USBFS_SetupReqLen = pUSBFS_SetupReqPak->wLength; + int USBFS_SetupReqLen = FSUSBCTX.USBFS_SetupReqLen = pUSBFS_SetupReqPak->wLength; int USBFS_SetupReqIndex = pUSBFS_SetupReqPak->wIndex; int USBFS_IndexValue = FSUSBCTX.USBFS_IndexValue = ( pUSBFS_SetupReqPak->wIndex << 16 ) | pUSBFS_SetupReqPak->wValue; len = 0; if( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD ) { -#if FUSB_HID_USER_REPORTS - len = HandleHidUserReportSetup( ctx, pUSBFS_SetupReqPak ); - if( len < 0 ) goto sendstall; -#endif #if FUSB_HID_INTERFACES > 0 if( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) == USB_REQ_TYP_CLASS ) { @@ -209,8 +224,36 @@ void USBFS_IRQHandler() switch( USBFS_SetupReqCode ) { case HID_SET_REPORT: +#if FUSB_HID_USER_REPORTS + len = HandleHidUserSetReportSetup( ctx, pUSBFS_SetupReqPak ); + if( len < 0 ) goto sendstall; + ctx->USBFS_SetupReqLen = len; + USBFS->UEP0_TX_LEN = 0; + USBFS->UEP0_CTRL_H = USBFS_UEP_R_TOG | USBFS_UEP_R_RES_ACK | USBFS_UEP_T_TOG; + goto replycomplete; + case HID_GET_REPORT: + len = HandleHidUserGetReportSetup( ctx, pUSBFS_SetupReqPak ); + len = 255; + if( len < 0 ) goto sendstall; + ctx->USBFS_SetupReqLen = len; + len = len >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : len; + if( !ctx->pCtrlPayloadPtr ) + { + len = HandleHidUserReportDataIn( ctx, ctrl0buff, len ); + } + else + { + DMA7FastCopy( ctrl0buff, ctx->pCtrlPayloadPtr, len ); + ctx->pCtrlPayloadPtr += len; + } + USBFS->UEP0_TX_LEN = len; + USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK; + ctx->USBFS_SetupReqLen -= len; + goto replycomplete; +#endif break; + case HID_SET_IDLE: if( USBFS_SetupReqIndex < FUSB_HID_INTERFACES ) FSUSBCTX.USBFS_HidIdle[ USBFS_SetupReqIndex ] = (uint8_t)( USBFS_IndexValue >> 8 ); @@ -223,7 +266,7 @@ void USBFS_IRQHandler() case HID_GET_IDLE: if( USBFS_SetupReqIndex < FUSB_HID_INTERFACES ) { - CTRL0BUFF[0] = FSUSBCTX.USBFS_HidIdle[ USBFS_SetupReqIndex ]; + ctrl0buff[0] = FSUSBCTX.USBFS_HidIdle[ USBFS_SetupReqIndex ]; len = 1; } break; @@ -231,7 +274,7 @@ void USBFS_IRQHandler() case HID_GET_PROTOCOL: if( USBFS_SetupReqIndex < FUSB_HID_INTERFACES ) { - CTRL0BUFF[0] = FSUSBCTX.USBFS_HidProtocol[ USBFS_SetupReqIndex ]; + ctrl0buff[0] = FSUSBCTX.USBFS_HidProtocol[ USBFS_SetupReqIndex ]; len = 1; } break; @@ -241,6 +284,8 @@ void USBFS_IRQHandler() break; } } +#else + ; #endif } else @@ -257,7 +302,7 @@ void USBFS_IRQHandler() { if( e->lIndexValue == USBFS_IndexValue ) { - ctx->pUSBFS_Descr = e->addr; + ctx->pCtrlPayloadPtr = (uint8_t*)e->addr; len = e->length; break; } @@ -267,18 +312,20 @@ void USBFS_IRQHandler() goto sendstall; } + /* Copy Descriptors to Endp0 DMA buffer */ - if( USBFS_SetupReqLen > len ) + int totalLen = USBFS_SetupReqLen; + if( totalLen > len ) { - USBFS_SetupReqLen = len; + totalLen = len; } - len = ( USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ) ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen; - fastcopy( CTRL0BUFF, ctx->pUSBFS_Descr, len ); //memcpy( CTRL0BUFF, ctx->pUSBFS_Descr, len ); + len = ( totalLen >= DEF_USBD_UEP0_SIZE ) ? DEF_USBD_UEP0_SIZE : totalLen; + DMA7FastCopy( ctrl0buff, ctx->pCtrlPayloadPtr, len ); //memcpy( CTRL0BUFF, ctx->pCtrlPayloadPtr, len ); + ctx->USBFS_SetupReqLen = totalLen - len; + ctx->pCtrlPayloadPtr += len; USBFS->UEP0_TX_LEN = len; USBFS->UEP0_CTRL_H = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK; - ctx->pUSBFS_Descr += len; goto replycomplete; - break; } /* Set usb address */ @@ -288,7 +335,7 @@ void USBFS_IRQHandler() /* Get usb configuration now set */ case USB_GET_CONFIGURATION: - CTRL0BUFF[0] = ctx->USBFS_DevConfig; + ctrl0buff[0] = ctx->USBFS_DevConfig; if( ctx->USBFS_SetupReqLen > 1 ) ctx->USBFS_SetupReqLen = 1; break; @@ -376,7 +423,7 @@ void USBFS_IRQHandler() /* This request allows the host to select another setting for the specified interface */ case USB_GET_INTERFACE: - CTRL0BUFF[0] = 0x00; + ctrl0buff[0] = 0x00; if( USBFS_SetupReqLen > 1 ) USBFS_SetupReqLen = 1; break; @@ -385,20 +432,20 @@ void USBFS_IRQHandler() /* host get status of specified device/interface/end-points */ case USB_GET_STATUS: - CTRL0BUFF[0] = 0x00; - CTRL0BUFF[1] = 0x00; + ctrl0buff[0] = 0x00; + ctrl0buff[1] = 0x00; if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE ) { #if FUSB_SUPPORTS_SLEEP - CTRL0BUFF[0] = (ctx->USBFS_DevSleepStatus & 0x01)<<1; + ctrl0buff[0] = (ctx->USBFS_DevSleepStatus & 0x01)<<1; #else - CTRL0BUFF[0] = 0x00; + ctrl0buff[0] = 0x00; #endif } else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP ) { if( ( USBFS_SetupReqIndex & DEF_UEP_IN ) && ep < FUSB_CONFIG_EPS ) - CTRL0BUFF[0] = ( UEP_CTRL_H(ep) & USBFS_UEP_T_RES_MASK ) == USBFS_UEP_T_RES_STALL; + ctrl0buff[0] = ( UEP_CTRL_H(ep) & USBFS_UEP_T_RES_MASK ) == USBFS_UEP_T_RES_STALL; else goto sendstall; } @@ -489,19 +536,51 @@ void USBFS_IRQHandler() // Handle any other interrupts and just clear them out. *(uint16_t*)(&USBFS->INT_FG) = intfgst; - //intfgst = *(uint16_t*)(&USBFS->INT_FG); +#if FUSB_IO_PROFILE GPIOA->BSHR = 1<<16; +#endif + +#if FUSB_USE_HPE + asm volatile( "mret" ); +#endif } void USBFS_InternalFinishSetup() { - USBFS->UEP4_1_MOD = RB_UEP1_TX_EN; +#if FUSB_CONFIG_EPS > 4 + USBFS->UEP4_1_MOD = RB_UEP1_TX_EN | RB_UEP4_TX_EN; +#elif FUSB_CONFIG_EPS > 1 + USBFS->UEP4_1_MOD = RB_UEP1_TX_EN | RB_UEP4_TX_EN; +#endif + +#if FUSB_CONFIG_EPS > 3 + USBFS->UEP2_3_MOD = RB_UEP2_TX_EN | RB_UEP3_TX_EN; +#elif FUSB_CONFIG_EPS > 2 USBFS->UEP2_3_MOD = RB_UEP2_TX_EN; +#endif + USBFS->UEP567_MOD = 0; // This is really cursed. Somehow it doesn't explode. // But, normally the USB wants a separate buffer here. - USBFS->UEP0_DMA = (uintptr_t)CTRL0BUFF; + +#if FUSB_CONFIG_EPS > 4 + USBFS->UEP4_DMA = (uintptr_t)FSUSBCTX.ENDPOINTS[4]; +#endif +#if FUSB_CONFIG_EPS > 3 + USBFS->UEP3_DMA = (uintptr_t)FSUSBCTX.ENDPOINTS[3]; +#endif +#if FUSB_CONFIG_EPS > 2 + USBFS->UEP2_DMA = (uintptr_t)FSUSBCTX.ENDPOINTS[2]; +#endif +#if FUSB_CONFIG_EPS > 1 + USBFS->UEP1_DMA = (uintptr_t)FSUSBCTX.ENDPOINTS[1]; +#endif +#if FUSB_CONFIG_EPS > 0 + USBFS->UEP0_DMA = (uintptr_t)FSUSBCTX.ENDPOINTS[0]; +#else +#error You must have at least EP0! +#endif UEP_CTRL_H(0) = USBFS_UEP_R_RES_ACK | USBFS_UEP_T_RES_NAK; int i; @@ -572,5 +651,21 @@ int FSUSBSetup() return 0; } +// To TX, you can use USBFS_GetEPBufferIfAvailable or USBFSD_UEP_DMA( endp ) + +static inline uint8_t * USBFS_GetEPBufferIfAvailable( int endp ) +{ + if( FSUSBCTX.USBFS_Endp_Busy[ endp ] ) return 0; + return USBFSD_UEP_BUF( endp ); +} + +static inline void USBFS_SendEndpoint( int endp, int len ) +{ + USBFSD_UEP_TLEN( endp ) = len; + USBFSD_UEP_TX_CTRL( endp ) = ( USBFSD_UEP_TX_CTRL( endp ) & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_ACK; + FSUSBCTX.USBFS_Endp_Busy[ endp ] = 0x01; +} + + diff --git a/examples_x035/usbdevice.incomplete/fsusb.h b/examples_x035/usbdevice/fsusb.h similarity index 52% rename from examples_x035/usbdevice.incomplete/fsusb.h rename to examples_x035/usbdevice/fsusb.h index 3eb4f21f..8533b836 100644 --- a/examples_x035/usbdevice.incomplete/fsusb.h +++ b/examples_x035/usbdevice/fsusb.h @@ -27,18 +27,27 @@ extern uint32_t USBDEBUG0, USBDEBUG1, USBDEBUG2; struct _USBState; +// Provided functions: int FSUSBSetup(); uint8_t USBFS_Endp_DataUp(uint8_t endp, const uint8_t *pbuf, uint16_t len, uint8_t mod); - static inline uint8_t * USBFS_GetEPBufferIfAvailable( int endp ); static inline void USBFS_SendEndpoint( int endp, int len ); +static inline uint8_t * USBFS_GetEPBufferIfAvailable( int endp ); +static inline void USBFS_SendEndpoint( int endp, int len ); + +static inline void DMA7FastCopy( uint8_t * dest, const uint8_t * src, int len ); +static inline void DMA7FastCopyComplete(); + + // Implement the following: -#if FUSB_HID_NONSTANDARD -int HandleHidUserReportSetup( struct _USBState * ctx, tusb_control_request_t * req ); -int HandleHidUserReportOut( struct _USBState * ctx, uint8_t * data, int len ); -void HandleHidUserReportIn( struct _USBState * ctx, uint8_t * data, int len ); +#if FUSB_HID_USER_REPORTS +int HandleHidUserGetReportSetup( struct _USBState * ctx, tusb_control_request_t * req ); +int HandleHidUserSetReportSetup( struct _USBState * ctx, tusb_control_request_t * req ); +void HandleHidUserReportDataOut( struct _USBState * ctx, uint8_t * data, int len ); +int HandleHidUserReportDataIn( struct _USBState * ctx, uint8_t * data, int len ); +void HandleHidUserReportOutComplete( struct _USBState * ctx ); #endif @@ -47,45 +56,35 @@ void HandleHidUserReportIn( struct _USBState * ctx, uint8_t * data, int len ); struct _USBState { // Setup Request - volatile uint8_t USBFS_SetupReqCode; - volatile uint8_t USBFS_SetupReqType; - volatile uint16_t USBFS_SetupReqLen; - volatile uint32_t USBFS_IndexValue; + uint8_t USBFS_SetupReqCode; + uint8_t USBFS_SetupReqType; + uint16_t USBFS_SetupReqLen; // Used for tracking place along send. + uint32_t USBFS_IndexValue; // USB Device Status - volatile uint8_t USBFS_DevConfig; - volatile uint8_t USBFS_DevAddr; - volatile uint8_t USBFS_DevSleepStatus; - volatile uint8_t USBFS_DevEnumStatus; + uint8_t USBFS_DevConfig; + uint8_t USBFS_DevAddr; + uint8_t USBFS_DevSleepStatus; + uint8_t USBFS_DevEnumStatus; - #define pUSBFS_SetupReqPak ((tusb_control_request_t*)USBFSD_UEP_BUF(0)) - #define CTRL0BUFF USBFSD_UEP_BUF(0) + uint8_t * pCtrlPayloadPtr; + + uint8_t ENDPOINTS[FUSB_CONFIG_EPS][64]; + + #define CTRL0BUFF (FSUSBCTX.ENDPOINTS[0]) + #define pUSBFS_SetupReqPak ((tusb_control_request_t*)CTRL0BUFF) #if FUSB_HID_INTERFACES > 0 uint8_t USBFS_HidIdle[FUSB_HID_INTERFACES]; uint8_t USBFS_HidProtocol[FUSB_HID_INTERFACES]; #endif - volatile uint8_t USBFS_Endp_Busy[FUSB_CONFIG_EPS]; - const uint8_t *pUSBFS_Descr; }; extern struct _USBState FSUSBCTX; -// To TX, you can use USBFS_GetEPBufferIfAvailable or USBFSD_UEP_DMA( endp ) -static inline uint8_t * USBFS_GetEPBufferIfAvailable( int endp ) -{ - if( FSUSBCTX.USBFS_Endp_Busy[ endp ] ) return 0; - return USBFSD_UEP_BUF( endp ); -} - -static inline void USBFS_SendEndpoint( int endp, int len ) -{ - USBFSD_UEP_TLEN( endp ) = len; - USBFSD_UEP_TX_CTRL( endp ) = ( USBFSD_UEP_TX_CTRL( endp ) & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_ACK; - FSUSBCTX.USBFS_Endp_Busy[ endp ] = 0x01; -} +#include "fsusb.c" #endif diff --git a/examples_x035/usbdevice.incomplete/funconfig.h b/examples_x035/usbdevice/funconfig.h similarity index 100% rename from examples_x035/usbdevice.incomplete/funconfig.h rename to examples_x035/usbdevice/funconfig.h diff --git a/examples_x035/usbdevice.incomplete/testtop/Makefile b/examples_x035/usbdevice/testtop.hidapi/Makefile similarity index 100% rename from examples_x035/usbdevice.incomplete/testtop/Makefile rename to examples_x035/usbdevice/testtop.hidapi/Makefile diff --git a/examples_x035/usbdevice.incomplete/testtop/os_generic.h b/examples_x035/usbdevice/testtop.hidapi/os_generic.h similarity index 100% rename from examples_x035/usbdevice.incomplete/testtop/os_generic.h rename to examples_x035/usbdevice/testtop.hidapi/os_generic.h diff --git a/examples_x035/usbdevice.incomplete/testtop/testtop.c b/examples_x035/usbdevice/testtop.hidapi/testtop.c similarity index 98% rename from examples_x035/usbdevice.incomplete/testtop/testtop.c rename to examples_x035/usbdevice/testtop.hidapi/testtop.c index 87f8ef8b..3ceb7ec1 100644 --- a/examples_x035/usbdevice.incomplete/testtop/testtop.c +++ b/examples_x035/usbdevice/testtop.hidapi/testtop.c @@ -38,7 +38,7 @@ int main() // But we can fill in random for the rest. for( i = 1; i < sizeof( buffer0 ); i ++ ) - buffer0[i] = 0xbb;//rand(); + buffer0[i] = i;//rand(); if( buffer0[1] == 0xa4 ) buffer0[1]++; diff --git a/examples_x035/usbdevice.incomplete/testtop/winbuild.bat b/examples_x035/usbdevice/testtop.hidapi/winbuild.bat similarity index 100% rename from examples_x035/usbdevice.incomplete/testtop/winbuild.bat rename to examples_x035/usbdevice/testtop.hidapi/winbuild.bat diff --git a/examples_x035/usbdevice.incomplete/usb_config.h b/examples_x035/usbdevice/usb_config.h similarity index 98% rename from examples_x035/usbdevice.incomplete/usb_config.h rename to examples_x035/usbdevice/usb_config.h index 5ed6ce3f..82800e46 100644 --- a/examples_x035/usbdevice.incomplete/usb_config.h +++ b/examples_x035/usbdevice/usb_config.h @@ -5,9 +5,10 @@ #define FUSB_CONFIG_EPS 3 // Include EP0 in this count #define FUSB_SUPPORTS_SLEEP 0 #define FUSB_HID_INTERFACES 2 -#define FUSB_CURSED_TURBO_DMA 1 +#define FUSB_CURSED_TURBO_DMA 0 // Hacky, but seems fine, shaves 2.5us off filling 64-byte buffers. #define FUSB_HID_USER_REPORTS 1 - +#define FUSB_USE_HPE 1 // Use hardware stack. +#define FUSB_IO_PROFILE 1 #include "usb_defines.h" diff --git a/examples_x035/usbdevice.incomplete/usb_defines.h b/examples_x035/usbdevice/usb_defines.h similarity index 91% rename from examples_x035/usbdevice.incomplete/usb_defines.h rename to examples_x035/usbdevice/usb_defines.h index 3abf670c..02d8f456 100644 --- a/examples_x035/usbdevice.incomplete/usb_defines.h +++ b/examples_x035/usbdevice/usb_defines.h @@ -557,6 +557,191 @@ static inline uint8_t tu_desc_len(void const* desc) #define TU_BIT( x ) (1<<(x)) #endif +/* USB constant and structure define */ + +/* USB PID */ +#ifndef USB_PID_SETUP + #define USB_PID_NULL 0x00 /* reserved PID */ + #define USB_PID_SOF 0x05 + #define USB_PID_SETUP 0x0D + #define USB_PID_IN 0x09 + #define USB_PID_OUT 0x01 + #define USB_PID_ACK 0x02 + #define USB_PID_NAK 0x0A + #define USB_PID_STALL 0x0E + #define USB_PID_DATA0 0x03 + #define USB_PID_DATA1 0x0B + #define USB_PID_PRE 0x0C +#endif + +/* USB standard device request code */ +#ifndef USB_GET_DESCRIPTOR + #define USB_GET_STATUS 0x00 + #define USB_CLEAR_FEATURE 0x01 + #define USB_SET_FEATURE 0x03 + #define USB_SET_ADDRESS 0x05 + #define USB_GET_DESCRIPTOR 0x06 + #define USB_SET_DESCRIPTOR 0x07 + #define USB_GET_CONFIGURATION 0x08 + #define USB_SET_CONFIGURATION 0x09 + #define USB_GET_INTERFACE 0x0A + #define USB_SET_INTERFACE 0x0B + #define USB_SYNCH_FRAME 0x0C +#endif + +/* USB hub class request code */ +#ifndef HUB_GET_DESCRIPTOR + #define HUB_GET_STATUS 0x00 + #define HUB_CLEAR_FEATURE 0x01 + #define HUB_GET_STATE 0x02 + #define HUB_SET_FEATURE 0x03 + #define HUB_GET_DESCRIPTOR 0x06 + #define HUB_SET_DESCRIPTOR 0x07 +#endif + +/* USB HID class request code */ +#ifndef HID_GET_REPORT + #define HID_GET_REPORT 0x01 + #define HID_GET_IDLE 0x02 + #define HID_GET_PROTOCOL 0x03 + #define HID_SET_REPORT 0x09 + #define HID_SET_IDLE 0x0A + #define HID_SET_PROTOCOL 0x0B +#endif + +/* USB CDC Class request code */ +#ifndef CDC_GET_LINE_CODING +#define CDC_GET_LINE_CODING 0X21 /* This request allows the host to find out the currently configured line coding */ +#define CDC_SET_LINE_CODING 0x20 /* Configures DTE rate, stop-bits, parity, and number-of-character */ +#define CDC_SET_LINE_CTLSTE 0X22 /* This request generates RS-232/V.24 style control signals */ +#define CDC_SEND_BREAK 0X23 /* Sends special carrier modulation used to specify RS-232 style break */ +#endif + +/* 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 */ + #define USB_REQ_RECIP_DEVICE 0x00 + #define USB_REQ_RECIP_INTERF 0x01 + #define USB_REQ_RECIP_ENDP 0x02 + #define USB_REQ_RECIP_OTHER 0x03 + #define USB_REQ_FEAT_REMOTE_WAKEUP 0x01 + #define USB_REQ_FEAT_ENDP_HALT 0x00 +#endif + +/* USB request type for hub class request */ +#ifndef HUB_GET_HUB_DESCRIPTOR + #define HUB_CLEAR_HUB_FEATURE 0x20 + #define HUB_CLEAR_PORT_FEATURE 0x23 + #define HUB_GET_BUS_STATE 0xA3 + #define HUB_GET_HUB_DESCRIPTOR 0xA0 + #define HUB_GET_HUB_STATUS 0xA0 + #define HUB_GET_PORT_STATUS 0xA3 + #define HUB_SET_HUB_DESCRIPTOR 0x20 + #define HUB_SET_HUB_FEATURE 0x20 + #define HUB_SET_PORT_FEATURE 0x23 +#endif + +/* Hub class feature selectors */ +#ifndef HUB_PORT_RESET + #define HUB_C_HUB_LOCAL_POWER 0 + #define HUB_C_HUB_OVER_CURRENT 1 + #define HUB_PORT_CONNECTION 0 + #define HUB_PORT_ENABLE 1 + #define HUB_PORT_SUSPEND 2 + #define HUB_PORT_OVER_CURRENT 3 + #define HUB_PORT_RESET 4 + #define HUB_PORT_POWER 8 + #define HUB_PORT_LOW_SPEED 9 + #define HUB_C_PORT_CONNECTION 16 + #define HUB_C_PORT_ENABLE 17 + #define HUB_C_PORT_SUSPEND 18 + #define HUB_C_PORT_OVER_CURRENT 19 + #define HUB_C_PORT_RESET 20 +#endif + +/* USB 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 +#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_IMAGE 0x06 + #define USB_DEV_CLASS_PRINTER 0x07 + #define USB_DEV_CLASS_STORAGE 0x08 + #define USB_DEV_CLASS_HUB 0x09 + #define USB_DEV_CLASS_VEN_SPEC 0xFF +#endif + +/* USB 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 +#endif + +#ifndef USB_DEVICE_ADDR + #define USB_DEVICE_ADDR 0x02 +#endif +#ifndef DEFAULT_ENDP0_SIZE + #define DEFAULT_ENDP0_SIZE 8 /* default maximum packet size for endpoint 0 */ +#endif +#ifndef MAX_PACKET_SIZE + #define MAX_PACKET_SIZE 64 /* maximum packet size */ +#endif +#ifndef USB_BO_CBW_SIZE + #define USB_BO_CBW_SIZE 0x1F + #define USB_BO_CSW_SIZE 0x0D +#endif +#ifndef USB_BO_CBW_SIG0 + #define USB_BO_CBW_SIG0 0x55 + #define USB_BO_CBW_SIG1 0x53 + #define USB_BO_CBW_SIG2 0x42 + #define USB_BO_CBW_SIG3 0x43 + #define USB_BO_CSW_SIG0 0x55 + #define USB_BO_CSW_SIG1 0x53 + #define USB_BO_CSW_SIG2 0x42 + #define USB_BO_CSW_SIG3 0x53 +#endif + +#define DEF_STRING_DESC_LANG 0x00 +#define DEF_STRING_DESC_MANU 0x01 +#define DEF_STRING_DESC_PROD 0x02 +#define DEF_STRING_DESC_SERN 0x03 + + //--------------------------------------------------------------------+ // Common Definitions //--------------------------------------------------------------------+ diff --git a/examples_x035/usbdevice/usbdevice.c b/examples_x035/usbdevice/usbdevice.c new file mode 100644 index 00000000..c3280a38 --- /dev/null +++ b/examples_x035/usbdevice/usbdevice.c @@ -0,0 +1,87 @@ +/* Small example showing how to use the SWIO programming pin to + do printf through the debug interface */ + +#include "ch32v003fun.h" +#include +#include +#include "fsusb.h" + +uint32_t count; + +int last = 0; +void handle_debug_input( int numbytes, uint8_t * data ) +{ + last = data[0]; + count += numbytes; +} + +uint8_t scratchpad[256]; + +int HandleHidUserSetReportSetup( struct _USBState * ctx, tusb_control_request_t * req ) +{ + int id = req->wValue & 0xff; + if( id == 0xaa ) + { + // memset( scratchpad, 0x55, sizeof(scratchpad) ); + // printf( "SET REPORT! %d [%02x]\n", req->wLength, scratchpad[200] ); + ctx->pCtrlPayloadPtr = scratchpad; + return req->wLength; + } + return 0; +} + +int HandleHidUserGetReportSetup( struct _USBState * ctx, tusb_control_request_t * req ) +{ + int id = req->wValue & 0xff; + if( id == 0xaa ) + { + //printf( "GET REPORT! %d\n", req->wLength ); + ctx->pCtrlPayloadPtr = scratchpad; + return 255; + } + return 0; +} + +void HandleHidUserReportDataOut( struct _USBState * ctx, uint8_t * data, int len ) +{ +} + +int HandleHidUserReportDataIn( struct _USBState * ctx, uint8_t * data, int len ) +{ +// printf( "IN %d %d %08x %08x\n", len, ctx->USBFS_SetupReqLen, data, FSUSBCTX.ENDPOINTS[0] ); +// memset( data, 0xcc, len ); + return len; +} + +void HandleHidUserReportOutComplete( struct _USBState * ctx ) +{ + return; +} + +int main() +{ + SystemInit(); + + funGpioInitAll(); + + funPinMode( PA0, GPIO_CFGLR_OUT_10Mhz_PP ); + + FSUSBSetup(); + + while(1) + { + //printf( "%lu %08lx %lu %d %d\n", USBDEBUG0, USBDEBUG1, USBDEBUG2, 0, 0 ); + int i; + for( i = 1; i < 3; i++ ) + { + + uint32_t * buffer = (uint32_t*)USBFS_GetEPBufferIfAvailable( i ); + if( buffer ) + { + buffer[0] = 0x000000aa; + USBFS_SendEndpoint( i, (i==1)?8:4 ); + } + } + } +} + From 124fec8d077b6af2ef423378c3bc33c4edb0c88e Mon Sep 17 00:00:00 2001 From: cnlohr Date: Tue, 23 Apr 2024 14:49:37 -0400 Subject: [PATCH 21/31] Fix compile --- ch32v003fun/ch32v003fun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ch32v003fun/ch32v003fun.c b/ch32v003fun/ch32v003fun.c index c7a75ecc..0eb08865 100644 --- a/ch32v003fun/ch32v003fun.c +++ b/ch32v003fun/ch32v003fun.c @@ -717,7 +717,7 @@ void NMI_Handler( void ) __attribute__((section(".text.vector_handler"))) _ void NMI_Handler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); #endif void HardFault_Handler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); -#if defined(CH32V20x) || defined(CH32V30x) +#if defined(CH32V20x) || defined(CH32V30x) || defined(CH32X03x) void Ecall_M_Mode_Handler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); void Ecall_U_Mode_Handler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); void Break_Point_Handler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used)); From 36e4c3b7fb6365b8af3aea732d023d033039826d Mon Sep 17 00:00:00 2001 From: cnlohr Date: Tue, 23 Apr 2024 14:53:01 -0400 Subject: [PATCH 22/31] Try to make CI happy --- examples_x035/usbdevice/testtop.hidapi/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples_x035/usbdevice/testtop.hidapi/Makefile b/examples_x035/usbdevice/testtop.hidapi/Makefile index 7094e41d..021910cf 100644 --- a/examples_x035/usbdevice/testtop.hidapi/Makefile +++ b/examples_x035/usbdevice/testtop.hidapi/Makefile @@ -1,5 +1,9 @@ all : testtop +# to make CI happy. +testtop.hidapi.elf : + gcc -o $@ $^ -I../../../minichlink -ludev + testtop : testtop.c gcc -o $@ $^ -I../../../minichlink -ludev From 30820c1a1fe147e6fdf6ffed531bc059c9d9e579 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Tue, 23 Apr 2024 14:56:25 -0400 Subject: [PATCH 23/31] Build test straps --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d02acbe1..2c2e2559 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,7 +23,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Install Dependencies - run: sudo apt-get update && sudo apt-get install -y build-essential make libnewlib-dev gcc-riscv64-unknown-elf libusb-1.0-0-dev + run: sudo apt-get update && sudo apt-get install -y build-essential make libnewlib-dev gcc-riscv64-unknown-elf libusb-1.0-0-dev libudev-dev - name: Build ${{ matrix.example }} run: cd ${{ matrix.example }} && make V=1 -j3 $(basename ${{ matrix.example }}.elf) && riscv64-unknown-elf-size $(basename ${{ matrix.example }}.elf) # Build using PlatformIO From 53a25da2b4a2ca0fd89d6f960d545adc5a553044 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Tue, 23 Apr 2024 14:59:01 -0400 Subject: [PATCH 24/31] Fix CI --- examples_x035/usbdevice/testtop.hidapi/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_x035/usbdevice/testtop.hidapi/Makefile b/examples_x035/usbdevice/testtop.hidapi/Makefile index 021910cf..a59f3cf6 100644 --- a/examples_x035/usbdevice/testtop.hidapi/Makefile +++ b/examples_x035/usbdevice/testtop.hidapi/Makefile @@ -1,7 +1,7 @@ all : testtop # to make CI happy. -testtop.hidapi.elf : +testtop.hidapi.elf : testtop.c gcc -o $@ $^ -I../../../minichlink -ludev testtop : testtop.c From 7ab7a55a79e7fa342655ce5827da1a61b006899f Mon Sep 17 00:00:00 2001 From: cnlohr Date: Tue, 23 Apr 2024 21:01:10 -0700 Subject: [PATCH 25/31] Add hidapi --- examples_x035/usbdevice/Makefile | 6 + .../usbdevice/testtop.hidapi/testtop.c | 2 +- examples_x035/usbdevice/usb_config.h | 212 ++++++++++-------- 3 files changed, 129 insertions(+), 91 deletions(-) diff --git a/examples_x035/usbdevice/Makefile b/examples_x035/usbdevice/Makefile index 27b389bc..7ef3dfce 100644 --- a/examples_x035/usbdevice/Makefile +++ b/examples_x035/usbdevice/Makefile @@ -5,6 +5,12 @@ TARGET_MCU:=CH32X035 ADDITIONAL_C_FILES:= include ../../ch32v003fun/ch32v003fun.mk +install_udev_rules : + sudo cp 99-x035demo.rules /etc/udev/rules.d/ + sudo udevadm control --reload + sudo udevadm trigger + + flash : cv_flash clean : cv_clean diff --git a/examples_x035/usbdevice/testtop.hidapi/testtop.c b/examples_x035/usbdevice/testtop.hidapi/testtop.c index 3ceb7ec1..a7a4b683 100644 --- a/examples_x035/usbdevice/testtop.hidapi/testtop.c +++ b/examples_x035/usbdevice/testtop.hidapi/testtop.c @@ -12,7 +12,7 @@ int main() { - hid_device * hd = hid_open( 0xaaaa, 0xd004, L"CUSTOMDEVICE000"); // third parameter is "serial" + hid_device * hd = hid_open( 0x1206, 0xd035, L"CUSTOMDEVICE000"); // third parameter is "serial" if( !hd ) { fprintf( stderr, "Error: Failed to open device.\n" ); diff --git a/examples_x035/usbdevice/usb_config.h b/examples_x035/usbdevice/usb_config.h index 82800e46..1f763ae0 100644 --- a/examples_x035/usbdevice/usb_config.h +++ b/examples_x035/usbdevice/usb_config.h @@ -2,7 +2,7 @@ #define _USB_CONFIG_H #define FUSB_5V_OPERATION 0 -#define FUSB_CONFIG_EPS 3 // Include EP0 in this count +#define FUSB_CONFIG_EPS 4 // Include EP0 in this count #define FUSB_SUPPORTS_SLEEP 0 #define FUSB_HID_INTERFACES 2 #define FUSB_CURSED_TURBO_DMA 0 // Hacky, but seems fine, shaves 2.5us off filling 64-byte buffers. @@ -21,8 +21,8 @@ static const uint8_t device_descriptor[] = { 0x0, //Device Subclass 0x0, //Device Protocol (000 = use config descriptor) 64, //Max packet size for EP0 (This has to be 8 because of the USB Low-Speed Standard) - 0xaa, 0xaa, //ID Vendor - 0x04, 0xd0, //ID Product + 0x09, 0x12, //ID Vendor + 0x35, 0xd0, //ID Product 0x03, 0x00, //ID Rev 1, //Manufacturer string 2, //Product string @@ -31,6 +31,91 @@ static const uint8_t device_descriptor[] = { }; +/* Keyboard Report Descriptor */ +static const uint8_t KeyRepDesc[ ] = +{ + 0x05, 0x01, // Usage Page (Generic Desktop) + 0x09, 0x06, // Usage (Keyboard) + 0xA1, 0x01, // Collection (Application) + 0x05, 0x07, // Usage Page (Key Codes) + 0x19, 0xE0, // Usage Minimum (224) + 0x29, 0xE7, // Usage Maximum (231) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x08, // Report Count (8) + 0x81, 0x02, // Input (Data,Variable,Absolute) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x01, // Input (Constant) + 0x95, 0x03, // Report Count (3) + 0x75, 0x01, // Report Size (1) + 0x05, 0x08, // Usage Page (LEDs) + 0x19, 0x01, // Usage Minimum (1) + 0x29, 0x03, // Usage Maximum (3) + 0x91, 0x02, // Output (Data,Variable,Absolute) + 0x95, 0x05, // Report Count (5) + 0x75, 0x01, // Report Size (1) + 0x91, 0x01, // Output (Constant,Array,Absolute) + 0x95, 0x06, // Report Count (6) + 0x75, 0x08, // Report Size (8) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x05, 0x07, // Usage Page (Key Codes) + 0x19, 0x00, // Usage Minimum (0) + 0x29, 0x91, // Usage Maximum (145) + 0x81, 0x00, // Input(Data,Array,Absolute) + 0xC0 // End Collection +}; + +/* Mouse Report Descriptor */ +static const uint8_t MouseRepDesc[ ] = +{ + + 0x05, 0x01, // Usage Page (Generic Desktop) + 0x09, 0x02, // Usage (Mouse) + 0xA1, 0x01, // Collection (Application) + 0x09, 0x01, // Usage (Pointer) + 0xA1, 0x00, // Collection (Physical) + 0x05, 0x09, // Usage Page (Button) + 0x19, 0x01, // Usage Minimum (Button 1) + 0x29, 0x03, // Usage Maximum (Button 3) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x03, // Report Count (3) + 0x81, 0x02, // Input (Data,Variable,Absolute) + 0x75, 0x05, // Report Size (5) + 0x95, 0x01, // Report Count (1) + 0x81, 0x01, // Input (Constant,Array,Absolute) + 0x05, 0x01, // Usage Page (Generic Desktop) + 0x09, 0x30, // Usage (X) + 0x09, 0x31, // Usage (Y) + 0x09, 0x38, // Usage (Wheel) + 0x15, 0x81, // Logical Minimum (-127) + 0x25, 0x7F, // Logical Maximum (127) + 0x75, 0x08, // Report Size (8) + 0x95, 0x03, // Report Count (3) + 0x81, 0x06, // Input (Data,Variable,Relative) + 0xC0, // End Collection + 0xC0 // End Collection +}; + +static const uint8_t HIDAPIRepDesc[ ] = +{ + HID_USAGE_PAGE ( 0xff ), // Vendor-defined page. + HID_USAGE ( 0x00 ), + HID_REPORT_SIZE ( 8 ), + HID_COLLECTION ( HID_COLLECTION_LOGICAL ), + HID_REPORT_COUNT ( 254 ), + HID_REPORT_ID ( 0xaa ) + HID_USAGE ( 0x01 ), + HID_FEATURE ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) , + HID_REPORT_COUNT ( 63 ), // For use with `hidapitester --vidpid 1209/D003 --open --read-feature 171` + HID_REPORT_ID ( 0xab ) + HID_USAGE ( 0x01 ), + HID_FEATURE ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) , + HID_COLLECTION_END, +}; /* Configuration Descriptor Set */ static const uint8_t config_descriptor[ ] = @@ -38,8 +123,8 @@ static const uint8_t config_descriptor[ ] = /* Configuration Descriptor */ 0x09, // bLength 0x02, // bDescriptorType - 0x3B, 0x00, // wTotalLength - 0x02, // bNumInterfaces + 0x54, 0x00, // wTotalLength + 0x03, // bNumInterfaces (2) 0x01, // bConfigurationValue 0x00, // iConfiguration 0xA0, // bmAttributes: Bus Powered; Remote Wakeup @@ -63,7 +148,7 @@ static const uint8_t config_descriptor[ ] = 0x00, // bCountryCode 0x01, // bNumDescriptors 0x22, // bDescriptorType - 0x3E, 0x00, // wDescriptorLength + sizeof(KeyRepDesc), 0x00, // wDescriptorLength /* Endpoint Descriptor (Keyboard) */ 0x07, // bLength @@ -91,7 +176,7 @@ static const uint8_t config_descriptor[ ] = 0x00, // bCountryCode 0x01, // bNumDescriptors 0x22, // bDescriptorType - 0x34, 0x00, // wDescriptorLength + sizeof(MouseRepDesc), 0x00, // wDescriptorLength /* Endpoint Descriptor (Mouse) */ 0x07, // bLength @@ -99,97 +184,42 @@ static const uint8_t config_descriptor[ ] = 0x82, // bEndpointAddress: IN Endpoint 2 0x03, // bmAttributes 0x08, 0x00, // wMaxPacketSize - 0x01 // bInterval: 1mS -}; + 0x01, // bInterval: 1mS + + /* Interface Descriptor (Mouse) */ + 0x09, // bLength + 0x04, // bDescriptorType + 0x02, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x01, // bNumEndpoints + 0x03, // bInterfaceClass + 0x00, // bInterfaceSubClass + 0xff, // bInterfaceProtocol: OTher + 0x00, // iInterface + /* HID Descriptor (Mouse) */ + 0x09, // bLength + 0x21, // bDescriptorType + 0x10, 0x01, // bcdHID + 0x00, // bCountryCode + 0x01, // bNumDescriptors + 0x22, // bDescriptorType + sizeof(HIDAPIRepDesc), 0x00, // wDescriptorLength -/* Keyboard Report Descriptor */ -static const uint8_t KeyRepDesc[ ] = -{ - 0x05, 0x01, // Usage Page (Generic Desktop) - 0x09, 0x06, // Usage (Keyboard) - 0xA1, 0x01, // Collection (Application) - 0x05, 0x07, // Usage Page (Key Codes) - 0x19, 0xE0, // Usage Minimum (224) - 0x29, 0xE7, // Usage Maximum (231) - 0x15, 0x00, // Logical Minimum (0) - 0x25, 0x01, // Logical Maximum (1) - 0x75, 0x01, // Report Size (1) - 0x95, 0x08, // Report Count (8) - 0x81, 0x02, // Input (Data,Variable,Absolute) - 0x95, 0x01, // Report Count (1) - 0x75, 0x08, // Report Size (8) - 0x81, 0x01, // Input (Constant) - 0x95, 0x03, // Report Count (3) - 0x75, 0x01, // Report Size (1) - 0x05, 0x08, // Usage Page (LEDs) - 0x19, 0x01, // Usage Minimum (1) - 0x29, 0x03, // Usage Maximum (3) - 0x91, 0x02, // Output (Data,Variable,Absolute) - 0x95, 0x05, // Report Count (5) - 0x75, 0x01, // Report Size (1) - 0x91, 0x01, // Output (Constant,Array,Absolute) - 0x95, 0x06, // Report Count (6) - 0x75, 0x08, // Report Size (8) - 0x26, 0xFF, 0x00, // Logical Maximum (255) - 0x05, 0x07, // Usage Page (Key Codes) - 0x19, 0x00, // Usage Minimum (0) - 0x29, 0x91, // Usage Maximum (145) - 0x81, 0x00, // Input(Data,Array,Absolute) - 0xC0 // End Collection -, - // TODO - Figure out how to work this in. - HID_USAGE_PAGE ( 0xff ), // Vendor-defined page. - HID_USAGE ( 0x00 ), - HID_REPORT_SIZE ( 8 ), - HID_COLLECTION ( HID_COLLECTION_LOGICAL ), - HID_REPORT_COUNT ( 254 ), - HID_REPORT_ID ( 0xaa ) - HID_USAGE ( 0x01 ), - HID_FEATURE ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) , - HID_REPORT_COUNT ( 63 ), // For use with `hidapitester --vidpid 1209/D003 --open --read-feature 171` - HID_REPORT_ID ( 0xab ) - HID_USAGE ( 0x01 ), - HID_FEATURE ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) , - HID_COLLECTION_END, + /* Endpoint Descriptor (Mouse) */ + 0x07, // bLength + 0x05, // bDescriptorType + 0x83, // bEndpointAddress: IN Endpoint 2 + 0x03, // bmAttributes + 0x08, 0x00, // wMaxPacketSize + 0x0a, // bInterval: 1mS }; -/* Mouse Report Descriptor */ -static const uint8_t MouseRepDesc[ ] = -{ - 0x05, 0x01, // Usage Page (Generic Desktop) - 0x09, 0x02, // Usage (Mouse) - 0xA1, 0x01, // Collection (Application) - 0x09, 0x01, // Usage (Pointer) - 0xA1, 0x00, // Collection (Physical) - 0x05, 0x09, // Usage Page (Button) - 0x19, 0x01, // Usage Minimum (Button 1) - 0x29, 0x03, // Usage Maximum (Button 3) - 0x15, 0x00, // Logical Minimum (0) - 0x25, 0x01, // Logical Maximum (1) - 0x75, 0x01, // Report Size (1) - 0x95, 0x03, // Report Count (3) - 0x81, 0x02, // Input (Data,Variable,Absolute) - 0x75, 0x05, // Report Size (5) - 0x95, 0x01, // Report Count (1) - 0x81, 0x01, // Input (Constant,Array,Absolute) - 0x05, 0x01, // Usage Page (Generic Desktop) - 0x09, 0x30, // Usage (X) - 0x09, 0x31, // Usage (Y) - 0x09, 0x38, // Usage (Wheel) - 0x15, 0x81, // Logical Minimum (-127) - 0x25, 0x7F, // Logical Maximum (127) - 0x75, 0x08, // Report Size (8) - 0x95, 0x03, // Report Count (3) - 0x81, 0x06, // Input (Data,Variable,Relative) - 0xC0, // End Collection - 0xC0 // End Collection -}; -#define STR_MANUFACTURER u"WCH-TEST" +#define STR_MANUFACTURER u"CNLohr" #define STR_PRODUCT u"ch32v003fun ch32x035 test" #define STR_SERIAL u"CUSTOMDEVICE000" @@ -231,6 +261,8 @@ const static struct descriptor_list_struct { // interface number // 2200 for hid descriptors. {0x00002200, KeyRepDesc, sizeof(KeyRepDesc)}, {0x00012200, MouseRepDesc, sizeof(MouseRepDesc)}, + {0x00022200, HIDAPIRepDesc, sizeof(HIDAPIRepDesc)}, + {0x00002100, config_descriptor + 18, 9 }, // Not sure why, this seems to be useful for Windows + Android. {0x00000300, (const uint8_t *)&string0, 4}, From 1763213526021f04928bdbc222e23f6706cdb70d Mon Sep 17 00:00:00 2001 From: cnlohr Date: Tue, 23 Apr 2024 21:01:25 -0700 Subject: [PATCH 26/31] Add webusb demo --- .../usbdevice/testtop.webusb/index.html | 244 ++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 examples_x035/usbdevice/testtop.webusb/index.html diff --git a/examples_x035/usbdevice/testtop.webusb/index.html b/examples_x035/usbdevice/testtop.webusb/index.html new file mode 100644 index 00000000..c3ab9653 --- /dev/null +++ b/examples_x035/usbdevice/testtop.webusb/index.html @@ -0,0 +1,244 @@ + + + + + + + + +
+
+ + From 9d7ee13b9cfaa73cd2023e2bdc722e23a2d37e6e Mon Sep 17 00:00:00 2001 From: cnlohr Date: Wed, 24 Apr 2024 03:03:57 -0400 Subject: [PATCH 27/31] Update app --- examples_x035/usbdevice/funconfig.h | 1 + examples_x035/usbdevice/testtop.hidapi/testtop.c | 2 +- examples_x035/usbdevice/usb_config.h | 16 +++++++++------- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/examples_x035/usbdevice/funconfig.h b/examples_x035/usbdevice/funconfig.h index a8a70b30..a4f64d23 100644 --- a/examples_x035/usbdevice/funconfig.h +++ b/examples_x035/usbdevice/funconfig.h @@ -4,6 +4,7 @@ // Though this should be on by default we can extra force it on. #define FUNCONF_USE_DEBUGPRINTF 1 #define FUNCONF_DEBUGPRINTF_TIMEOUT (1<<31) // Wait for a very very long time. +#define FUNCONF_5V_OPERATION 1 #endif diff --git a/examples_x035/usbdevice/testtop.hidapi/testtop.c b/examples_x035/usbdevice/testtop.hidapi/testtop.c index a7a4b683..ea2a11cf 100644 --- a/examples_x035/usbdevice/testtop.hidapi/testtop.c +++ b/examples_x035/usbdevice/testtop.hidapi/testtop.c @@ -12,7 +12,7 @@ int main() { - hid_device * hd = hid_open( 0x1206, 0xd035, L"CUSTOMDEVICE000"); // third parameter is "serial" + hid_device * hd = hid_open( 0x1209, 0xd035, L"CUSTOMDEVICE000"); // third parameter is "serial" if( !hd ) { fprintf( stderr, "Error: Failed to open device.\n" ); diff --git a/examples_x035/usbdevice/usb_config.h b/examples_x035/usbdevice/usb_config.h index 1f763ae0..357d4292 100644 --- a/examples_x035/usbdevice/usb_config.h +++ b/examples_x035/usbdevice/usb_config.h @@ -1,14 +1,17 @@ #ifndef _USB_CONFIG_H #define _USB_CONFIG_H -#define FUSB_5V_OPERATION 0 -#define FUSB_CONFIG_EPS 4 // Include EP0 in this count -#define FUSB_SUPPORTS_SLEEP 0 -#define FUSB_HID_INTERFACES 2 +#include "funconfig.h" +#include "ch32v003fun.h" + +#define FUSB_CONFIG_EPS 4 // Include EP0 in this count +#define FUSB_SUPPORTS_SLEEP 0 +#define FUSB_HID_INTERFACES 2 #define FUSB_CURSED_TURBO_DMA 0 // Hacky, but seems fine, shaves 2.5us off filling 64-byte buffers. #define FUSB_HID_USER_REPORTS 1 -#define FUSB_USE_HPE 1 // Use hardware stack. #define FUSB_IO_PROFILE 1 +#define FUSB_USE_HPE FUNCONF_ENABLE_HPE +#define FUSB_5V_OPERATION FUNCONF_5V_OPERATION #include "usb_defines.h" @@ -213,8 +216,7 @@ static const uint8_t config_descriptor[ ] = 0x83, // bEndpointAddress: IN Endpoint 2 0x03, // bmAttributes 0x08, 0x00, // wMaxPacketSize - 0x0a, // bInterval: 1mS - + 0x0a, // bInterval: 10mS }; From 5b0a0f4395437b95c911355f4c4acdd79032fc6c Mon Sep 17 00:00:00 2001 From: cnlohr Date: Wed, 24 Apr 2024 05:06:33 -0400 Subject: [PATCH 28/31] Update with PD defines --- ch32v003fun/ch32v003fun.h | 168 +++++++++++++++++++++++---- examples_x035/usbdevice/usb_config.h | 2 +- 2 files changed, 148 insertions(+), 22 deletions(-) diff --git a/ch32v003fun/ch32v003fun.h b/ch32v003fun/ch32v003fun.h index 6146f89b..7fceaa41 100644 --- a/ch32v003fun/ch32v003fun.h +++ b/ch32v003fun/ch32v003fun.h @@ -56,6 +56,7 @@ #define FUNCONF_UART_PRINTF_BAUD 115200 // Only used if FUNCONF_USE_UARTPRINTF is set. #define FUNCONF_DEBUGPRINTF_TIMEOUT 160000 // Arbitrary time units #define FUNCONF_ENABLE_HPE 1 // Enable hardware interrupt stack. Very good on QingKeV4, i.e. x035, v10x, v20x, v30x, but questionable on 003. +#define FUNCONF_USE_5V_VDD 0 // Enable this if you plan to use your part at 5V - affects USB and PD configration on the x035. */ // Sanity check for when porting old code. @@ -179,6 +180,10 @@ #endif #endif +#ifndef FUNCONF_USE_5V_VDD + #define FUNCONF_USE_5V_VDD 0 +#endif + // Default package for CH32V20x #if defined(CH32V20x) #if !defined(CH32V20x_D8W) && !defined(CH32V20x_D8) && !defined(CH32V20x_D6) @@ -1773,18 +1778,11 @@ typedef struct __IO uint32_t UEPX_MOD; } USBFS_TypeDef; + + #define USB_PHY_V33 (1<<6) #define USB_IOEN (1<<7) -#define UDP_PUE_00 (0b00<<2) -#define UDP_PUE_01 (0b01<<2) -#define UDP_PUE_10 (0b10<<2) -#define UDP_PUE_11 (0b11<<2) -#define UDM_PUE_00 (0b00<<0) -#define UDM_PUE_01 (0b01<<0) -#define UDM_PUE_10 (0b10<<0) -#define UDM_PUE_11 (0b11<<0) - #define USBFSD_UEP_MOD_BASE 0x4002340C #define USBFSD_UEP_DMA_BASE 0x40023410 @@ -1898,17 +1896,6 @@ typedef struct #define UNUM_EP 8 -#define UDP_PUE_MASK 0x0000000C -#define UDP_PUE_DISABLE 0x00000000 -#define UDP_PUE_35UA 0x00000004 -#define UDP_PUE_10K 0x00000008 -#define UDP_PUE_1K5 0x0000000C - -#define UDM_PUE_MASK 0x00000003 -#define UDM_PUE_DISABLE 0x00000000 -#define UDM_PUE_35UA 0x00000001 -#define UDM_PUE_10K 0x00000002 -#define UDM_PUE_1K5 0x00000003 /* USB Host Mode */ @@ -1978,6 +1965,27 @@ typedef struct __IO uint32_t DMA; } USBPD_TypeDef; + +/* USB Power Delivery */ +typedef struct +{ + __IO uint16_t CONFIG; + __IO uint16_t BCM_CLK_CNT; + + __IO uint8_t CONTROL; + __IO uint8_t TX_SEL; + __IO uint16_t BMC_TX_SZ; + + __IO uint8_t DATA_BUF; + __IO uint8_t STATUS; + __IO uint16_t BMC_BYTE_CNT; + + __IO uint16_t PORT_CC1; + __IO uint16_t PORT_CC2; + + __IO uint32_t USBPD_DMA; +} USBPD_DETAILED_TypeDef; + #endif // #if defined(CH32X03x) @@ -2188,6 +2196,123 @@ typedef struct #endif #endif + + +// AFIO CTLR Bits +#define PB6_FILT_EN (1<<27) +#define PB5_FILT_EN (1<<26) +#define PA4_FILT_EN (1<<25) +#define PA3_FILT_EN (1<<24) +#define UDM_BC_CMPO (1<<19) +#define UDP_BC_CMPO (1<<17) +#define UDM_BC_VSRC (1<<17) +#define UDP_BC_VSRC (1<<16) +#define USBPD_IN_HVT (1<<9) +#define USBPD_PHY_V33 (1<<8) +#define USB_IOEN (1<<7) +#define USB_PHY_V33 (1<<6) +#define UDP_PUE_00 (0b00<<2) +#define UDP_PUE_01 (0b01<<2) +#define UDP_PUE_10 (0b10<<2) +#define UDP_PUE_11 (0b11<<2) +#define UDM_PUE_00 (0b00<<0) +#define UDM_PUE_01 (0b01<<0) +#define UDM_PUE_10 (0b10<<0) +#define UDM_PUE_11 (0b11<<0) +#define UDP_PUE_MASK 0x0000000C +#define UDP_PUE_DISABLE 0x00000000 +#define UDP_PUE_35UA 0x00000004 +#define UDP_PUE_10K 0x00000008 +#define UDP_PUE_1K5 0x0000000C +#define UDM_PUE_MASK 0x00000003 +#define UDM_PUE_DISABLE 0x00000000 +#define UDM_PUE_35UA 0x00000001 +#define UDM_PUE_10K 0x00000002 +#define UDM_PUE_1K5 0x00000003 + + +// USB PD Bits +#define IE_TX_END (1<<15) +#define IE_RX_RESET (1<<14) +#define IE_RX_ACT (1<<13) +#define IE_RX_BYTE (1<<12) +#define IE_RX_BIT (1<<11) +#define IE_PD_IO (1<<10) +#define WAKE_POLAR (1<<5) +#define PD_RST_EN (1<<4) +#define PD_DMA_EN (1<<3) +#define CC_SEL (1<<2) +#define PD_ALL_CLR (1<<1) +#define PD_FILT_EN (1<<0) +#define BMC_CLK_CNT_MASK (0xff) + +//R8_CONTROL +#define BMC_BYTE_HI (1<<7) +#define TX_BIT_BACK (1<<6) +#define DATA_FLAG (1<<5) +#define RX_STATE_MASK (0x7<<2) +#define RX_STATE_0 (1<<2) +#define RX_STATE_1 (1<<3) +#define RX_STATE_2 (1<<4) +#define BMC_START (1<<1) +#define PD_TX_EN (1<<0) + +#define TX_SEL4_MASK (3<<6) +#define TX_SEL4_0 (1<<6) +#define TX_SEL4_1 (1<<7) + +#define TX_SEL3_MASK (3<<4) +#define TX_SEL3_0 (1<<4) +#define TX_SEL3_1 (1<<5) + +#define TX_SEL2_MASK (3<<2) +#define TX_SEL2_0 (1<<2) +#define TX_SEL2_1 (1<<3) + +#define TX_SEL1 (1<<0) + +#define BMC_TX_SZ_MASK (0x1ff) + +//R8_STATUS +#define IF_TX_END (1<<7) +#define IF_RX_RESET (1<<6) +#define IF_RX_ACT (1<<5) +#define IF_RX_BYTE (1<<4) +#define IF_RX_BIT (1<<3) +#define IFBUF_ERR (1<<2) +#define BMC_AUX_MASK (3<<0) +#define BMC_AUX_1 (1<<1) +#define BMC_AUX_0 (1<<0) + +// PORT CC1 +#define CC1_CE_MASK (7<<5) +#define CC1_CE_0 (1<<5) +#define CC1_CE_1 (2<<5) +#define CC1_CE_2 (4<<5) + +#define CC1_LVE (1<<4) +#define CC1_PU_MASK (3<<2) +#define CC1_PU_DISABLE (0<<2) +#define CC1_PU_330uA (1<<2) +#define CC1_PU_180uA (2<<2) +#define CC1_PU_80uA (3<<2) +#define PA_CC1_AI (1<<0) + +#define CC2_CE_MASK (7<<5) +#define CC2_CE_0 (1<<5) +#define CC2_CE_1 (2<<5) +#define CC2_CE_2 (4<<5) + +#define CC2_LVE (1<<4) +#define CC2_PU_MASK (3<<2) +#define CC2_PU_DISABLE (0<<2) +#define CC2_PU_330uA (1<<2) +#define CC2_PU_180uA (2<<2) +#define CC2_PU_80uA (3<<2) +#define PA_CC2_AI (1<<0) + + + /* Peripheral declaration */ #define TIM2 ((TIM_TypeDef *)TIM2_BASE) #if defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) @@ -2263,7 +2388,8 @@ typedef struct #define TKey ((TKEY_TypeDef *)ADC1_BASE) #define OPA ((OPACMP_TypeDef *)OPA_BASE) #define USBFS ((USBFS_TypeDef *)USBFS_BASE) -#define USBPD ((USBPD_TypeDef *)USBPD_BASE) +#define USBPDWORD ((USBPD_TypeDef *)USBPD_BASE) +#define USBPD ((USBPD_DETAILED_TypeDef *)USBPD_BASE) #define USBDH ((USBDH_TypeDef *)USBFS_BASE) #endif diff --git a/examples_x035/usbdevice/usb_config.h b/examples_x035/usbdevice/usb_config.h index 357d4292..093cd7a2 100644 --- a/examples_x035/usbdevice/usb_config.h +++ b/examples_x035/usbdevice/usb_config.h @@ -127,7 +127,7 @@ static const uint8_t config_descriptor[ ] = 0x09, // bLength 0x02, // bDescriptorType 0x54, 0x00, // wTotalLength - 0x03, // bNumInterfaces (2) + 0x03, // bNumInterfaces (3) 0x01, // bConfigurationValue 0x00, // iConfiguration 0xA0, // bmAttributes: Bus Powered; Remote Wakeup From a1fe5b00ba4b29c4890fe3f3ab9f2231860f8c47 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sat, 27 Apr 2024 01:07:18 -0400 Subject: [PATCH 29/31] Fix 203 blink demo --- examples_v20x/blink/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples_v20x/blink/Makefile b/examples_v20x/blink/Makefile index 90acba47..80ca9c6a 100644 --- a/examples_v20x/blink/Makefile +++ b/examples_v20x/blink/Makefile @@ -1,7 +1,8 @@ all : flash TARGET:=blink -TARGET_MCU:=CH32V203 +TARGET_MCU:=CH32V203G6U6 +TARGET_MCU_PACKAGE:=CH32V203G6U6 include ../../ch32v003fun/ch32v003fun.mk From 45c1d38bf3c5dab5a8c61d01c7b5e64d3d2720f1 Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sat, 27 Apr 2024 01:08:31 -0400 Subject: [PATCH 30/31] Update overall, tested and working on 203 --- ch32v003fun/ch32v003fun.mk | 18 ++++++++--------- examples_x035/usbdevice/99-x035demo.rules | 12 ++++++++++++ minichlink/pgm-wch-linke.c | 24 ++++++++++++++++++----- 3 files changed, 40 insertions(+), 14 deletions(-) create mode 100644 examples_x035/usbdevice/99-x035demo.rules diff --git a/ch32v003fun/ch32v003fun.mk b/ch32v003fun/ch32v003fun.mk index 750c2850..ee6519e8 100644 --- a/ch32v003fun/ch32v003fun.mk +++ b/ch32v003fun/ch32v003fun.mk @@ -87,7 +87,14 @@ else -DCH32V20x=1 # MCU Flash/RAM split - ifeq ($(findstring F8, $(TARGET_MCU_PACKAGE)), F8) + + + # Package + ifeq ($(findstring 203RB, $(TARGET_MCU_PACKAGE)), 203RB) + CFLAGS+=-DCH32V20x_D8 + else ifeq ($(findstring 208, $(TARGET_MCU_PACKAGE)), 208) + CFLAGS+=-DCH32V20x_D8W + else ifeq ($(findstring F8, $(TARGET_MCU_PACKAGE)), F8) MCU_PACKAGE:=1 else ifeq ($(findstring G8, $(TARGET_MCU_PACKAGE)), G8) MCU_PACKAGE:=1 @@ -111,13 +118,6 @@ else MCU_PACKAGE:=3 else ifeq ($(findstring WB, $(TARGET_MCU_PACKAGE)), WB) MCU_PACKAGE:=3 - endif - - # Package - ifeq ($(findstring 203RB, $(TARGET_MCU_PACKAGE)), 203RB) - CFLAGS+=-DCH32V20x_D8 - else ifeq ($(findstring 208, $(TARGET_MCU_PACKAGE)), 208) - CFLAGS+=-DCH32V20x_D8W else CFLAGS+=-DCH32V20x_D6 endif @@ -224,6 +224,6 @@ cv_flash : $(TARGET).bin $(FLASH_COMMAND) cv_clean : - rm -rf $(TARGET).elf $(TARGET).bin $(TARGET).hex $(TARGET).lst $(TARGET).map $(TARGET).hex || true + rm -rf $(TARGET).elf $(TARGET).bin $(TARGET).hex $(TARGET).lst $(TARGET).map $(TARGET).hex $(GENERATED_LD_FILE) || true build : $(TARGET).bin diff --git a/examples_x035/usbdevice/99-x035demo.rules b/examples_x035/usbdevice/99-x035demo.rules new file mode 100644 index 00000000..39e7ce91 --- /dev/null +++ b/examples_x035/usbdevice/99-x035demo.rules @@ -0,0 +1,12 @@ +KERNEL=="hidraw*", SUBSYSTEM=="hidraw", MODE="0664", GROUP="plugdev", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="d035" +KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="d035", GROUP="plugdev", MODE="0660" +#KERNEL=="hidraw*", SUBSYSTEM=="hidraw", MODE="0660", GROUP="plugdev" + + +#, TAG+="uaccess", TAG+="udev-acl" +# KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="d035", GROUP="plugdev", MODE="0664" +#KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="d035", MODE="0666" +#KERNEL=="hiddev*", SUBSYSTEM=="usbmisc", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="d035", GROUP="plugdev", MODE="0660", TAG+="uaccess", TAG+="udev-acl" +#SUBSYSTEM=="usb", ATTR{idVendor}=="1209", ATTR{idProduct}=="d035", MODE="0660", GROUP="plugdev", TAG+="uaccess", TAG+="udev-acl" +#KERNEL=="hidraw*", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="d035", MODE="0660", GROUP="plugdev", TAG+="uaccess", TAG+="udev-acl" + diff --git a/minichlink/pgm-wch-linke.c b/minichlink/pgm-wch-linke.c index f674f0f7..b322a9c0 100644 --- a/minichlink/pgm-wch-linke.c +++ b/minichlink/pgm-wch-linke.c @@ -394,16 +394,22 @@ static int LESetupInterface( void * d ) MCF.WriteReg32( d, DMCONTROL, 0x80000001 ); // Initiate a halt request. MCF.WriteReg32( d, DMCONTROL, 0x80000003 ); // No, really make sure, and also super halt processor. MCF.WriteReg32( d, DMCONTROL, 0x80000001 ); // Un-super-halt processor. - MCF.WriteReg32( d, DMABSTRACTCS, 0x00000700 ); // Ignore any pending errors. - MCF.WriteReg32( d, DMABSTRACTAUTO, 0 ); - MCF.WriteReg32( d, DMCOMMAND, 0x00221000 ); // Read x0 (Null command) with nopostexec (to fix v307 read issues) int r = 0; - r |= MCF.WaitForDoneOp( d, 0 ); + + int timeout = 0; +retry_DoneOp: + MCF.WriteReg32( d, DMABSTRACTCS, 0x00000700 ); // Ignore any pending errors. + MCF.WriteReg32( d, DMABSTRACTAUTO, 0 ); + MCF.WriteReg32( d, DMCOMMAND, 0x00221000 ); // Read x0 (Null command) with nopostexec (to fix v307 read issues) + r = MCF.WaitForDoneOp( d, 0 ); if( r ) { - fprintf( stderr, "Fault on setup\n" ); + fprintf( stderr, "Retrying\n" ); + if( timeout++ < 10 ) goto retry_DoneOp; + fprintf( stderr, "Fault on setup %d\n", r ); + return -4; } else { @@ -413,8 +419,16 @@ static int LESetupInterface( void * d ) // This puts the processor on hold to allow the debugger to run. // Recommended to switch to 05 from 09 by Alexander M // wch_link_command( dev, "\x81\x11\x01\x09", 4, (int*)&transferred, rbuff, 1024 ); // Reply: Chip ID + Other data (see below) +retry_ID: wch_link_command( dev, "\x81\x11\x01\x05", 4, (int*)&transferred, rbuff, 1024 ); // Reply: Chip ID + Other data (see below) + if( rbuff[0] == 0x00 ) + { + if( timeout++ < 10 ) goto retry_ID; + fprintf( stderr, "Failed to get chip ID\n" ); + return -4; + } + if( transferred != 20 ) { fprintf( stderr, "Error: could not get part status\n" ); From 098fb621d8143890e8c9030df5847b36ebc4a46e Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sat, 27 Apr 2024 01:13:34 -0400 Subject: [PATCH 31/31] Fix compile --- examples_x035/sandbox/sandbox.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/examples_x035/sandbox/sandbox.c b/examples_x035/sandbox/sandbox.c index c341d2fd..a83ff5fe 100644 --- a/examples_x035/sandbox/sandbox.c +++ b/examples_x035/sandbox/sandbox.c @@ -7,6 +7,7 @@ uint32_t count; int last = 0; + void handle_debug_input( int numbytes, uint8_t * data ) { last = data[0]; @@ -21,23 +22,8 @@ int main() funPinMode( PA0, GPIO_CFGLR_OUT_10Mhz_PP ); - printf( "%08x\n", &USBPD->DMA ); + printf( "Hello\n" ); while(1); - -#if 0 - while(1) - { - GPIOA->BSHR = 1; // Turn on GPIOs - printf( "+%lu %lu\n", count++ ); - Delay_Ms(100); - int i; - for( i = 0; i < 10000; i++ ) - poll_input(); - GPIOA->BSHR = (1<<16); // Turn off GPIODs - printf( "-%lu[%c]\n", count++, last ); - Delay_Ms(100); - } -#endif }