From 8096afc6dea975e95e0b50dc4b55926236b90b62 Mon Sep 17 00:00:00 2001 From: ReimuNotMoe <34613827+ReimuNotMoe@users.noreply.github.com> Date: Thu, 6 Oct 2022 03:45:51 +0800 Subject: [PATCH] Microchip PIC24/dsPIC33 device mode support --- src/common/tusb_mcu.h | 5 + src/portable/microchip/pic/dcd_pic.c | 141 ++++++++++++++++++++------- 2 files changed, 113 insertions(+), 33 deletions(-) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index baa82fc1..514ffcd4 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -111,6 +111,11 @@ #define TUP_DCD_ENDPOINT_MAX 8 #define TUP_DCD_ENDPOINT_EXCLUSIVE_NUMBER +#elif TU_CHECK_MCU(OPT_MCU_PIC32MX, OPT_MCU_PIC32MM, OPT_MCU_PIC32MK) || \ + TU_CHECK_MCU(OPT_MCU_PIC24, OPT_MCU_DSPIC33) + #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_DCD_ENDPOINT_EXCLUSIVE_NUMBER + //------------- ST -------------// #elif TU_CHECK_MCU(OPT_MCU_STM32F0) #define TUP_DCD_ENDPOINT_MAX 8 diff --git a/src/portable/microchip/pic/dcd_pic.c b/src/portable/microchip/pic/dcd_pic.c index df9b2ff0..6cf0e628 100644 --- a/src/portable/microchip/pic/dcd_pic.c +++ b/src/portable/microchip/pic/dcd_pic.c @@ -39,14 +39,10 @@ #if (CFG_TUSB_MCU == OPT_MCU_PIC32MX || CFG_TUSB_MCU == OPT_MCU_PIC32MM || CFG_TUSB_MCU == OPT_MCU_PIC32MK) -#define TU_PIC_HAS_MMU 1 -#define TU_PIC_HAS_HW_RMW 1 #define TU_PIC_INT_SIZE 4 #elif (CFG_TUSB_MCU == OPT_MCU_PIC24 || CFG_TUSB_MCU == OPT_MCU_DSPIC33) -#define TU_PIC_HAS_MMU 0 -#define TU_PIC_HAS_HW_RMW 0 #define TU_PIC_INT_SIZE 2 #else @@ -56,7 +52,7 @@ #endif -#if TU_PIC_HAS_MMU +#if TU_PIC_INT_SIZE == 4 #ifndef KVA_TO_PA #define KVA_TO_PA(kva) ((uint32_t)(kva) & 0x1fffffff) @@ -89,6 +85,8 @@ enum { TOK_PID_SETUP = 0xDu, }; +// The BDT is 8 bytes on 32bit PICs and 4 bytes on 8/16bit PICs +#if TU_PIC_INT_SIZE == 4 typedef struct TU_ATTR_PACKED { union { @@ -119,6 +117,37 @@ typedef struct TU_ATTR_PACKED } buffer_descriptor_t; TU_VERIFY_STATIC( sizeof(buffer_descriptor_t) == 8, "size is not correct" ); +#else +typedef struct TU_ATTR_PACKED +{ + union { + uint16_t head; + + struct { + uint16_t : 10; + uint16_t tok_pid : 4; + uint16_t data : 1; + uint16_t own : 1; + }; + struct { + uint16_t : 10; + uint16_t bdt_stall : 1; + uint16_t dts : 1; + uint16_t ninc : 1; + uint16_t keep : 1; + }; + + struct { + uint16_t bc : 10; + uint16_t : 6; + }; + }; + uint8_t *addr; +} buffer_descriptor_t; + +TU_VERIFY_STATIC( sizeof(buffer_descriptor_t) == 4, "size is not correct" ); +#endif + typedef struct TU_ATTR_PACKED { @@ -142,7 +171,11 @@ typedef struct union { /* [#EP][OUT,IN][EVEN,ODD] */ buffer_descriptor_t bdt[16][2][2]; - uint16_t bda[512]; +#if TU_PIC_INT_SIZE == 4 + uint16_t bda[256]; +#else + uint8_t bda[256]; +#endif }; TU_ATTR_ALIGNED(4) union { endpoint_state_t endpoint[16][2]; @@ -158,7 +191,11 @@ typedef struct // BDT(Buffer Descriptor Table) must be 256-byte aligned CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(512) volatile static dcd_data_t _dcd; +#if TU_PIC_INT_SIZE == 4 TU_VERIFY_STATIC( sizeof(_dcd.bdt) == 512, "size is not correct" ); +#else +TU_VERIFY_STATIC( sizeof(_dcd.bdt) == 256, "size is not correct" ); +#endif #if TU_PIC_INT_SIZE == 4 typedef uint32_t ep_reg_t; @@ -172,7 +209,12 @@ static inline volatile void *ep_addr(uint8_t rhport, uint8_t ep_num) { #else volatile void *ep_reg_base = &U1EP0; #endif - return ep_reg_base + 0x10 * ep_num; +#if TU_PIC_INT_SIZE == 4 + const size_t offset = 0x10; +#else + const size_t offset = 0x2; +#endif + return ep_reg_base + offset * ep_num; } static inline ep_reg_t ep_read(uint8_t rhport, uint8_t ep_num) { @@ -186,7 +228,7 @@ static inline void ep_write(uint8_t rhport, uint8_t ep_num, ep_reg_t val) { } static inline void ep_clear(uint8_t rhport, uint8_t ep_num, ep_reg_t val) { -#if TU_PIC_HAS_HW_RMW +#if TU_PIC_INT_SIZE == 4 volatile ep_reg_t *ep_clr = (ep_addr(rhport, ep_num) + 0x4); *ep_clr = val; #else @@ -197,7 +239,7 @@ static inline void ep_clear(uint8_t rhport, uint8_t ep_num, ep_reg_t val) { } static inline void ep_set(uint8_t rhport, uint8_t ep_num, ep_reg_t val) { -#if TU_PIC_HAS_HW_RMW +#if TU_PIC_INT_SIZE == 4 volatile ep_reg_t *ep_s = (ep_addr(rhport, ep_num) + 0x8); *ep_s = val; #else @@ -278,7 +320,7 @@ static void prepare_next_setup_packet(uint8_t rhport) _dcd.bdt[0][1][in_odd].data = 1; _dcd.bdt[0][1][in_odd ^ 1].data = 0; dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), - _dcd.setup_packet, sizeof(_dcd.setup_packet)); + _dcd.setup_packet, sizeof(_dcd.setup_packet)); } static void process_stall(uint8_t rhport) @@ -298,7 +340,7 @@ static void process_stall(uint8_t rhport) static void process_tokdne(uint8_t rhport) { - uint32_t s = U1STAT; + ep_reg_t s = U1STAT; U1IR = _U1IR_TRNIF_MASK; @@ -321,7 +363,11 @@ static void process_tokdne(uint8_t rhport) ep->odd = odd ^ 1; if (pid == TOK_PID_SETUP) { dcd_event_setup_received(rhport, (uint8_t *)PA_TO_KVA1(bd->addr), true); +#if TU_PIC_INT_SIZE == 4 U1CONCLR = _U1CON_PKTDIS_TOKBUSY_MASK; +#else + U1CONbits.PKTDIS = 0; +#endif return; } @@ -341,8 +387,8 @@ static void process_tokdne(uint8_t rhport) } const unsigned length = ep->length; dcd_event_xfer_complete(rhport, - tu_edpt_addr(epnum, dir), - length - remaining, XFER_RESULT_SUCCESS, true); + tu_edpt_addr(epnum, dir), + length - remaining, XFER_RESULT_SUCCESS, true); if (0 == epnum && 0 == length) { /* After completion a ZLP of control transfer, * it prepares for the next steup transfer. */ @@ -358,11 +404,16 @@ static void process_tokdne(uint8_t rhport) static void process_bus_reset(uint8_t rhport) { +#if TU_PIC_INT_SIZE == 4 U1PWRCCLR = _U1PWRC_USUSPEND_MASK; U1CONSET = _U1CON_PPBRST_MASK; +#else + U1PWRCbits.USUSPND = 0; + U1CONbits.PPBRST = 1; +#endif U1ADDR = 0; - U1IE = _U1IE_URSTIE_DETACHIE_MASK | _U1IE_TRNIE_MASK | _U1IE_IDLEIE_MASK | + U1IE = _U1IE_URSTIE_MASK | _U1IE_TRNIE_MASK | _U1IE_IDLEIE_MASK | _U1IE_UERRIE_MASK | _U1IE_STALLIE_MASK; U1EP0 = _U1EP0_EPHSHK_MASK | _U1EP0_EPRXEN_MASK | _U1EP0_EPTXEN_MASK; @@ -386,7 +437,11 @@ static void process_bus_reset(uint8_t rhport) tu_memclr(_dcd.endpoint[1], sizeof(_dcd.endpoint) - sizeof(_dcd.endpoint[0])); _dcd.addr = 0; prepare_next_setup_packet(rhport); +#if TU_PIC_INT_SIZE == 4 U1CONCLR = _U1CON_PPBRST_MASK; +#else + U1CONbits.PPBRST = 0; +#endif dcd_event_bus_reset(rhport, TUSB_SPEED_FULL, true); } @@ -399,9 +454,15 @@ static void process_bus_sleep(uint8_t rhport) static void process_bus_resume(uint8_t rhport) { // Enable suspend & disable resume interrupt +#if TU_PIC_INT_SIZE == 4 U1PWRCCLR = _U1PWRC_USUSPEND_MASK; U1IECLR = _U1IE_RESUMEIE_MASK; U1IESET = _U1IE_IDLEIE_MASK; +#else + U1PWRCbits.USUSPND = 0; + U1IEbits.RESUMEIE = 0; + U1IEbits.IDLEIE = 1; +#endif dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); } @@ -418,26 +479,29 @@ void dcd_init(uint8_t rhport) TRISBbits.TRISB6 = 1; #endif -#if (CFG_TUSB_MCU == OPT_MCU_PIC32MX) || (CFG_TUSB_MCU == OPT_MCU_PIC32MM) - U1PWRCSET = _U1PWRC_USBPWR_MASK; -#elif CFG_TUSB_MCU == OPT_MCU_PIC32MK - // TODO -#elif (CFG_TUSB_MCU == OPT_MCU_PIC24) || (CFG_TUSB_MCU == OPT_MCU_DSPIC33) - U1PWRCbits.USBPWR = 1; -#endif - tu_memclr(&_dcd, sizeof(_dcd)); +#if TU_PIC_INT_SIZE == 4 + U1PWRCSET = _U1PWRC_USBPWR_MASK; +#else + U1PWRCbits.USBPWR = 1; +#endif + +#if TU_PIC_INT_SIZE == 4 uint32_t bdt_phys = KVA_TO_PA((uintptr_t)_dcd.bdt); U1BDTP1 = (uint8_t)(bdt_phys >> 8); U1BDTP2 = (uint8_t)(bdt_phys >> 16); U1BDTP3 = (uint8_t)(bdt_phys >> 24); +#else + U1BDTP1 = (uint8_t)((uint16_t)(void *)_dcd.bdt >> 8); - U1IE = _U1IE_URSTIE_DETACHIE_MASK; + U1CNFG1bits.PPB = 2; +#endif + + U1IE = _U1IE_URSTIE_MASK; dcd_connect(rhport); - } void dcd_int_enable(uint8_t rhport) @@ -459,18 +523,30 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) void dcd_remote_wakeup(uint8_t rhport) { +#if TU_PIC_INT_SIZE == 4 U1CONSET = _U1CON_RESUME_MASK; - +#else + U1CONbits.RESUME = 1; +#endif unsigned cnt = 25000000 / 1000; while (cnt--) asm volatile("nop"); +#if TU_PIC_INT_SIZE == 4 U1CONCLR = _U1CON_RESUME_MASK; +#else + U1CONbits.RESUME = 0; +#endif } void dcd_connect(uint8_t rhport) { - while (!U1CONbits.USBEN) + while (!U1CONbits.USBEN) { +#if TU_PIC_INT_SIZE == 4 U1CONSET = _U1CON_USBEN_SOFEN_MASK; +#else + U1CONbits.USBEN = 1; +#endif + } } void dcd_disconnect(uint8_t rhport) @@ -502,14 +578,14 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) ep->max_packet_size = tu_edpt_packet_size(ep_desc); + unsigned val = _U1EP0_EPCONDIS_MASK; val |= (xfer != TUSB_XFER_ISOCHRONOUS) ? _U1EP0_EPHSHK_MASK : 0; val |= dir ? _U1EP0_EPTXEN_MASK : _U1EP0_EPRXEN_MASK; - volatile void *ep_reg_base = &U1EP0; - volatile uint32_t *reg_ep = (ep_reg_base + 0x10 * epn); - - *reg_ep |= val; + ep_reg_t tmp = ep_read(rhport, epn); + tmp |= val; + ep_write(rhport, epn, tmp); if (xfer != TUSB_XFER_ISOCHRONOUS) { bd[odd].dts = 1; @@ -569,6 +645,7 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { + const unsigned epn = tu_edpt_number(ep_addr); const unsigned dir = tu_edpt_dir(ep_addr); endpoint_state_t *ep = &_dcd.endpoint[epn][dir]; @@ -593,7 +670,6 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to } bd->bc = total_bytes >= mps ? mps: total_bytes; bd->addr = (uint8_t *)KVA_TO_PA(buffer); -// __DSB(); bd->own = 1; /* This bit must be set last */ if (ie) intr_enable(rhport); @@ -673,7 +749,7 @@ void dcd_int_handler(uint8_t rhport) U1IR = is; /* discard any pending events */ } - if (is & _U1IR_URSTIF_DETACHIF_MASK) { + if (is & _U1IR_URSTIF_MASK) { U1IR = is; /* discard any pending events */ process_bus_reset(rhport); } @@ -705,7 +781,6 @@ void dcd_int_handler(uint8_t rhport) } intr_clear(rhport); - } #endif