diff options
| author | Ha Thach <[email protected]> | 2026-03-07 15:29:23 +0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-03-07 15:29:23 +0700 |
| commit | d65964ea32b8081cbc5f2533296c68a90ec1b84f (patch) | |
| tree | 8570ec4ceecc56403e5bdc449da023e744f25510 | |
| parent | 5f69034631491cfd4dabe1a0051721f073a6f91c (diff) | |
| parent | 1c53009dc70e8535347f83cd9f3024ea495a085c (diff) | |
Merge pull request #3519 from hathach/samx7x_update
refresh dcd_samx7x
| -rw-r--r-- | examples/device/audio_4_channel_mic_freertos/skip.txt | 1 | ||||
| -rw-r--r-- | examples/device/audio_test_freertos/skip.txt | 1 | ||||
| -rw-r--r-- | examples/device/cdc_msc_freertos/skip.txt | 1 | ||||
| -rw-r--r-- | examples/device/hid_composite_freertos/skip.txt | 1 | ||||
| -rw-r--r-- | examples/device/midi_test_freertos/skip.txt | 1 | ||||
| -rw-r--r-- | hw/bsp/same7x/boards/same70_qmtech/board.cmake | 7 | ||||
| -rw-r--r-- | hw/bsp/same7x/boards/same70_qmtech/board.mk | 5 | ||||
| -rw-r--r-- | hw/bsp/same7x/boards/same70_xplained/board.cmake | 6 | ||||
| -rw-r--r-- | hw/bsp/same7x/boards/same70_xplained/board.mk | 5 | ||||
| -rw-r--r-- | hw/bsp/same7x/family.c | 85 | ||||
| -rw-r--r-- | hw/bsp/same7x/family.cmake | 20 | ||||
| -rw-r--r-- | hw/bsp/same7x/family.mk | 7 | ||||
| -rw-r--r-- | src/common/tusb_mcu.h | 4 | ||||
| -rw-r--r-- | src/portable/microchip/samx7x/dcd_samx7x.c | 679 | ||||
| -rw-r--r-- | src/portable/microchip/samx7x/samx7x_common.h (renamed from src/portable/microchip/samx7x/common_usb_regs.h) | 69 | ||||
| -rw-r--r-- | src/tusb_option.h | 18 |
16 files changed, 403 insertions, 507 deletions
diff --git a/examples/device/audio_4_channel_mic_freertos/skip.txt b/examples/device/audio_4_channel_mic_freertos/skip.txt index 4c2780096..db01347ed 100644 --- a/examples/device/audio_4_channel_mic_freertos/skip.txt +++ b/examples/device/audio_4_channel_mic_freertos/skip.txt @@ -9,7 +9,6 @@ mcu:MKL25ZXX mcu:MSP430x5xx mcu:RP2040 mcu:SAMD11 -mcu:SAMX7X mcu:VALENTYUSB_EPTRI mcu:RAXXX mcu:STM32L0 diff --git a/examples/device/audio_test_freertos/skip.txt b/examples/device/audio_test_freertos/skip.txt index 2da7808e7..7463aa86a 100644 --- a/examples/device/audio_test_freertos/skip.txt +++ b/examples/device/audio_test_freertos/skip.txt @@ -9,7 +9,6 @@ mcu:MKL25ZXX mcu:MSP430x5xx mcu:RP2040 mcu:SAMD11 -mcu:SAMX7X mcu:VALENTYUSB_EPTRI mcu:RAXXX family:broadcom_32bit diff --git a/examples/device/cdc_msc_freertos/skip.txt b/examples/device/cdc_msc_freertos/skip.txt index d90741df7..d3a096eb0 100644 --- a/examples/device/cdc_msc_freertos/skip.txt +++ b/examples/device/cdc_msc_freertos/skip.txt @@ -9,7 +9,6 @@ mcu:MKL25ZXX mcu:MSP430x5xx mcu:RP2040 mcu:SAMD11 -mcu:SAMX7X mcu:VALENTYUSB_EPTRI mcu:RAXXX mcu:STM32L0 diff --git a/examples/device/hid_composite_freertos/skip.txt b/examples/device/hid_composite_freertos/skip.txt index 01990a5b4..06920db67 100644 --- a/examples/device/hid_composite_freertos/skip.txt +++ b/examples/device/hid_composite_freertos/skip.txt @@ -9,7 +9,6 @@ mcu:MKL25ZXX mcu:MSP430x5xx mcu:RP2040 mcu:SAMD11 -mcu:SAMX7X mcu:VALENTYUSB_EPTRI mcu:RAXXX family:broadcom_32bit diff --git a/examples/device/midi_test_freertos/skip.txt b/examples/device/midi_test_freertos/skip.txt index 01990a5b4..06920db67 100644 --- a/examples/device/midi_test_freertos/skip.txt +++ b/examples/device/midi_test_freertos/skip.txt @@ -9,7 +9,6 @@ mcu:MKL25ZXX mcu:MSP430x5xx mcu:RP2040 mcu:SAMD11 -mcu:SAMX7X mcu:VALENTYUSB_EPTRI mcu:RAXXX family:broadcom_32bit diff --git a/hw/bsp/same7x/boards/same70_qmtech/board.cmake b/hw/bsp/same7x/boards/same70_qmtech/board.cmake index cde4c3da6..fc2071b3a 100644 --- a/hw/bsp/same7x/boards/same70_qmtech/board.cmake +++ b/hw/bsp/same7x/boards/same70_qmtech/board.cmake @@ -1,5 +1,8 @@ -set(JLINK_DEVICE SAME70N19B) -set(LD_FILE_GNU ${TOP}/hw/mcu/microchip/same70/same70b/gcc/gcc/same70q21b_flash.ld) +set(JLINK_DEVICE ATSAME70N19B) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/same70n19b_flash.ld) + +# N19B and Q21B share the same vector table / startup code +set(STARTUP_FILE_GNU ${TOP}/hw/mcu/microchip/same70/same70b/gcc/gcc/startup_same70q21b.c) function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC diff --git a/hw/bsp/same7x/boards/same70_qmtech/board.mk b/hw/bsp/same7x/boards/same70_qmtech/board.mk index 09ae98860..4ad8212a8 100644 --- a/hw/bsp/same7x/boards/same70_qmtech/board.mk +++ b/hw/bsp/same7x/boards/same70_qmtech/board.mk @@ -1,3 +1,6 @@ CFLAGS += -D__SAME70N19B__ -JLINK_DEVICE = SAME70N19B +LD_FILE = $(BOARD_PATH)/same70n19b_flash.ld +STARTUP_FILE = $(SDK_DIR)/same70b/gcc/gcc/startup_same70q21b.c + +JLINK_DEVICE = ATSAME70N19B diff --git a/hw/bsp/same7x/boards/same70_xplained/board.cmake b/hw/bsp/same7x/boards/same70_xplained/board.cmake index b226b6c4f..f762464a6 100644 --- a/hw/bsp/same7x/boards/same70_xplained/board.cmake +++ b/hw/bsp/same7x/boards/same70_xplained/board.cmake @@ -1,5 +1,9 @@ -set(JLINK_DEVICE SAME70Q21B) +set(JLINK_DEVICE ATSAME70Q21B) set(LD_FILE_GNU ${TOP}/hw/mcu/microchip/same70/same70b/gcc/gcc/same70q21b_flash.ld) +set(LD_FILE_IAR ${TOP}/hw/mcu/microchip/same70/same70b/iar/config/linker/Microchip/atsame70q21b/flash.icf) + +set(STARTUP_FILE_GNU ${TOP}/hw/mcu/microchip/same70/same70b/gcc/gcc/startup_same70q21b.c) +set(STARTUP_FILE_IAR ${TOP}/hw/mcu/microchip/same70/same70b/iar/iar/startup_same70q21b.c) function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC diff --git a/hw/bsp/same7x/boards/same70_xplained/board.mk b/hw/bsp/same7x/boards/same70_xplained/board.mk index ca23a9be5..231d5d770 100644 --- a/hw/bsp/same7x/boards/same70_xplained/board.mk +++ b/hw/bsp/same7x/boards/same70_xplained/board.mk @@ -1,3 +1,6 @@ CFLAGS += -D__SAME70Q21B__ -JLINK_DEVICE = SAME70Q21B +LD_FILE = $(SDK_DIR)/same70b/gcc/gcc/same70q21b_flash.ld +STARTUP_FILE = $(SDK_DIR)/same70b/gcc/gcc/startup_same70q21b.c + +JLINK_DEVICE = ATSAME70Q21B diff --git a/hw/bsp/same7x/family.c b/hw/bsp/same7x/family.c index ff6ecf277..61c1792d1 100644 --- a/hw/bsp/same7x/family.c +++ b/hw/bsp/same7x/family.c @@ -42,56 +42,15 @@ static inline void board_vbus_set(uint8_t rhport, bool state); void _init(void); #include "board.h" -#ifndef LED_STATE_ON - #define LED_STATE_ON 1 -#endif - -#ifndef LED_PORT_CLOCK - #define LED_PORT_CLOCK ID_PIOA -#endif - -#ifndef BUTTON_PORT_CLOCK - #define BUTTON_PORT_CLOCK ID_PIOA -#endif - -#ifndef UART_PORT_CLOCK - #define UART_PORT_CLOCK ID_USART1 -#endif - -#ifndef BOARD_USART - #define BOARD_USART USART1 -#endif - -#ifndef BOARD_UART_DESCRIPTOR - #define BOARD_UART_DESCRIPTOR edbg_com -#endif - -#ifndef BOARD_UART_BUFFER - #define BOARD_UART_BUFFER edbg_com_buffer -#endif - -#ifndef BUTTON_STATE_ACTIVE - #define BUTTON_STATE_ACTIVE 0 -#endif - -#ifndef UART_TX_FUNCTION - #define UART_TX_FUNCTION MUX_PB4D_USART1_TXD1 -#endif - -#ifndef UART_RX_FUNCTION - #define UART_RX_FUNCTION MUX_PA21A_USART1_RXD1 -#endif - #ifndef UART_BUFFER_SIZE #define UART_BUFFER_SIZE 64 #endif #define LED_STATE_OFF (1 - LED_STATE_ON) -static struct usart_async_descriptor BOARD_UART_DESCRIPTOR; -static uint8_t BOARD_UART_BUFFER[UART_BUFFER_SIZE]; +static struct usart_async_descriptor edbg_com; +static uint8_t edbg_com_buffer[UART_BUFFER_SIZE]; static volatile bool uart_busy = false; - static void tx_complete_cb(const struct usart_async_descriptor *const io_descr) { (void) io_descr; uart_busy = false; @@ -121,10 +80,10 @@ void board_init(void) { gpio_set_pin_function(UART_RX_PIN, UART_RX_FUNCTION); gpio_set_pin_function(UART_TX_PIN, UART_TX_FUNCTION); - usart_async_init(&BOARD_UART_DESCRIPTOR, BOARD_USART, BOARD_UART_BUFFER, sizeof(BOARD_UART_BUFFER), _usart_get_usart_async()); - usart_async_set_baud_rate(&BOARD_UART_DESCRIPTOR, CFG_BOARD_UART_BAUDRATE); - usart_async_register_callback(&BOARD_UART_DESCRIPTOR, USART_ASYNC_TXC_CB, tx_complete_cb); - usart_async_enable(&BOARD_UART_DESCRIPTOR); + usart_async_init(&edbg_com, BOARD_USART, edbg_com_buffer, sizeof(edbg_com_buffer), _usart_get_usart_async()); + usart_async_set_baud_rate(&edbg_com, CFG_BOARD_UART_BAUDRATE); + usart_async_register_callback(&edbg_com, USART_ASYNC_TXC_CB, tx_complete_cb); + usart_async_enable(&edbg_com); #if CFG_TUSB_OS == OPT_OS_NONE // 1ms tick timer (SystemCoreClock may not be correct after init) @@ -181,10 +140,40 @@ int board_uart_write(void const *buf, int len) { while (uart_busy) {} uart_busy = true; - io_write(&BOARD_UART_DESCRIPTOR.io, buf, len); + io_write(&edbg_com.io, buf, len); return len; } +// Read 128-bit unique ID via EFC STUI/SPUI commands +// Must run from RAM since STUI remaps flash to the unique ID +__attribute__((noinline)) TU_ATTR_SECTION(.ramfunc) static void read_unique_id(uint32_t uid[4]) { + // Wait for flash to be ready + while (!(EFC->EEFC_FSR & EEFC_FSR_FRDY)) {} + + // Issue Start Read Unique Identifier command + EFC->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_STUI; + while (EFC->EEFC_FSR & EEFC_FSR_FRDY) {} + + // Read 128-bit unique ID from flash base address + const volatile uint32_t *flash = (const volatile uint32_t *) IFLASH_ADDR; + for (int i = 0; i < 4; i++) { + uid[i] = flash[i]; + } + + // Issue Stop Read Unique Identifier command + EFC->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_SPUI; + while (!(EFC->EEFC_FSR & EEFC_FSR_FRDY)) {} +} + +size_t board_get_unique_id(uint8_t id[], size_t max_len) { + const size_t uid_len = 16; + if (max_len < uid_len) { + return 0; + } + read_unique_id((uint32_t *)(uintptr_t) id); + return uid_len; +} + #if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; diff --git a/hw/bsp/same7x/family.cmake b/hw/bsp/same7x/family.cmake index a9c9de413..63726a8e5 100644 --- a/hw/bsp/same7x/family.cmake +++ b/hw/bsp/same7x/family.cmake @@ -13,7 +13,6 @@ set(FAMILY_MCUS SAMX7X CACHE INTERNAL "") #------------------------------------ # Startup & Linker script #------------------------------------ -set(STARTUP_FILE_GNU ${SDK_DIR}/same70b/gcc/gcc/startup_same70q21b.c) set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) set(LD_FILE_Clang ${LD_FILE_GNU}) @@ -47,12 +46,9 @@ function(family_add_board BOARD_TARGET) update_board(${BOARD_TARGET}) - target_compile_options(${BOARD_TARGET} PUBLIC - -Wno-error=unused-parameter - -Wno-error=cast-align - -Wno-error=redundant-decls - -Wno-error=cast-qual - ) + if (TOOLCHAIN STREQUAL "gcc" OR TOOLCHAIN STREQUAL "clang") + set_target_properties(${BOARD_TARGET} PROPERTIES COMPILE_FLAGS -Wno-error=cast-qual) + endif () endfunction() #------------------------------------ @@ -89,9 +85,13 @@ function(family_configure_example TARGET RTOS) "LINKER:--config=${LD_FILE_IAR}" ) endif () - set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} PROPERTIES - SKIP_LINTING ON - COMPILE_OPTIONS -w) + if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + # ignore hal error + set_source_files_properties(${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + PROPERTIES + SKIP_LINTING ON + COMPILE_OPTIONS -w) + endif() family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) diff --git a/hw/bsp/same7x/family.mk b/hw/bsp/same7x/family.mk index c8fa74d71..19e119625 100644 --- a/hw/bsp/same7x/family.mk +++ b/hw/bsp/same7x/family.mk @@ -21,11 +21,9 @@ CFLAGS_SKIP += -Wcast-qual LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs # All source paths should be relative to the top level. -LD_FILE = $(SDK_DIR)/same70b/gcc/gcc/same70q21b_flash.ld - SRC_C += \ src/portable/microchip/samx7x/dcd_samx7x.c \ - $(SDK_DIR)/same70b/gcc/gcc/startup_same70q21b.c \ + $(STARTUP_FILE) \ $(SDK_DIR)/same70b/gcc/system_same70q21b.c \ $(SDK_DIR)/hpl/core/hpl_init.c \ $(SDK_DIR)/hpl/usart/hpl_usart.c \ @@ -48,9 +46,6 @@ INC += \ $(TOP)/$(SDK_DIR)/hri \ $(TOP)/$(SDK_DIR)/CMSIS/Core/Include -# For freeRTOS port source -FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM7 - # For flash-jlink target flash: $(BUILD)/$(PROJECT).bin edbg --verbose -t same70 -pv -f $< diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 5b9497b9a..32f7eb557 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -172,6 +172,10 @@ #define TUP_RHPORT_HIGHSPEED 1 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY + // Enable dcache if DMA is enabled + #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT CFG_TUD_SAMX7X_DMA_ENABLE + #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 32 + #elif TU_CHECK_MCU(OPT_MCU_PIC32MZ) #define TUP_DCD_ENDPOINT_MAX 8 #define TUD_ENDPOINT_ONE_DIRECTION_ONLY diff --git a/src/portable/microchip/samx7x/dcd_samx7x.c b/src/portable/microchip/samx7x/dcd_samx7x.c index b0a053c01..6da1e9778 100644 --- a/src/portable/microchip/samx7x/dcd_samx7x.c +++ b/src/portable/microchip/samx7x/dcd_samx7x.c @@ -1,133 +1,117 @@ /* -* The MIT License (MIT) -* -* Copyright (c) 2018, hathach (tinyusb.org) -* Copyright (c) 2021, HiFiPhile -* -* 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. -*/ + * The MIT License (MIT) + * + * Copyright (c) 2018, hathach (tinyusb.org) + * Copyright (c) 2021, HiFiPhile + * + * 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. + */ #include "tusb_option.h" #if CFG_TUD_ENABLED && CFG_TUSB_MCU == OPT_MCU_SAMX7X -#include "device/dcd.h" -#include "sam.h" -#include "common_usb_regs.h" -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ - -// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) -// We disable SOF for now until needed later on -#ifndef USE_SOF -# define USE_SOF 0 -#endif - -// Dual bank can improve performance, but need 2 times bigger packet buffer -// As SAM7x has only 4KB packet buffer, use with caution ! -// Enable in FS mode as packets are smaller -#ifndef USE_DUAL_BANK -# if TUD_OPT_HIGH_SPEED -# define USE_DUAL_BANK 0 -# else -# define USE_DUAL_BANK 1 -# endif -#endif + #include "device/dcd.h" + #include "sam.h" + #include "samx7x_common.h" + //--------------------------------------------------------------------+ + // MACRO TYPEDEF CONSTANT ENUM DECLARATION + //--------------------------------------------------------------------+ -#define EP_GET_FIFO_PTR(ep, scale) (((TU_XSTRCAT(TU_STRCAT(uint, scale),_t) (*)[0x8000 / ((scale) / 8)])FIFO_RAM_ADDR)[(ep)]) + // Dual bank can improve performance, but need 2 times bigger packet buffer + // As SAM7x has only 4KB packet buffer, use with caution ! + // Enable in FS mode as packets are smaller + #ifndef USE_DUAL_BANK + #if TUD_OPT_HIGH_SPEED + #define USE_DUAL_BANK 0 + #else + #define USE_DUAL_BANK 1 + #endif + #endif -// DMA Channel Transfer Descriptor -typedef struct { - volatile uint32_t next_desc; - volatile uint32_t buff_addr; - volatile uint32_t chnl_ctrl; - uint32_t padding; -} dma_desc_t; + #define EP_GET_FIFO_PTR(ep, scale) \ + (((TU_XSTRCAT(TU_STRCAT(uint, scale), _t)(*)[0x8000 / ((scale) / 8)]) FIFO_RAM_ADDR)[(ep)]) // Transfer control context typedef struct { - uint8_t * buffer; - uint16_t total_len; - uint16_t queued_len; - uint16_t max_packet_size; - uint8_t interval; - tu_fifo_t * fifo; + uint8_t *buffer; + uint16_t total_len; + uint16_t queued_len; + uint16_t max_packet_size; + uint8_t interval; + tu_fifo_t *fifo; } xfer_ctl_t; static tusb_speed_t get_speed(void); -static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix); - -// DMA descriptors shouldn't be placed in ITCM ! -CFG_TUD_MEM_SECTION static dma_desc_t dma_desc[6]; +static void dcd_transmit_packet(xfer_ctl_t *xfer, uint8_t ep_ix); static xfer_ctl_t xfer_status[EP_MAX]; -static const tusb_desc_endpoint_t ep0_desc = -{ +static const tusb_desc_endpoint_t ep0_desc = { .bEndpointAddress = 0x00, .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, }; -TU_ATTR_ALWAYS_INLINE static inline void CleanInValidateCache(uint32_t *addr, int32_t size) -{ - if (SCB->CCR & SCB_CCR_DC_Msk) - { - SCB_CleanInvalidateDCache_by_Addr(addr, size); - } - else - { - __DSB(); - __ISB(); - } + #if CFG_TUD_MEM_DCACHE_ENABLE +bool dcd_dcache_clean(const void *addr, uint32_t data_size) { + TU_VERIFY(addr && data_size); + return samx7x_dcache_clean(addr, data_size); } + +bool dcd_dcache_invalidate(const void *addr, uint32_t data_size) { + TU_VERIFY(addr && data_size); + return samx7x_dcache_invalidate(addr, data_size); +} + +bool dcd_dcache_clean_invalidate(const void *addr, uint32_t data_size) { + TU_VERIFY(addr && data_size); + return samx7x_dcache_clean_invalidate(addr, data_size); +} + #endif //------------------------------------------------------------------ // Device API //------------------------------------------------------------------ // Initialize controller to device mode -bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rh_init; +bool dcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { + (void)rh_init; dcd_connect(rhport); return true; } // Enable device interrupt -void dcd_int_enable (uint8_t rhport) -{ - (void) rhport; - NVIC_EnableIRQ((IRQn_Type) ID_USBHS); +void dcd_int_enable(uint8_t rhport) { + (void)rhport; + NVIC_EnableIRQ((IRQn_Type)ID_USBHS); } // Disable device interrupt -void dcd_int_disable (uint8_t rhport) -{ - (void) rhport; - NVIC_DisableIRQ((IRQn_Type) ID_USBHS); +void dcd_int_disable(uint8_t rhport) { + (void)rhport; + NVIC_DisableIRQ((IRQn_Type)ID_USBHS); } // Receive Set Address request, mcu port must also include status IN response -void dcd_set_address (uint8_t rhport, uint8_t dev_addr) -{ - (void) dev_addr; +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { + (void)dev_addr; // DCD can only set address after status for this request is complete // do it at dcd_edpt0_status_complete() @@ -136,30 +120,26 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr) } // Wake up host -void dcd_remote_wakeup (uint8_t rhport) -{ - (void) rhport; +void dcd_remote_wakeup(uint8_t rhport) { + (void)rhport; USB_REG->DEVCTRL |= DEVCTRL_RMWKUP; } // Connect by enabling internal pull-up resistor on D+/D- -void dcd_connect(uint8_t rhport) -{ - (void) rhport; +void dcd_connect(uint8_t rhport) { + (void)rhport; dcd_int_disable(rhport); // Enable the USB controller in device mode USB_REG->CTRL = CTRL_UIMOD | CTRL_USBE; - while (!(USB_REG->SR & SR_CLKUSABLE)); -#if TUD_OPT_HIGH_SPEED + while (!(USB_REG->SR & SR_CLKUSABLE)) + ; + #if TUD_OPT_HIGH_SPEED USB_REG->DEVCTRL &= ~DEVCTRL_SPDCONF; -#else + #else USB_REG->DEVCTRL |= DEVCTRL_SPDCONF_LOW_POWER; -#endif + #endif // Enable the End Of Reset, Suspend & Wakeup interrupts USB_REG->DEVIER = (DEVIER_EORSTES | DEVIER_SUSPES | DEVIER_WAKEUPES); -#if USE_SOF - USB_REG->DEVIER = DEVIER_SOFES; -#endif // Clear the End Of Reset, SOF & Wakeup interrupts USB_REG->DEVICR = (DEVICR_EORSTC | DEVICR_SOFC | DEVICR_WAKEUPC); // Manually set the Suspend Interrupt @@ -173,15 +153,15 @@ void dcd_connect(uint8_t rhport) } // Disconnect by disabling internal pull-up resistor on D+/D- -void dcd_disconnect(uint8_t rhport) -{ - (void) rhport; +void dcd_disconnect(uint8_t rhport) { + (void)rhport; dcd_int_disable(rhport); // Disable all endpoints USB_REG->DEVEPT &= ~(0x3FF << DEVEPT_EPEN0_Pos); // Unfreeze USB clock USB_REG->CTRL &= ~CTRL_FRZCLK; - while (!(USB_REG->SR & SR_CLKUSABLE)); + while (!(USB_REG->SR & SR_CLKUSABLE)) + ; // Clear all the pending interrupts USB_REG->DEVICR = DEVICR_Msk; // Disable all interrupts @@ -189,127 +169,106 @@ void dcd_disconnect(uint8_t rhport) // Detach the device USB_REG->DEVCTRL |= DEVCTRL_DETACH; // Disable the device address - USB_REG->DEVCTRL &=~(DEVCTRL_ADDEN | DEVCTRL_UADD); + USB_REG->DEVCTRL &= ~(DEVCTRL_ADDEN | DEVCTRL_UADD); } -void dcd_sof_enable(uint8_t rhport, bool en) -{ - (void) rhport; - (void) en; - - // TODO implement later +void dcd_sof_enable(uint8_t rhport, bool en) { + (void)rhport; + if (en) { + USB_REG->DEVIER = DEVIER_SOFES; + } else { + USB_REG->DEVIDR = DEVIDR_SOFEC; + } } -static tusb_speed_t get_speed(void) -{ +static tusb_speed_t get_speed(void) { switch (USB_REG->SR & SR_SPEED) { - case SR_SPEED_FULL_SPEED: - default: - return TUSB_SPEED_FULL; - case SR_SPEED_HIGH_SPEED: - return TUSB_SPEED_HIGH; - case SR_SPEED_LOW_SPEED: - return TUSB_SPEED_LOW; + case SR_SPEED_FULL_SPEED: + default: + return TUSB_SPEED_FULL; + case SR_SPEED_HIGH_SPEED: + return TUSB_SPEED_HIGH; + case SR_SPEED_LOW_SPEED: + return TUSB_SPEED_LOW; } } -static void dcd_ep_handler(uint8_t ep_ix) -{ +static void dcd_ep_handler(uint8_t ep_ix) { uint32_t int_status = USB_REG->DEVEPTISR[ep_ix]; int_status &= USB_REG->DEVEPTIMR[ep_ix]; - uint16_t count = (USB_REG->DEVEPTISR[ep_ix] & - DEVEPTISR_BYCT) >> DEVEPTISR_BYCT_Pos; - xfer_ctl_t *xfer = &xfer_status[ep_ix]; + uint16_t count = (USB_REG->DEVEPTISR[ep_ix] & DEVEPTISR_BYCT) >> DEVEPTISR_BYCT_Pos; + xfer_ctl_t *xfer = &xfer_status[ep_ix]; - if (ep_ix == 0U) - { + if (ep_ix == 0U) { static uint8_t ctrl_dir; - if (int_status & DEVEPTISR_CTRL_RXSTPI) - { + if (int_status & DEVEPTISR_CTRL_RXSTPI) { ctrl_dir = (USB_REG->DEVEPTISR[0] & DEVEPTISR_CTRL_CTRLDIR) >> DEVEPTISR_CTRL_CTRLDIR_Pos; // Setup packet should always be 8 bytes. If not, ignore it, and try again. - if (count == 8) - { - uint8_t *ptr = EP_GET_FIFO_PTR(0,8); + if (count == 8) { + uint8_t *ptr = EP_GET_FIFO_PTR(0, 8); dcd_event_setup_received(0, ptr, true); } // Ack and disable SETUP interrupt USB_REG->DEVEPTICR[0] = DEVEPTICR_CTRL_RXSTPIC; USB_REG->DEVEPTIDR[0] = DEVEPTIDR_CTRL_RXSTPEC; } - if (int_status & DEVEPTISR_RXOUTI) - { - uint8_t *ptr = EP_GET_FIFO_PTR(0,8); + if (int_status & DEVEPTISR_RXOUTI) { + uint8_t *ptr = EP_GET_FIFO_PTR(0, 8); - if (count && xfer->total_len) - { + if (count && xfer->total_len) { uint16_t remain = xfer->total_len - xfer->queued_len; - if (count > remain) - { + if (count > remain) { count = remain; } - if (xfer->buffer) - { + if (xfer->buffer) { memcpy(xfer->buffer + xfer->queued_len, ptr, count); - } else - { - tu_fifo_write_n(xfer->fifo, ptr, count); + } else { + tu_hwfifo_read_to_fifo(ptr, xfer->fifo, count, NULL); } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } // Acknowledge the interrupt USB_REG->DEVEPTICR[0] = DEVEPTICR_RXOUTIC; - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) - { + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { // RX COMPLETE dcd_event_xfer_complete(0, 0, xfer->queued_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt USB_REG->DEVEPTIDR[0] = DEVEPTIDR_RXOUTEC; // Re-enable SETUP interrupt - if (ctrl_dir == 1) - { + if (ctrl_dir == 1) { USB_REG->DEVEPTIER[0] = DEVEPTIER_CTRL_RXSTPES; } } } - if (int_status & DEVEPTISR_TXINI) - { + if (int_status & DEVEPTISR_TXINI) { // Disable the interrupt USB_REG->DEVEPTIDR[0] = DEVEPTIDR_TXINEC; - if ((xfer->total_len != xfer->queued_len)) - { + if ((xfer->total_len != xfer->queued_len)) { // TX not complete dcd_transmit_packet(xfer, 0); - } else - { + } else { // TX complete dcd_event_xfer_complete(0, 0x80 + 0, xfer->total_len, XFER_RESULT_SUCCESS, true); // Re-enable SETUP interrupt - if (ctrl_dir == 0) - { + if (ctrl_dir == 0) { USB_REG->DEVEPTIER[0] = DEVEPTIER_CTRL_RXSTPES; } } } - } else - { - if (int_status & DEVEPTISR_RXOUTI) - { - if (count && xfer->total_len) - { + } else { + if (int_status & DEVEPTISR_RXOUTI) { + if (count && xfer->total_len) { uint16_t remain = xfer->total_len - xfer->queued_len; - if (count > remain) - { + if (count > remain) { count = remain; } - uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); - if (xfer->buffer) - { + uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix, 8); + if (xfer->buffer) { memcpy(xfer->buffer + xfer->queued_len, ptr, count); } else { - tu_fifo_write_n(xfer->fifo, ptr, count); + tu_hwfifo_read_to_fifo(ptr, xfer->fifo, count, NULL); } xfer->queued_len = (uint16_t)(xfer->queued_len + count); } @@ -317,8 +276,7 @@ static void dcd_ep_handler(uint8_t ep_ix) USB_REG->DEVEPTIDR[ep_ix] = DEVEPTIDR_FIFOCONC; // Acknowledge the interrupt USB_REG->DEVEPTICR[ep_ix] = DEVEPTICR_RXOUTIC; - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) - { + if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { // RX COMPLETE dcd_event_xfer_complete(0, ep_ix, xfer->queued_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt @@ -326,16 +284,13 @@ static void dcd_ep_handler(uint8_t ep_ix) // Though the host could still send, we don't know. } } - if (int_status & DEVEPTISR_TXINI) - { + if (int_status & DEVEPTISR_TXINI) { // Acknowledge the interrupt USB_REG->DEVEPTICR[ep_ix] = DEVEPTICR_TXINIC; - if ((xfer->total_len != xfer->queued_len)) - { + if ((xfer->total_len != xfer->queued_len)) { // TX not complete dcd_transmit_packet(xfer, ep_ix); - } else - { + } else { // TX complete dcd_event_xfer_complete(0, 0x80 + ep_ix, xfer->total_len, XFER_RESULT_SUCCESS, true); // Disable the interrupt @@ -345,45 +300,40 @@ static void dcd_ep_handler(uint8_t ep_ix) } } -static void dcd_dma_handler(uint8_t ep_ix) -{ +static void dcd_dma_handler(uint8_t ep_ix) { uint32_t status = USB_REG->DEVDMA[ep_ix - 1].DEVDMASTATUS; - if (status & DEVDMASTATUS_CHANN_ENB) - { + if (status & DEVDMASTATUS_CHANN_ENB) { return; // Ignore EOT_STA interrupt } // Disable DMA interrupt USB_REG->DEVIDR = DEVIDR_DMA_1 << (ep_ix - 1); - xfer_ctl_t *xfer = &xfer_status[ep_ix]; - uint16_t count = xfer->total_len - ((status & DEVDMASTATUS_BUFF_COUNT) >> DEVDMASTATUS_BUFF_COUNT_Pos); - if(USB_REG->DEVEPTCFG[ep_ix] & DEVEPTCFG_EPDIR) - { + xfer_ctl_t *xfer = &xfer_status[ep_ix]; + uint16_t count = xfer->total_len - ((status & DEVDMASTATUS_BUFF_COUNT) >> DEVDMASTATUS_BUFF_COUNT_Pos); + if (USB_REG->DEVEPTCFG[ep_ix] & DEVEPTCFG_EPDIR) { dcd_event_xfer_complete(0, 0x80 + ep_ix, count, XFER_RESULT_SUCCESS, true); - } else - { + } else { + dcd_dcache_invalidate(xfer->buffer, count); dcd_event_xfer_complete(0, ep_ix, count, XFER_RESULT_SUCCESS, true); } } -void dcd_int_handler(uint8_t rhport) -{ - (void) rhport; +void dcd_int_handler(uint8_t rhport) { + (void)rhport; uint32_t int_status = USB_REG->DEVISR; int_status &= USB_REG->DEVIMR; // End of reset interrupt - if (int_status & DEVISR_EORST) - { + if (int_status & DEVISR_EORST) { // Unfreeze USB clock USB_REG->CTRL &= ~CTRL_FRZCLK; - while(!(USB_REG->SR & SR_CLKUSABLE)); + while (!(USB_REG->SR & SR_CLKUSABLE)) + ; // Reset all endpoints - for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) - { + for (int ep_ix = 1; ep_ix < EP_MAX; ep_ix++) { USB_REG->DEVEPT |= 1 << (DEVEPT_EPRST0_Pos + ep_ix); - USB_REG->DEVEPT &=~(1 << (DEVEPT_EPRST0_Pos + ep_ix)); + USB_REG->DEVEPT &= ~(1 << (DEVEPT_EPRST0_Pos + ep_ix)); } - dcd_edpt_open (0, &ep0_desc); + dcd_edpt_open(0, &ep0_desc); USB_REG->DEVICR = DEVICR_EORSTC; USB_REG->DEVICR = DEVICR_WAKEUPC; USB_REG->DEVICR = DEVICR_SUSPC; @@ -392,10 +342,10 @@ void dcd_int_handler(uint8_t rhport) dcd_event_bus_reset(rhport, get_speed(), true); } // End of Wakeup interrupt - if (int_status & DEVISR_WAKEUP) - { + if (int_status & DEVISR_WAKEUP) { USB_REG->CTRL &= ~CTRL_FRZCLK; - while (!(USB_REG->SR & SR_CLKUSABLE)); + while (!(USB_REG->SR & SR_CLKUSABLE)) + ; USB_REG->DEVICR = DEVICR_WAKEUPC; USB_REG->DEVIDR = DEVIDR_WAKEUPEC; USB_REG->DEVIER = DEVIER_SUSPES; @@ -403,11 +353,11 @@ void dcd_int_handler(uint8_t rhport) dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } // Suspend interrupt - if (int_status & DEVISR_SUSP) - { + if (int_status & DEVISR_SUSP) { // Unfreeze USB clock USB_REG->CTRL &= ~CTRL_FRZCLK; - while (!(USB_REG->SR & SR_CLKUSABLE)); + while (!(USB_REG->SR & SR_CLKUSABLE)) + ; USB_REG->DEVICR = DEVICR_SUSPC; USB_REG->DEVIDR = DEVIDR_SUSPEC; USB_REG->DEVIER = DEVIER_WAKEUPES; @@ -415,29 +365,21 @@ void dcd_int_handler(uint8_t rhport) dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } -#if USE_SOF - if(int_status & DEVISR_SOF) - { + if (int_status & DEVISR_SOF) { USB_REG->DEVICR = DEVICR_SOFC; dcd_event_bus_signal(0, DCD_EVENT_SOF, true); } -#endif // Endpoints interrupt - for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) - { - if (int_status & (DEVISR_PEP_0 << ep_ix)) - { + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { + if (int_status & (DEVISR_PEP_0 << ep_ix)) { dcd_ep_handler(ep_ix); } } // Endpoints DMA interrupt - for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) - { - if (EP_DMA_SUPPORT(ep_ix)) - { - if (int_status & (DEVISR_DMA_1 << (ep_ix - 1))) - { + for (int ep_ix = 0; ep_ix < EP_MAX; ep_ix++) { + if (EP_DMA_SUPPORT(ep_ix)) { + if (int_status & (DEVISR_DMA_1 << (ep_ix - 1))) { dcd_dma_handler(ep_ix); } } @@ -449,35 +391,29 @@ void dcd_int_handler(uint8_t rhport) //--------------------------------------------------------------------+ // Invoked when a control transfer's status stage is complete. // May help DCD to prepare for next control transfer, this API is optional. -void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request) -{ - (void) rhport; +void dcd_edpt0_status_complete(uint8_t rhport, const tusb_control_request_t *request) { + (void)rhport; if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && - request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && - request->bRequest == TUSB_REQ_SET_ADDRESS ) - { - uint8_t const dev_addr = (uint8_t) request->wValue; + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) { + const uint8_t dev_addr = (uint8_t)request->wValue; USB_REG->DEVCTRL |= dev_addr | DEVCTRL_ADDEN; } } // Configure endpoint's registers according to descriptor -bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_desc->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(ep_desc->bEndpointAddress); - uint16_t const epMaxPktSize = tu_edpt_packet_size(ep_desc); - tusb_xfer_type_t const eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; - uint8_t fifoSize = 0; // FIFO size - uint16_t defaultEndpointSize = 8; // Default size of Endpoint +bool dcd_edpt_open(uint8_t rhport, const tusb_desc_endpoint_t *ep_desc) { + (void)rhport; + const uint8_t epnum = tu_edpt_number(ep_desc->bEndpointAddress); + const uint8_t dir = tu_edpt_dir(ep_desc->bEndpointAddress); + const uint16_t epMaxPktSize = tu_edpt_packet_size(ep_desc); + const tusb_xfer_type_t eptype = (tusb_xfer_type_t)ep_desc->bmAttributes.xfer; + uint8_t fifoSize = 0; // FIFO size + uint16_t defaultEndpointSize = 8; // Default size of Endpoint // Find upper 2 power number of epMaxPktSize - if (epMaxPktSize) - { - while (defaultEndpointSize < epMaxPktSize) - { + if (epMaxPktSize) { + while (defaultEndpointSize < epMaxPktSize) { fifoSize++; defaultEndpointSize <<= 1; } @@ -485,121 +421,94 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) xfer_status[epnum].max_packet_size = epMaxPktSize; USB_REG->DEVEPT |= 1 << (DEVEPT_EPRST0_Pos + epnum); - USB_REG->DEVEPT &=~(1 << (DEVEPT_EPRST0_Pos + epnum)); + USB_REG->DEVEPT &= ~(1 << (DEVEPT_EPRST0_Pos + epnum)); - if (epnum == 0) - { + if (epnum == 0) { // Enable the control endpoint - Endpoint 0 USB_REG->DEVEPT |= DEVEPT_EPEN0; // Configure the Endpoint 0 configuration register - USB_REG->DEVEPTCFG[0] = - ( - (fifoSize << DEVEPTCFG_EPSIZE_Pos) | - (TUSB_XFER_CONTROL << DEVEPTCFG_EPTYPE_Pos) | - (DEVEPTCFG_EPBK_1_BANK << DEVEPTCFG_EPBK_Pos) | - DEVEPTCFG_ALLOC - ); + USB_REG->DEVEPTCFG[0] = ((fifoSize << DEVEPTCFG_EPSIZE_Pos) | (TUSB_XFER_CONTROL << DEVEPTCFG_EPTYPE_Pos) | + (DEVEPTCFG_EPBK_1_BANK << DEVEPTCFG_EPBK_Pos) | DEVEPTCFG_ALLOC); USB_REG->DEVEPTIER[0] = DEVEPTIER_RSTDTS; USB_REG->DEVEPTIDR[0] = DEVEPTIDR_CTRL_STALLRQC; - if (DEVEPTISR_CFGOK == (USB_REG->DEVEPTISR[0] & DEVEPTISR_CFGOK)) - { + if (DEVEPTISR_CFGOK == (USB_REG->DEVEPTISR[0] & DEVEPTISR_CFGOK)) { // Endpoint configuration is successful USB_REG->DEVEPTIER[0] = DEVEPTIER_CTRL_RXSTPES; // Enable Endpoint 0 Interrupts USB_REG->DEVIER = DEVIER_PEP_0; return true; - } else - { + } else { // Endpoint configuration is not successful return false; } - } else - { + } else { // Enable the endpoint USB_REG->DEVEPT |= ((0x01 << epnum) << DEVEPT_EPEN0_Pos); // Set up the maxpacket size, fifo start address fifosize // and enable the interrupt. CLear the data toggle. // AUTOSW is needed for DMA ack ! USB_REG->DEVEPTCFG[epnum] = - ( - (fifoSize << DEVEPTCFG_EPSIZE_Pos) | - (eptype << DEVEPTCFG_EPTYPE_Pos) | - (DEVEPTCFG_EPBK_1_BANK << DEVEPTCFG_EPBK_Pos) | - DEVEPTCFG_AUTOSW | - ((dir & 0x01) << DEVEPTCFG_EPDIR_Pos) - ); - if (eptype == TUSB_XFER_ISOCHRONOUS) - { + ((fifoSize << DEVEPTCFG_EPSIZE_Pos) | (eptype << DEVEPTCFG_EPTYPE_Pos) | + (DEVEPTCFG_EPBK_1_BANK << DEVEPTCFG_EPBK_Pos) | DEVEPTCFG_AUTOSW | ((dir & 0x01) << DEVEPTCFG_EPDIR_Pos)); + if (eptype == TUSB_XFER_ISOCHRONOUS) { USB_REG->DEVEPTCFG[epnum] |= DEVEPTCFG_NBTRANS_1_TRANS; } -#if USE_DUAL_BANK - if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK) - { + #if USE_DUAL_BANK + if (eptype == TUSB_XFER_ISOCHRONOUS || eptype == TUSB_XFER_BULK) { USB_REG->DEVEPTCFG[epnum] |= DEVEPTCFG_EPBK_2_BANK; } -#endif + #endif USB_REG->DEVEPTCFG[epnum] |= DEVEPTCFG_ALLOC; USB_REG->DEVEPTIER[epnum] = DEVEPTIER_RSTDTS; USB_REG->DEVEPTIDR[epnum] = DEVEPTIDR_CTRL_STALLRQC; - if (DEVEPTISR_CFGOK == (USB_REG->DEVEPTISR[epnum] & DEVEPTISR_CFGOK)) - { + if (DEVEPTISR_CFGOK == (USB_REG->DEVEPTISR[epnum] & DEVEPTISR_CFGOK)) { USB_REG->DEVIER = ((0x01 << epnum) << DEVIER_PEP_0_Pos); return true; - } else - { + } else { // Endpoint configuration is not successful return false; } } } -void dcd_edpt_close_all (uint8_t rhport) -{ - (void) rhport; +void dcd_edpt_close_all(uint8_t rhport) { + (void)rhport; // TODO implement dcd_edpt_close_all() } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { - (void) rhport; - (void) ep_addr; - (void) largest_packet_size; + (void)rhport; + (void)ep_addr; + (void)largest_packet_size; return false; } -bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep) { - (void) rhport; - (void) desc_ep; +bool dcd_edpt_iso_activate(uint8_t rhport, const tusb_desc_endpoint_t *desc_ep) { + (void)rhport; + (void)desc_ep; return false; } -static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) -{ +static void dcd_transmit_packet(xfer_ctl_t *xfer, uint8_t ep_ix) { uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); - if (len) - { - if (len > xfer->max_packet_size) - { + if (len) { + if (len > xfer->max_packet_size) { len = xfer->max_packet_size; } - uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix,8); - if(xfer->buffer) - { + uint8_t *ptr = EP_GET_FIFO_PTR(ep_ix, 8); + if (xfer->buffer) { memcpy(ptr, xfer->buffer + xfer->queued_len, len); - } - else - { - tu_fifo_read_n(xfer->fifo, ptr, len); + } else { + tu_hwfifo_write_from_fifo(ptr, xfer->fifo, len, NULL); } __DSB(); __ISB(); xfer->queued_len = (uint16_t)(xfer->queued_len + len); } - if (ep_ix == 0U) - { + if (ep_ix == 0U) { // Control endpoint: clear the interrupt flag to send the data USB_REG->DEVEPTICR[0] = DEVEPTICR_TXINIC; - } else - { + } else { // Other endpoint types: clear the FIFO control flag to send the data USB_REG->DEVEPTIDR[ep_ix] = DEVEPTIDR_FIFOCONC; } @@ -607,59 +516,36 @@ static void dcd_transmit_packet(xfer_ctl_t * xfer, uint8_t ep_ix) } // Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, bool is_isr) -{ - (void) is_isr; - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes, bool is_isr) { + (void)is_isr; + (void)rhport; + const uint8_t epnum = tu_edpt_number(ep_addr); + const uint8_t dir = tu_edpt_dir(ep_addr); - xfer_ctl_t * xfer = &xfer_status[epnum]; + xfer_ctl_t *xfer = &xfer_status[epnum]; - xfer->buffer = buffer; - xfer->total_len = total_bytes; + xfer->buffer = buffer; + xfer->total_len = total_bytes; xfer->queued_len = 0; - xfer->fifo = NULL; + xfer->fifo = NULL; - if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) - { - // Force the CPU to flush the buffer. We increase the size by 32 because the call aligns the - // address to 32-byte boundaries. - CleanInValidateCache((uint32_t*) tu_align((uint32_t) buffer, 4), total_bytes + 31); + if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) { uint32_t udd_dma_ctrl = total_bytes << DEVDMACONTROL_BUFF_LENGTH_Pos; - if (dir == TUSB_DIR_OUT) - { + if (dir == TUSB_DIR_OUT) { udd_dma_ctrl |= DEVDMACONTROL_END_TR_IT | DEVDMACONTROL_END_TR_EN; } else { udd_dma_ctrl |= DEVDMACONTROL_END_B_EN; + dcd_dcache_clean(xfer->buffer, total_bytes); } USB_REG->DEVDMA[epnum - 1].DEVDMAADDRESS = (uint32_t)buffer; udd_dma_ctrl |= DEVDMACONTROL_END_BUFFIT | DEVDMACONTROL_CHANN_ENB; - // Disable IRQs to have a short sequence - // between read of EOT_STA and DMA enable - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - if (!(USB_REG->DEVDMA[epnum - 1].DEVDMASTATUS & DEVDMASTATUS_END_TR_ST)) - { - USB_REG->DEVDMA[epnum - 1].DEVDMACONTROL = udd_dma_ctrl; - USB_REG->DEVIER = DEVIER_DMA_1 << (epnum - 1); - __set_PRIMASK(irq_state); - return true; - } - __set_PRIMASK(irq_state); - - // Here a ZLP has been received - // and the DMA transfer must be not started. - // It is the end of transfer - return false; - } else - { - if (dir == TUSB_DIR_OUT) - { + USB_REG->DEVDMA[epnum - 1].DEVDMACONTROL = udd_dma_ctrl; + USB_REG->DEVIER = DEVIER_DMA_1 << (epnum - 1); + } else { + if (dir == TUSB_DIR_OUT) { USB_REG->DEVEPTIER[epnum] = DEVEPTIER_RXOUTES; - } else - { - dcd_transmit_packet(xfer,epnum); + } else { + dcd_transmit_packet(xfer, epnum); } } return true; @@ -669,112 +555,43 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t // bytes should be written and second to keep the return value free to give back a boolean // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes, bool is_isr) -{ - (void) is_isr; - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes, bool is_isr) { + (void)is_isr; + (void)rhport; + const uint8_t epnum = tu_edpt_number(ep_addr); + const uint8_t dir = tu_edpt_dir(ep_addr); - xfer_ctl_t * xfer = &xfer_status[epnum]; - if(epnum == 0x80) - xfer = &xfer_status[EP_MAX]; + xfer_ctl_t *xfer = &xfer_status[epnum]; - xfer->buffer = NULL; - xfer->total_len = total_bytes; + xfer->buffer = NULL; + xfer->total_len = total_bytes; xfer->queued_len = 0; - xfer->fifo = ff; - - if (EP_DMA_SUPPORT(epnum) && total_bytes != 0) - { - tu_fifo_buffer_info_t info; - uint32_t udd_dma_ctrl_lin = DEVDMACONTROL_CHANN_ENB; - uint32_t udd_dma_ctrl_wrap = DEVDMACONTROL_CHANN_ENB | DEVDMACONTROL_END_BUFFIT; - if (dir == TUSB_DIR_OUT) - { - tu_fifo_get_write_info(ff, &info); - udd_dma_ctrl_lin |= DEVDMACONTROL_END_TR_IT | DEVDMACONTROL_END_TR_EN; - udd_dma_ctrl_wrap |= DEVDMACONTROL_END_TR_IT | DEVDMACONTROL_END_TR_EN; - } else { - tu_fifo_get_read_info(ff, &info); - if(info.wrapped.len == 0) - { - udd_dma_ctrl_lin |= DEVDMACONTROL_END_B_EN; - } - udd_dma_ctrl_wrap |= DEVDMACONTROL_END_B_EN; - } - - // Clean invalidate cache of linear part - CleanInValidateCache((uint32_t*) tu_align((uint32_t) info.linear.ptr, 4), info.linear.len + 31); - - USB_REG->DEVDMA[epnum - 1].DEVDMAADDRESS = (uint32_t)info.linear.ptr; - if (info.wrapped.len) - { - // Clean invalidate cache of wrapped part - CleanInValidateCache((uint32_t*) tu_align((uint32_t) info.wrapped.ptr, 4), info.wrapped.len + 31); + xfer->fifo = ff; - dma_desc[epnum - 1].next_desc = 0; - dma_desc[epnum - 1].buff_addr = (uint32_t)info.wrapped.ptr; - dma_desc[epnum - 1].chnl_ctrl = - udd_dma_ctrl_wrap | (info.wrapped.len << DEVDMACONTROL_BUFF_LENGTH_Pos); - // Clean cache of wrapped DMA descriptor - CleanInValidateCache((uint32_t*)&dma_desc[epnum - 1], sizeof(dma_desc_t)); - - udd_dma_ctrl_lin |= DEVDMASTATUS_DESC_LDST; - USB_REG->DEVDMA[epnum - 1].DEVDMANXTDSC = (uint32_t)&dma_desc[epnum - 1]; - } else { - udd_dma_ctrl_lin |= DEVDMACONTROL_END_BUFFIT; - } - udd_dma_ctrl_lin |= (info.linear.len << DEVDMACONTROL_BUFF_LENGTH_Pos); - // Disable IRQs to have a short sequence - // between read of EOT_STA and DMA enable - uint32_t irq_state = __get_PRIMASK(); - __disable_irq(); - if (!(USB_REG->DEVDMA[epnum - 1].DEVDMASTATUS & DEVDMASTATUS_END_TR_ST)) - { - USB_REG->DEVDMA[epnum - 1].DEVDMACONTROL = udd_dma_ctrl_lin; - USB_REG->DEVIER = DEVIER_DMA_1 << (epnum - 1); - __set_PRIMASK(irq_state); - return true; - } - __set_PRIMASK(irq_state); - - // Here a ZLP has been received - // and the DMA transfer must be not started. - // It is the end of transfer - return false; - } else - { - if (dir == TUSB_DIR_OUT) - { - USB_REG->DEVEPTIER[epnum] = DEVEPTIER_RXOUTES; - } else - { - dcd_transmit_packet(xfer,epnum); - } + if (dir == TUSB_DIR_OUT) { + USB_REG->DEVEPTIER[epnum] = DEVEPTIER_RXOUTES; + } else { + dcd_transmit_packet(xfer, epnum); } return true; } // Stall endpoint -void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { + (void)rhport; + const uint8_t epnum = tu_edpt_number(ep_addr); USB_REG->DEVEPTIER[epnum] = DEVEPTIER_CTRL_STALLRQS; // Re-enable SETUP interrupt - if (epnum == 0) - { + if (epnum == 0) { USB_REG->DEVEPTIER[0] = DEVEPTIER_CTRL_RXSTPES; } } // clear stall, data toggle is also reset to DATA0 -void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) -{ - (void) rhport; - uint8_t const epnum = tu_edpt_number(ep_addr); +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { + (void)rhport; + const uint8_t epnum = tu_edpt_number(ep_addr); USB_REG->DEVEPTIDR[epnum] = DEVEPTIDR_CTRL_STALLRQC; - USB_REG->DEVEPTIER[epnum] = HSTPIPIER_RSTDTS; + USB_REG->DEVEPTIER[epnum] = DEVEPTIER_RSTDTS; } #endif diff --git a/src/portable/microchip/samx7x/common_usb_regs.h b/src/portable/microchip/samx7x/samx7x_common.h index db4a81e0e..5e3c20c0f 100644 --- a/src/portable/microchip/samx7x/common_usb_regs.h +++ b/src/portable/microchip/samx7x/samx7x_common.h @@ -1,4 +1,4 @@ - /* +/* * The MIT License (MIT) * * Copyright (c) 2019 Microchip Technology Inc. @@ -2098,7 +2098,72 @@ typedef struct #define FIFO_RAM_ADDR 0xA0100000u // Errata: The DMA feature is not available for Pipe/Endpoint 7 -#define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6) +#define EP_DMA_SUPPORT(epnum) (epnum >= 1 && epnum <= 6 && CFG_TUD_SAMX7X_DMA_ENABLE) + +//------------- DCache -------------// +#if CFG_TUD_MEM_DCACHE_ENABLE || CFG_TUH_MEM_DCACHE_ENABLE + +typedef struct { + uintptr_t start; + uintptr_t end; +} mem_region_t; + +// Can be used to define additional uncached regions +#ifndef CFG_SAMX7X_MEM_UNCACHED_REGIONS +#define CFG_SAMX7X_MEM_UNCACHED_REGIONS +#endif + +static mem_region_t uncached_regions[] = { + // DTCM + {.start = 0x20000000, .end = 0x203fffff}, + CFG_SAMX7X_MEM_UNCACHED_REGIONS +}; + +TU_ATTR_ALWAYS_INLINE static inline uint32_t round_up_to_cache_line_size(uint32_t size) { + if (size & (CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT-1)) { + size = (size & ~(CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT-1)) + CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT; + } + return size; +} + +TU_ATTR_ALWAYS_INLINE static inline bool is_cache_mem(uintptr_t addr) { + if (0 == (SCB->CCR & SCB_CCR_DC_Msk)) { + return false; // D-Cache is disabled + } + for (unsigned int i = 0; i < TU_ARRAY_SIZE(uncached_regions); i++) { + if (uncached_regions[i].start <= addr && addr <= uncached_regions[i].end) { return false; } + } + return true; +} + +TU_ATTR_ALWAYS_INLINE static inline bool samx7x_dcache_clean(void const* addr, uint32_t data_size) { + const uintptr_t addr32 = (uintptr_t) addr; + if (is_cache_mem(addr32)) { + data_size = round_up_to_cache_line_size(data_size); + SCB_CleanDCache_by_Addr((uint32_t *) addr32, (int32_t) data_size); + } + return true; +} + +TU_ATTR_ALWAYS_INLINE static inline bool samx7x_dcache_invalidate(void const* addr, uint32_t data_size) { + const uintptr_t addr32 = (uintptr_t) addr; + if (is_cache_mem(addr32)) { + data_size = round_up_to_cache_line_size(data_size); + SCB_InvalidateDCache_by_Addr((void*) addr32, (int32_t) data_size); + } + return true; +} + +TU_ATTR_ALWAYS_INLINE static inline bool samx7x_dcache_clean_invalidate(void const* addr, uint32_t data_size) { + const uintptr_t addr32 = (uintptr_t) addr; + if (is_cache_mem(addr32)) { + data_size = round_up_to_cache_line_size(data_size); + SCB_CleanInvalidateDCache_by_Addr((uint32_t *) addr32, (int32_t) data_size); + } + return true; +} + +#endif #else // TODO : SAM3U diff --git a/src/tusb_option.h b/src/tusb_option.h index 4450c7c45..f5879e1df 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -395,6 +395,24 @@ // odd byte with byte access #endif +//------- Microchip SAMX7X -------// +// DMA mode for device +#ifndef CFG_TUD_SAMX7X_DMA_ENABLE + #ifndef CFG_TUD_SAMX7X_DMA_ENABLE_DEFAULT + #define CFG_TUD_SAMX7X_DMA_ENABLE_DEFAULT 0 + #endif + + #define CFG_TUD_SAMX7X_DMA_ENABLE CFG_TUD_SAMX7X_DMA_ENABLE_DEFAULT +#endif + +#if (CFG_TUSB_MCU == OPT_MCU_SAMX7X) + #define CFG_TUSB_FIFO_HWFIFO_DATA_STRIDE 4 + #define CFG_TUSB_FIFO_HWFIFO_ADDR_STRIDE 4 + #define CFG_TUSB_FIFO_HWFIFO_DATA_ODD_16BIT_ACCESS + #define CFG_TUSB_FIFO_HWFIFO_DATA_ODD_8BIT_ACCESS + #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 +#endif + //-------------------------------------------------------------------- // RootHub Mode detection //-------------------------------------------------------------------- |
