From 9257a0f562a1cb939a902e7c41de5032b0f7de19 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 18 Aug 2023 12:48:12 +0700 Subject: [PATCH 01/71] - update nrf52 bsp for cmake - add empty tuh_int_handler/tud_int_handler if corresponidng stack not enabled - add hcd_template.c --- hw/bsp/nrf/boards/adafruit_clue/board.cmake | 5 + .../nrf/boards/arduino_nano33_ble/board.cmake | 5 + .../circuitplayground_bluefruit/board.cmake | 5 + .../feather_nrf52840_express/board.cmake | 6 + .../boards/feather_nrf52840_sense/board.cmake | 5 + .../nrf/boards/itsybitsy_nrf52840/board.cmake | 5 + .../boards/nrf52840_mdk_dongle/board.cmake | 5 + hw/bsp/nrf/boards/pca10056/board.cmake | 3 - hw/bsp/nrf/boards/pca10059/board.cmake | 5 + hw/bsp/nrf/boards/pca10095/board.cmake | 4 - hw/bsp/nrf/boards/pca10100/board.cmake | 5 + .../nrf/boards/raytac_mdbt50q_rx/board.cmake | 5 + hw/bsp/nrf/family.cmake | 14 +- src/device/usbd.h | 6 +- src/host/hcd.h | 12 +- src/portable/template/dcd_template.c | 4 +- src/portable/template/hcd_template.c | 162 ++++++++++++++++++ src/tusb.h | 9 +- 18 files changed, 241 insertions(+), 24 deletions(-) create mode 100644 hw/bsp/nrf/boards/adafruit_clue/board.cmake create mode 100644 hw/bsp/nrf/boards/arduino_nano33_ble/board.cmake create mode 100644 hw/bsp/nrf/boards/circuitplayground_bluefruit/board.cmake create mode 100644 hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake create mode 100644 hw/bsp/nrf/boards/feather_nrf52840_sense/board.cmake create mode 100644 hw/bsp/nrf/boards/itsybitsy_nrf52840/board.cmake create mode 100644 hw/bsp/nrf/boards/nrf52840_mdk_dongle/board.cmake create mode 100644 hw/bsp/nrf/boards/pca10059/board.cmake create mode 100644 hw/bsp/nrf/boards/pca10100/board.cmake create mode 100644 hw/bsp/nrf/boards/raytac_mdbt50q_rx/board.cmake create mode 100644 src/portable/template/hcd_template.c diff --git a/hw/bsp/nrf/boards/adafruit_clue/board.cmake b/hw/bsp/nrf/boards/adafruit_clue/board.cmake new file mode 100644 index 000000000..eb97e5c55 --- /dev/null +++ b/hw/bsp/nrf/boards/adafruit_clue/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52840) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/arduino_nano33_ble/board.cmake b/hw/bsp/nrf/boards/arduino_nano33_ble/board.cmake new file mode 100644 index 000000000..93647063a --- /dev/null +++ b/hw/bsp/nrf/boards/arduino_nano33_ble/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52840) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/arduino_nano33_ble.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/circuitplayground_bluefruit/board.cmake b/hw/bsp/nrf/boards/circuitplayground_bluefruit/board.cmake new file mode 100644 index 000000000..eb97e5c55 --- /dev/null +++ b/hw/bsp/nrf/boards/circuitplayground_bluefruit/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52840) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake b/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake new file mode 100644 index 000000000..0acbecf7a --- /dev/null +++ b/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake @@ -0,0 +1,6 @@ +set(MCU_VARIANT nrf52840) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld) +# set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52840_xxaa.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/feather_nrf52840_sense/board.cmake b/hw/bsp/nrf/boards/feather_nrf52840_sense/board.cmake new file mode 100644 index 000000000..eb97e5c55 --- /dev/null +++ b/hw/bsp/nrf/boards/feather_nrf52840_sense/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52840) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/itsybitsy_nrf52840/board.cmake b/hw/bsp/nrf/boards/itsybitsy_nrf52840/board.cmake new file mode 100644 index 000000000..eb97e5c55 --- /dev/null +++ b/hw/bsp/nrf/boards/itsybitsy_nrf52840/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52840) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/nrf52840_mdk_dongle/board.cmake b/hw/bsp/nrf/boards/nrf52840_mdk_dongle/board.cmake new file mode 100644 index 000000000..ffa5932c1 --- /dev/null +++ b/hw/bsp/nrf/boards/nrf52840_mdk_dongle/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52840) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/nrf52840_mdk_dongle.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/pca10056/board.cmake b/hw/bsp/nrf/boards/pca10056/board.cmake index b4fe39fc0..693d7beed 100644 --- a/hw/bsp/nrf/boards/pca10056/board.cmake +++ b/hw/bsp/nrf/boards/pca10056/board.cmake @@ -2,7 +2,4 @@ set(MCU_VARIANT nrf52840) set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52840_xxaa.ld) function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - NRF52840_XXAA - ) endfunction() diff --git a/hw/bsp/nrf/boards/pca10059/board.cmake b/hw/bsp/nrf/boards/pca10059/board.cmake new file mode 100644 index 000000000..c79eb5964 --- /dev/null +++ b/hw/bsp/nrf/boards/pca10059/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52840) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/pca10059.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/pca10095/board.cmake b/hw/bsp/nrf/boards/pca10095/board.cmake index 1e72243c9..ca5399a3a 100644 --- a/hw/bsp/nrf/boards/pca10095/board.cmake +++ b/hw/bsp/nrf/boards/pca10095/board.cmake @@ -2,10 +2,6 @@ set(MCU_VARIANT nrf5340_application) set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf5340_xxaa_application.ld) function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - NRF5340_XXAA - NRF5340_XXAA_APPLICATION - ) target_sources(${TARGET} PRIVATE ${NRFX_DIR}/drivers/src/nrfx_usbreg.c ) diff --git a/hw/bsp/nrf/boards/pca10100/board.cmake b/hw/bsp/nrf/boards/pca10100/board.cmake new file mode 100644 index 000000000..c30026815 --- /dev/null +++ b/hw/bsp/nrf/boards/pca10100/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52833) +set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52833_xxaa.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/boards/raytac_mdbt50q_rx/board.cmake b/hw/bsp/nrf/boards/raytac_mdbt50q_rx/board.cmake new file mode 100644 index 000000000..693d7beed --- /dev/null +++ b/hw/bsp/nrf/boards/raytac_mdbt50q_rx/board.cmake @@ -0,0 +1,5 @@ +set(MCU_VARIANT nrf52840) +set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52840_xxaa.ld) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index 2b13249f4..6c24d3658 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -33,13 +33,20 @@ function(add_board_target BOARD_TARGET) add_library(${BOARD_TARGET} STATIC # driver ${NRFX_DIR}/drivers/src/nrfx_power.c + ${NRFX_DIR}/drivers/src/nrfx_spim.c ${NRFX_DIR}/drivers/src/nrfx_uarte.c # mcu ${NRFX_DIR}/mdk/system_${MCU_VARIANT}.c ) - target_compile_definitions(${BOARD_TARGET} PUBLIC - CONFIG_GPIO_AS_PINRESET - ) + target_compile_definitions(${BOARD_TARGET} PUBLIC CONFIG_GPIO_AS_PINRESET) + + if (MCU_VARIANT STREQUAL "nrf52840") + target_compile_definitions(${BOARD_TARGET} PUBLIC NRF52840_XXAA) + elseif (MCU_VARIANT STREQUAL "nrf52833") + target_compile_definitions(${BOARD_TARGET} PUBLIC NRF52833_XXAA) + elseif (MCU_VARIANT STREQUAL "nrf5340_application") + target_compile_definitions(${BOARD_TARGET} PUBLIC NRF5340_XXAA NRF5340_XXAA_APPLICATION) + endif () if (TRACE_ETM STREQUAL "1") # ENABLE_TRACE will cause system_nrf5x.c to set up ETM trace @@ -115,6 +122,7 @@ function(family_configure_example TARGET RTOS) family_add_tinyusb(${TARGET} OPT_MCU_NRF5X ${RTOS}) target_sources(${TARGET}-tinyusb PUBLIC ${TOP}/src/portable/nordic/nrf5x/dcd_nrf5x.c + #${TOP}/src/portable/analog/max3421e/hcd_max3421e.c ) target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) diff --git a/src/device/usbd.h b/src/device/usbd.h index b11c1a09d..782f538fd 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -50,8 +50,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr); // Task function should be called in main/rtos loop TU_ATTR_ALWAYS_INLINE static inline -void tud_task (void) -{ +void tud_task (void) { tud_task_ext(UINT32_MAX, false); } @@ -80,8 +79,7 @@ bool tud_suspended(void); // Check if device is ready to transfer TU_ATTR_ALWAYS_INLINE static inline -bool tud_ready(void) -{ +bool tud_ready(void) { return tud_mounted() && !tud_suspended(); } diff --git a/src/host/hcd.h b/src/host/hcd.h index 9bcc1c6df..1b5038ef4 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -198,8 +198,7 @@ extern void hcd_event_handler(hcd_event_t const* event, bool in_isr); // Helper to send device attach event TU_ATTR_ALWAYS_INLINE static inline -void hcd_event_device_attach(uint8_t rhport, bool in_isr) -{ +void hcd_event_device_attach(uint8_t rhport, bool in_isr) { hcd_event_t event; event.rhport = rhport; event.event_id = HCD_EVENT_DEVICE_ATTACH; @@ -211,8 +210,7 @@ void hcd_event_device_attach(uint8_t rhport, bool in_isr) // Helper to send device removal event TU_ATTR_ALWAYS_INLINE static inline -void hcd_event_device_remove(uint8_t rhport, bool in_isr) -{ +void hcd_event_device_remove(uint8_t rhport, bool in_isr) { hcd_event_t event; event.rhport = rhport; event.event_id = HCD_EVENT_DEVICE_REMOVE; @@ -224,10 +222,8 @@ void hcd_event_device_remove(uint8_t rhport, bool in_isr) // Helper to send USB transfer event TU_ATTR_ALWAYS_INLINE static inline -void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr) -{ - hcd_event_t event = - { +void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr) { + hcd_event_t event = { .rhport = 0, // TODO correct rhport .event_id = HCD_EVENT_XFER_COMPLETE, .dev_addr = dev_addr, diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index 590dd9fcf..12d610bd6 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if CFG_TUSB_MCU == OPT_MCU_NONE +#if CFG_TUD_ENABLED && CFG_TUSB_MCU == OPT_MCU_NONE #include "device/dcd.h" @@ -141,4 +141,6 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) (void) ep_addr; } + + #endif diff --git a/src/portable/template/hcd_template.c b/src/portable/template/hcd_template.c new file mode 100644 index 000000000..3e3b91558 --- /dev/null +++ b/src/portable/template/hcd_template.c @@ -0,0 +1,162 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 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. + */ + +#include "tusb_option.h" + +#if CFG_TUH_ENABLED && CFG_TUSB_MCU == OPT_MCU_NONE + +#include "host/hcd.h" + +//--------------------------------------------------------------------+ +// Controller API +//--------------------------------------------------------------------+ + +// optional hcd configuration, called by tuh_configure() +bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { + (void) rhport; + (void) cfg_id; + (void) cfg_param; + + return false; +} + +// Initialize controller to host mode +bool hcd_init(uint8_t rhport) { + (void) rhport; + + return false; +} + +// Interrupt Handler +void hcd_int_handler(uint8_t rhport) { + (void) rhport; +} + +// Enable USB interrupt +void hcd_int_enable (uint8_t rhport) { + (void) rhport; +} + +// Disable USB interrupt +void hcd_int_disable(uint8_t rhport) { + (void) rhport; +} + +// Get frame number (1ms) +uint32_t hcd_frame_number(uint8_t rhport) { + (void) rhport; + + return 0; +} + +//--------------------------------------------------------------------+ +// Port API +//--------------------------------------------------------------------+ + +// Get the current connect status of roothub port +bool hcd_port_connect_status(uint8_t rhport) { + (void) rhport; + + return false; +} + +// Reset USB bus on the port. Return immediately, bus reset sequence may not be complete. +// Some port would require hcd_port_reset_end() to be invoked after 10ms to complete the reset sequence. +void hcd_port_reset(uint8_t rhport) { + (void) rhport; +} + +// Complete bus reset sequence, may be required by some controllers +void hcd_port_reset_end(uint8_t rhport) { + (void) rhport; +} + +// Get port link speed +tusb_speed_t hcd_port_speed_get(uint8_t rhport) { + (void) rhport; + + return TUSB_SPEED_FULL; +} + +// HCD closes all opened endpoints belong to this device +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { + (void) rhport; + (void) dev_addr; +} + +//--------------------------------------------------------------------+ +// Endpoints API +//--------------------------------------------------------------------+ + +// Open an endpoint +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { + (void) rhport; + (void) dev_addr; + (void) ep_desc; + + return false; +} + +// Submit a transfer, when complete hcd_event_xfer_complete() must be invoked +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { + (void) rhport; + (void) dev_addr; + (void) ep_addr; + (void) buffer; + (void) buflen; + + return false; +} + +// Abort a queued transfer. Note: it can only abort transfer that has not been started +// Return true if a queued transfer is aborted, false if there is no transfer to abort +bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + (void) dev_addr; + (void) ep_addr; + + return false; +} + +// Submit a special transfer to send 8-byte Setup Packet, when complete hcd_event_xfer_complete() must be invoked +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { + (void) rhport; + (void) dev_addr; + (void) setup_packet; + + return false; +} + +// clear stall, data toggle is also reset to DATA0 +bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + (void) dev_addr; + (void) ep_addr; + + return false; +} + +#endif diff --git a/src/tusb.h b/src/tusb.h index 37a521fa8..d6534ca28 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -64,7 +64,10 @@ #if CFG_TUH_VENDOR #include "class/vendor/vendor_host.h" #endif - +#else + #ifndef tuh_int_handler + #define tuh_int_handler(_x) + #endif #endif //------------- DEVICE -------------// @@ -118,6 +121,10 @@ #if CFG_TUD_BTH #include "class/bth/bth_device.h" #endif +#else + #ifndef tud_int_handler + #define tud_int_handler(_x) + #endif #endif From 824e585e2b1f62d1ed03f480439e62e5410636b6 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 18 Aug 2023 14:06:57 +0700 Subject: [PATCH 02/71] ground works for hcd max3421e --- .../feather_nrf52840_express/board.cmake | 4 +- .../boards/feather_nrf52840_express/board.h | 7 + hw/bsp/nrf/family.c | 80 +++-- hw/bsp/nrf/family.cmake | 2 +- hw/bsp/nrf/nrfx_config.h | 5 +- src/portable/analog/max3421e/hcd_max3421e.c | 302 ++++++++++++++++++ 6 files changed, 369 insertions(+), 31 deletions(-) create mode 100644 src/portable/analog/max3421e/hcd_max3421e.c diff --git a/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake b/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake index 0acbecf7a..78ed98225 100644 --- a/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake +++ b/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake @@ -1,6 +1,6 @@ set(MCU_VARIANT nrf52840) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld) -# set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52840_xxaa.ld) +#set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld) +set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52840_xxaa.ld) function(update_board TARGET) endfunction() diff --git a/hw/bsp/nrf/boards/feather_nrf52840_express/board.h b/hw/bsp/nrf/boards/feather_nrf52840_express/board.h index 8e6ce3230..e19f88a3c 100644 --- a/hw/bsp/nrf/boards/feather_nrf52840_express/board.h +++ b/hw/bsp/nrf/boards/feather_nrf52840_express/board.h @@ -45,6 +45,13 @@ #define UART_RX_PIN 24 #define UART_TX_PIN 25 +// SPI for USB host shield +#define SPI_SCK_PIN 14 +#define SPI_MOSI_PIN 13 +#define SPI_MISO_PIN 15 +#define SPI_CS_PIN 27 +#define MAX3241E_INT_PIN 26 + #ifdef __cplusplus } #endif diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 9ca666e36..b6ed15122 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -40,6 +40,7 @@ #include "hal/nrf_gpio.h" #include "drivers/include/nrfx_power.h" #include "drivers/include/nrfx_uarte.h" +#include "drivers/include/nrfx_spim.h" #ifdef SOFTDEVICE_PRESENT #include "nrf_sdm.h" @@ -54,8 +55,7 @@ //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ -void USBD_IRQHandler(void) -{ +void USBD_IRQHandler(void) { tud_int_handler(0); } @@ -81,6 +81,7 @@ enum { #endif static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(0); +static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(0); // tinyusb function that handles power event (detected, ready, removed) // We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled. @@ -88,13 +89,11 @@ extern void tusb_hal_nrf_power_event(uint32_t event); // nrf power callback, could be unused if SD is enabled or usb is disabled (board_test example) -TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) -{ +TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) { tusb_hal_nrf_power_event((uint32_t) event); } -void board_init(void) -{ +void board_init(void) { // stop LF clock just in case we jump from application without reset NRF_CLOCK->TASKS_LFCLKSTOP = 1UL; @@ -113,8 +112,7 @@ void board_init(void) SysTick_Config(SystemCoreClock/1000); // UART - nrfx_uarte_config_t uart_cfg = - { + nrfx_uarte_config_t uart_cfg = { .pseltxd = UART_TX_PIN, .pselrxd = UART_RX_PIN, .pselcts = NRF_UARTE_PSEL_DISCONNECTED, @@ -175,45 +173,78 @@ void board_init(void) if ( usb_reg & VBUSDETECT_Msk ) tusb_hal_nrf_power_event(USB_EVT_DETECTED); if ( usb_reg & OUTPUTRDY_Msk ) tusb_hal_nrf_power_event(USB_EVT_READY); #endif + + (void) _spi; +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421E) && CFG_TUH_MAX3421E + // USB host using max3421e usb controller via SPI + nrfx_spim_config_t cfg = { + .sck_pin = SPI_SCK_PIN, + .mosi_pin = SPI_MOSI_PIN, + .miso_pin = SPI_MISO_PIN, + .ss_pin = SPI_CS_PIN, + .ss_active_high = false, + .irq_priority = 3, + .orc = 0xFF, + // default setting 4 Mhz, Mode 0, MSB first + .frequency = NRF_SPIM_FREQ_4M, + .mode = NRF_SPIM_MODE_0, + .bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST, + }; + + // no handler --> blocking + nrfx_spim_init(&_spi, &cfg, NULL, NULL); +#endif + } //--------------------------------------------------------------------+ // Board porting API //--------------------------------------------------------------------+ -void board_led_write(bool state) -{ - nrf_gpio_pin_write(LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +void board_led_write(bool state) { + nrf_gpio_pin_write(LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); } -uint32_t board_button_read(void) -{ +uint32_t board_button_read(void) { return BUTTON_STATE_ACTIVE == nrf_gpio_pin_read(BUTTON_PIN); } -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; +int board_uart_read(uint8_t *buf, int len) { + (void) buf; + (void) len; return 0; // return NRFX_SUCCESS == nrfx_uart_rx(&_uart_id, buf, (size_t) len) ? len : 0; } -int board_uart_write(void const * buf, int len) -{ - return (NRFX_SUCCESS == nrfx_uarte_tx(&_uart_id, (uint8_t const*) buf, (size_t) len)) ? len : 0; +int board_uart_write(void const *buf, int len) { + return (NRFX_SUCCESS == nrfx_uarte_tx(&_uart_id, (uint8_t const *) buf, (size_t) len)) ? len : 0; } #if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; -void SysTick_Handler (void) -{ + +void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) -{ +uint32_t board_millis(void) { return system_ticks; } + +#endif + +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421E) && CFG_TUH_MAX3421E +// API: SPI transfer with MAX3421E, must be implemented by application +bool tuh_max3421e_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len) { + (void) rhport; + nrfx_spim_xfer_desc_t xfer = { + .p_tx_buffer = tx_buf, + .tx_length = tx_len, + .p_rx_buffer = rx_buf, + .rx_length = rx_len, + }; + return nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS; +} #endif #ifdef SOFTDEVICE_PRESENT @@ -251,8 +282,7 @@ void SD_EVT_IRQHandler(void) } } -void nrf_error_cb(uint32_t id, uint32_t pc, uint32_t info) -{ +void nrf_error_cb(uint32_t id, uint32_t pc, uint32_t info) { (void) id; (void) pc; (void) info; diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index 6c24d3658..527251e71 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -122,7 +122,7 @@ function(family_configure_example TARGET RTOS) family_add_tinyusb(${TARGET} OPT_MCU_NRF5X ${RTOS}) target_sources(${TARGET}-tinyusb PUBLIC ${TOP}/src/portable/nordic/nrf5x/dcd_nrf5x.c - #${TOP}/src/portable/analog/max3421e/hcd_max3421e.c + ${TOP}/src/portable/analog/max3421e/hcd_max3421e.c ) target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) diff --git a/hw/bsp/nrf/nrfx_config.h b/hw/bsp/nrf/nrfx_config.h index 696a3fb04..d0f718c6c 100644 --- a/hw/bsp/nrf/nrfx_config.h +++ b/hw/bsp/nrf/nrfx_config.h @@ -9,9 +9,8 @@ #define NRFX_UARTE_ENABLED 1 #define NRFX_UARTE0_ENABLED 1 -#define NRFX_UARTE1_ENABLED 0 -#define NRFX_UARTE2_ENABLED 0 -#define NRFX_UARTE3_ENABLED 0 +#define NRFX_SPIM_ENABLED 1 +#define NRFX_SPIM0_ENABLED 1 #define NRFX_PRS_ENABLED 0 #define NRFX_USBREG_ENABLED 1 diff --git a/src/portable/analog/max3421e/hcd_max3421e.c b/src/portable/analog/max3421e/hcd_max3421e.c new file mode 100644 index 000000000..7b9d73e4e --- /dev/null +++ b/src/portable/analog/max3421e/hcd_max3421e.c @@ -0,0 +1,302 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 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. + */ + +#include "tusb_option.h" + +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421E) && CFG_TUH_MAX3421E + +#include "host/hcd.h" + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +// Command format is +// Reg [7:3] | 0 [2] | Dir [1] | Ack [0] + +enum { + CMDBYTE_WRITE = 0x02, +}; + +enum { + RCVVFIFO_ADDR = 1u << 3, // 0x08 + SNDFIFO_ADDR = 2u << 3, // 0x10 + SUDFIFO_ADDR = 4u << 3, // 0x20 + RCVBC_ADDR = 6u << 3, // 0x30 + SNDBC_ADDR = 7u << 3, // 0x38 + USBIRQ_ADDR = 13u << 3, // 0x68 + USBIEN_ADDR = 14u << 3, // 0x70 + USBCTL_ADDR = 15u << 3, // 0x78 + CPUCTL_ADDR = 16u << 3, // 0x80 + PINCTL_ADDR = 17u << 3, // 0x88 + REVISION_ADDR = 18u << 3, // 0x90 + HIRQ_ADDR = 25u << 3, // 0xC8 + HIEN_ADDR = 26u << 3, // 0xD0 + MODE_ADDR = 27u << 3, // 0xD8 + PERADDR_ADDR = 28u << 3, // 0xE0 + HCTL_ADDR = 29u << 3, // 0xE8 + HXFR_ADDR = 30u << 3, // 0xF0 + HRSL_ADDR = 31u << 3, // 0xF8 +}; + +enum { + USBIRQ_OSCOK_IRQ = 1u << 0, + USBIRQ_NOVBUS_IRQ = 1u << 5, + USBIRQ_VBUS_IRQ = 1u << 6, +}; + +enum { + USBCTL_PWRDOWN = 1u << 4, + USBCTL_CHIPRES = 1u << 5, +}; + +enum { + CPUCTL_IE = 1u << 0, + CPUCTL_PULSEWID0 = 1u << 6, + CPUCTL_PULSEWID1 = 1u << 7, +}; + +enum { + PINCTL_GPXA = 1u << 0, + PINCTL_GPXB = 1u << 1, + PINCTL_POSINT = 1u << 2, + PINCTL_INTLEVEL = 1u << 3, + PINCTL_FDUPSPI = 1u << 4, +}; + +enum { + HIRQ_BUSEVENT_IRQ = 1u << 0, + HIRQ_RWU_IRQ = 1u << 1, + HIRQ_RCVDAV_IRQ = 1u << 2, + HIRQ_SNDBAV_IRQ = 1u << 3, + HIRQ_SUSDN_IRQ = 1u << 4, + HIRQ_CONDET_IRQ = 1u << 5, + HIRQ_FRAME_IRQ = 1u << 6, + HIRQ_HXFRDN_IRQ = 1u << 7, +}; + +enum { + MODE_HOST = 1u << 0, + MODE_LOWSPEED = 1u << 1, + MODE_HUBPRE = 1u << 2, + MODE_SOFKAENAB = 1u << 3, + MODE_SEPIRQ = 1u << 4, + MODE_DELAYISO = 1u << 5, + MODE_DMPULLDN = 1u << 6, + MODE_DPPULLDN = 1u << 7, +}; + +enum { + HCTL_BUSRST = 1u << 1, + HCTL_FRMRST = 1u << 2, + HCTL_SAMPLEBUS = 1u << 3, + HCTL_SIGRSM = 1u << 4, + HCTL_RCVTOG0 = 1u << 5, + HCTL_RCVTOG1 = 1u << 6, + HCTL_SNDTOG0 = 1u << 7, + HCTL_SNDTOG1 = 1u << 8, +}; + +enum { + HXFR_EPNUM_MASK = 0x0f, + HXFR_SETUP = 1u << 4, + HXFR_OUT_NIN = 1u << 5, + HXFR_ISO = 1u << 6, + HXFR_HS = 1u << 7, +}; + +enum { + HRSL_RESULT_MASK = 0x0f, + HRSL_RCVTOGRD = 1u << 4, + HRSL_SNDTOGRD = 1u << 5, + HRSL_KSTATUS = 1u << 6, + HRSL_JSTATUS = 1u << 7, +}; + +// API: SPI transfer with MAX3421E, must be implemented by application +bool tuh_max3421e_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len); + +// return HIRQ register since we are in full-duplex mode +static uint8_t reg_write(uint8_t reg, uint8_t data) { + uint8_t tx_buf[2] = {reg | CMDBYTE_WRITE, data}; + uint8_t rx_buf[2] = {0, 0}; + tuh_max3421e_spi_xfer_api(0, tx_buf, 2, rx_buf, 2); + return rx_buf[0]; +} + +static uint8_t reg_read(uint8_t reg) { + uint8_t tx_buf[2] = {reg, 0}; + uint8_t rx_buf[2] = {0, 0}; + return tuh_max3421e_spi_xfer_api(0, tx_buf, 2, rx_buf, 2) ? rx_buf[1] : 0; +} + + +//--------------------------------------------------------------------+ +// Controller API +//--------------------------------------------------------------------+ + +// optional hcd configuration, called by tuh_configure() +bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { + (void) rhport; + (void) cfg_id; + (void) cfg_param; + + return false; +} + +// Initialize controller to host mode +bool hcd_init(uint8_t rhport) { + (void) rhport; + + // full duplex, interrupt level (should be configurable) + reg_write(PINCTL_ADDR, PINCTL_FDUPSPI | PINCTL_INTLEVEL); + + // reset + reg_write(USBCTL_ADDR, USBCTL_CHIPRES); + reg_write(USBCTL_ADDR, 0); + while( !(reg_read(USBIRQ_ADDR) & USBIRQ_OSCOK_IRQ) ) { + // wait for oscillator to stabilize + } + + // Mode: Host and DP/DM pull down + reg_write(MODE_ADDR, MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST); + + // Connection detection + reg_write(HIEN_ADDR, HIRQ_CONDET_IRQ /*| HIRQ_FRAME_IRQ */); + + return false; +} + +// Interrupt Handler +void hcd_int_handler(uint8_t rhport) { + (void) rhport; +} + +// Enable USB interrupt +void hcd_int_enable (uint8_t rhport) { + (void) rhport; +} + +// Disable USB interrupt +void hcd_int_disable(uint8_t rhport) { + (void) rhport; +} + +// Get frame number (1ms) +uint32_t hcd_frame_number(uint8_t rhport) { + (void) rhport; + + return 0; +} + +//--------------------------------------------------------------------+ +// Port API +//--------------------------------------------------------------------+ + +// Get the current connect status of roothub port +bool hcd_port_connect_status(uint8_t rhport) { + (void) rhport; + + return false; +} + +// Reset USB bus on the port. Return immediately, bus reset sequence may not be complete. +// Some port would require hcd_port_reset_end() to be invoked after 10ms to complete the reset sequence. +void hcd_port_reset(uint8_t rhport) { + (void) rhport; +} + +// Complete bus reset sequence, may be required by some controllers +void hcd_port_reset_end(uint8_t rhport) { + (void) rhport; +} + +// Get port link speed +tusb_speed_t hcd_port_speed_get(uint8_t rhport) { + (void) rhport; + + return TUSB_SPEED_FULL; +} + +// HCD closes all opened endpoints belong to this device +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { + (void) rhport; + (void) dev_addr; +} + +//--------------------------------------------------------------------+ +// Endpoints API +//--------------------------------------------------------------------+ + +// Open an endpoint +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { + (void) rhport; + (void) dev_addr; + (void) ep_desc; + + return false; +} + +// Submit a transfer, when complete hcd_event_xfer_complete() must be invoked +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { + (void) rhport; + (void) dev_addr; + (void) ep_addr; + (void) buffer; + (void) buflen; + + return false; +} + +// Abort a queued transfer. Note: it can only abort transfer that has not been started +// Return true if a queued transfer is aborted, false if there is no transfer to abort +bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + (void) dev_addr; + (void) ep_addr; + + return false; +} + +// Submit a special transfer to send 8-byte Setup Packet, when complete hcd_event_xfer_complete() must be invoked +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { + (void) rhport; + (void) dev_addr; + (void) setup_packet; + + return false; +} + +// clear stall, data toggle is also reset to DATA0 +bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + (void) dev_addr; + (void) ep_addr; + + return false; +} + +#endif From cacc96b25dc04865389357467b7a6d92d040ef36 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 18 Aug 2023 17:39:10 +0700 Subject: [PATCH 03/71] adding connection event handling, add nrf gpio interrupt for max2341e interrupt pin --- .../boards/feather_nrf52840_express/board.h | 2 +- hw/bsp/nrf/family.c | 55 +++++++++----- hw/bsp/nrf/family.cmake | 2 + hw/bsp/nrf/nrfx_config.h | 2 +- hw/bsp/nrf/nrfx_glue.h | 69 +++++++++++++++++ src/portable/analog/max3421e/hcd_max3421e.c | 76 ++++++++++++++++++- 6 files changed, 184 insertions(+), 22 deletions(-) diff --git a/hw/bsp/nrf/boards/feather_nrf52840_express/board.h b/hw/bsp/nrf/boards/feather_nrf52840_express/board.h index e19f88a3c..7f042142e 100644 --- a/hw/bsp/nrf/boards/feather_nrf52840_express/board.h +++ b/hw/bsp/nrf/boards/feather_nrf52840_express/board.h @@ -50,7 +50,7 @@ #define SPI_MOSI_PIN 13 #define SPI_MISO_PIN 15 #define SPI_CS_PIN 27 -#define MAX3241E_INT_PIN 26 +#define MAX3241E_INTR_PIN 26 #ifdef __cplusplus } diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index b6ed15122..e58ee845b 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -38,6 +38,7 @@ #include "nrfx.h" #include "hal/nrf_gpio.h" +#include "drivers/include/nrfx_gpiote.h" #include "drivers/include/nrfx_power.h" #include "drivers/include/nrfx_uarte.h" #include "drivers/include/nrfx_spim.h" @@ -81,18 +82,45 @@ enum { #endif static nrfx_uarte_t _uart_id = NRFX_UARTE_INSTANCE(0); -static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(0); // tinyusb function that handles power event (detected, ready, removed) // We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled. extern void tusb_hal_nrf_power_event(uint32_t event); - // nrf power callback, could be unused if SD is enabled or usb is disabled (board_test example) TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) { tusb_hal_nrf_power_event((uint32_t) event); } +//------------- Host using MAX2341E -------------// +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421E) && CFG_TUH_MAX3421E +static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(0); + +void max2342e_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { + if ( !(pin == MAX3241E_INTR_PIN && action == NRF_GPIOTE_POLARITY_HITOLO) ) return; + + tuh_int_handler(1); +} + +// API: SPI transfer with MAX3421E, must be implemented by application +bool tuh_max3421e_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len) { + (void) rhport; + nrfx_spim_xfer_desc_t xfer = { + .p_tx_buffer = tx_buf, + .tx_length = tx_len, + .p_rx_buffer = rx_buf, + .rx_length = rx_len, + }; + return nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS; +} + +#endif + + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + void board_init(void) { // stop LF clock just in case we jump from application without reset NRF_CLOCK->TASKS_LFCLKSTOP = 1UL; @@ -174,7 +202,6 @@ void board_init(void) { if ( usb_reg & OUTPUTRDY_Msk ) tusb_hal_nrf_power_event(USB_EVT_READY); #endif - (void) _spi; #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421E) && CFG_TUH_MAX3421E // USB host using max3421e usb controller via SPI nrfx_spim_config_t cfg = { @@ -193,6 +220,14 @@ void board_init(void) { // no handler --> blocking nrfx_spim_init(&_spi, &cfg, NULL, NULL); + + // max3421e interrupt pin + nrfx_gpiote_init(1); + nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true); + in_config.pull = NRF_GPIO_PIN_PULLUP; + + nrfx_gpiote_in_init(MAX3241E_INTR_PIN, &in_config, max2342e_int_handler); + nrfx_gpiote_in_event_enable(MAX3241E_INTR_PIN, true); #endif } @@ -233,20 +268,6 @@ uint32_t board_millis(void) { #endif -#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421E) && CFG_TUH_MAX3421E -// API: SPI transfer with MAX3421E, must be implemented by application -bool tuh_max3421e_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len) { - (void) rhport; - nrfx_spim_xfer_desc_t xfer = { - .p_tx_buffer = tx_buf, - .tx_length = tx_len, - .p_rx_buffer = rx_buf, - .rx_length = rx_len, - }; - return nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS; -} -#endif - #ifdef SOFTDEVICE_PRESENT // process SOC event from SD uint32_t proc_soc(void) diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index 527251e71..8bf7bcb52 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -32,6 +32,8 @@ function(add_board_target BOARD_TARGET) if (NOT TARGET ${BOARD_TARGET}) add_library(${BOARD_TARGET} STATIC # driver + ${NRFX_DIR}/helpers/nrfx_flag32_allocator.c + ${NRFX_DIR}/drivers/src/nrfx_gpiote.c ${NRFX_DIR}/drivers/src/nrfx_power.c ${NRFX_DIR}/drivers/src/nrfx_spim.c ${NRFX_DIR}/drivers/src/nrfx_uarte.c diff --git a/hw/bsp/nrf/nrfx_config.h b/hw/bsp/nrf/nrfx_config.h index d0f718c6c..e3d0ea91b 100644 --- a/hw/bsp/nrf/nrfx_config.h +++ b/hw/bsp/nrf/nrfx_config.h @@ -5,6 +5,7 @@ #define NRFX_POWER_DEFAULT_CONFIG_IRQ_PRIORITY 7 #define NRFX_CLOCK_ENABLED 0 +#define NRFX_GPIOTE_ENABLED 1 #define NRFX_UARTE_ENABLED 1 #define NRFX_UARTE0_ENABLED 1 @@ -41,5 +42,4 @@ #error "Unknown device." #endif - #endif // NRFX_CONFIG_H__ diff --git a/hw/bsp/nrf/nrfx_glue.h b/hw/bsp/nrf/nrfx_glue.h index cdf49b4ab..ef756c670 100644 --- a/hw/bsp/nrf/nrfx_glue.h +++ b/hw/bsp/nrf/nrfx_glue.h @@ -220,6 +220,75 @@ static inline bool _NRFX_IRQ_IS_PENDING(IRQn_Type irq_number) /** @} */ +//------------------------------------------------------------------------------ + +#include + +/** + * @brief Atomic 32 bit unsigned type. + */ +#define nrfx_atomic_t nrfx_atomic_u32_t + +/** + * @brief Stores value to an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value to store. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_STORE(p_data, value) nrfx_atomic_u32_fetch_store(p_data, value) + +/** + * @brief Performs logical OR operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of OR operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_OR(p_data, value) nrfx_atomic_u32_fetch_or(p_data, value) + +/** + * @brief Performs logical AND operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of AND operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_AND(p_data, value) nrfx_atomic_u32_fetch_and(p_data, value) + +/** + * @brief Performs logical XOR operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of XOR operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_XOR(p_data, value) nrfx_atomic_u32_fetch_xor(p_data, value) + +/** + * @brief Performs logical ADD operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of ADD operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_ADD(p_data, value) nrfx_atomic_u32_fetch_add(p_data, value) + +/** + * @brief Performs logical SUB operation on an atomic object and returns previously stored value. + * + * @param[in] p_data Atomic memory pointer. + * @param[in] value Value of second operand of SUB operation. + * + * @return Old value stored into atomic object. + */ +#define NRFX_ATOMIC_FETCH_SUB(p_data, value) nrfx_atomic_u32_fetch_sub(p_data, value) + #ifdef __cplusplus } #endif diff --git a/src/portable/analog/max3421e/hcd_max3421e.c b/src/portable/analog/max3421e/hcd_max3421e.c index 7b9d73e4e..a89581b9c 100644 --- a/src/portable/analog/max3421e/hcd_max3421e.c +++ b/src/portable/analog/max3421e/hcd_max3421e.c @@ -136,6 +136,20 @@ enum { HRSL_JSTATUS = 1u << 7, }; +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +//typedef struct { +// uint8_t mode +//} max2341e_data_t; +// +//max2341e_data_t max2341e_data; + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + // API: SPI transfer with MAX3421E, must be implemented by application bool tuh_max3421e_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len); @@ -144,6 +158,7 @@ static uint8_t reg_write(uint8_t reg, uint8_t data) { uint8_t tx_buf[2] = {reg | CMDBYTE_WRITE, data}; uint8_t rx_buf[2] = {0, 0}; tuh_max3421e_spi_xfer_api(0, tx_buf, 2, rx_buf, 2); + TU_LOG2("HIRQ: %02X\r\n", rx_buf[0]); return rx_buf[0]; } @@ -167,6 +182,48 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { return false; } +tusb_speed_t handle_connect_irq(uint8_t rhport) { + (void) rhport; + + uint8_t const hrsl = reg_read(HRSL_ADDR); + uint8_t const jk = hrsl & (HRSL_JSTATUS | HRSL_KSTATUS); + + tusb_speed_t speed; + uint8_t new_mode = MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST; + + switch(jk) { + case 0x00: + // SEO is disconnected + speed = TUSB_SPEED_INVALID; + break; + + case (HRSL_JSTATUS | HRSL_KSTATUS): + // SE1 is illegal + speed = TUSB_SPEED_INVALID; + break; + + default: { + // Low speed if (LS = 1 and J-state) or (LS = 0 and K-State) + uint8_t const mode = reg_read(MODE_ADDR); + uint8_t const ls_bit = mode & MODE_LOWSPEED; + + if ( (ls_bit && (jk == HRSL_JSTATUS)) || (!ls_bit && (jk == HRSL_KSTATUS)) ) { + speed = TUSB_SPEED_LOW; + new_mode |= MODE_LOWSPEED; + } else { + speed = TUSB_SPEED_FULL; + } + + new_mode |= MODE_SOFKAENAB; // enable SOF since there is new device + + break; + } + } + + reg_write(MODE_ADDR, new_mode); + return speed; +} + // Initialize controller to host mode bool hcd_init(uint8_t rhport) { (void) rhport; @@ -184,15 +241,28 @@ bool hcd_init(uint8_t rhport) { // Mode: Host and DP/DM pull down reg_write(MODE_ADDR, MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST); - // Connection detection - reg_write(HIEN_ADDR, HIRQ_CONDET_IRQ /*| HIRQ_FRAME_IRQ */); + // Enable Connection IRQ + reg_write(HIEN_ADDR, HIRQ_CONDET_IRQ); - return false; + // Note: if device is already connected, CONDET IRQ may not be triggered. We need to detect it by sampling bus signal + reg_write(HCTL_ADDR, HCTL_SAMPLEBUS); + while( !(reg_read(HCTL_ADDR) & HCTL_SAMPLEBUS) ) {} + + handle_connect_irq(rhport); + reg_write(HIRQ_ADDR, HIRQ_CONDET_IRQ); + + // Enable Interrupt pin + reg_write(CPUCTL_ADDR, CPUCTL_IE); + + return true; } // Interrupt Handler void hcd_int_handler(uint8_t rhport) { (void) rhport; + + uint8_t hirq = reg_read(HIRQ_ADDR); + TU_LOG3_INT(hirq); } // Enable USB interrupt From b4134394166c1f77463b5cb62f28cff465fde174 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 22 Aug 2023 19:57:59 +0700 Subject: [PATCH 04/71] able to detect new device and start enumerating --- src/portable/analog/max3421e/hcd_max3421e.c | 70 +++++++++++++++------ 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/src/portable/analog/max3421e/hcd_max3421e.c b/src/portable/analog/max3421e/hcd_max3421e.c index a89581b9c..870c616a9 100644 --- a/src/portable/analog/max3421e/hcd_max3421e.c +++ b/src/portable/analog/max3421e/hcd_max3421e.c @@ -140,11 +140,13 @@ enum { // //--------------------------------------------------------------------+ -//typedef struct { -// uint8_t mode -//} max2341e_data_t; -// -//max2341e_data_t max2341e_data; +typedef struct { + uint8_t mode; + + volatile uint16_t frame_count; +} max2341e_data_t; + +static max2341e_data_t _hcd_data; //--------------------------------------------------------------------+ // @@ -168,6 +170,11 @@ static uint8_t reg_read(uint8_t reg) { return tuh_max3421e_spi_xfer_api(0, tx_buf, 2, rx_buf, 2) ? rx_buf[1] : 0; } +static inline uint8_t mode_write(uint8_t data) { + _hcd_data.mode = data; + return reg_write(MODE_ADDR, data); +} + //--------------------------------------------------------------------+ // Controller API @@ -220,7 +227,8 @@ tusb_speed_t handle_connect_irq(uint8_t rhport) { } } - reg_write(MODE_ADDR, new_mode); + mode_write(new_mode); + TU_LOG2_INT(speed); return speed; } @@ -228,6 +236,8 @@ tusb_speed_t handle_connect_irq(uint8_t rhport) { bool hcd_init(uint8_t rhport) { (void) rhport; + tu_memclr(&_hcd_data, sizeof(_hcd_data)); + // full duplex, interrupt level (should be configurable) reg_write(PINCTL_ADDR, PINCTL_FDUPSPI | PINCTL_INTLEVEL); @@ -239,17 +249,21 @@ bool hcd_init(uint8_t rhport) { } // Mode: Host and DP/DM pull down - reg_write(MODE_ADDR, MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST); + mode_write(MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST); // Enable Connection IRQ - reg_write(HIEN_ADDR, HIRQ_CONDET_IRQ); + reg_write(HIEN_ADDR, HIRQ_CONDET_IRQ | HIRQ_FRAME_IRQ); - // Note: if device is already connected, CONDET IRQ may not be triggered. We need to detect it by sampling bus signal + #if 0 + // Note: if device is already connected, CONDET IRQ may not be triggered. + // We need to detect it by sampling bus signal. FIXME not working reg_write(HCTL_ADDR, HCTL_SAMPLEBUS); - while( !(reg_read(HCTL_ADDR) & HCTL_SAMPLEBUS) ) {} + while ( reg_read(HCTL_ADDR) & HCTL_SAMPLEBUS ) {} - handle_connect_irq(rhport); - reg_write(HIRQ_ADDR, HIRQ_CONDET_IRQ); + if ( TUSB_SPEED_INVALID != handle_connect_irq(rhport) ) { + reg_write(HIRQ_ADDR, HIRQ_CONDET_IRQ); // clear connect irq + } + #endif // Enable Interrupt pin reg_write(CPUCTL_ADDR, CPUCTL_IE); @@ -262,7 +276,26 @@ void hcd_int_handler(uint8_t rhport) { (void) rhport; uint8_t hirq = reg_read(HIRQ_ADDR); - TU_LOG3_INT(hirq); + TU_LOG3_HEX(hirq); + + if (hirq & HIRQ_CONDET_IRQ) { + tusb_speed_t speed = handle_connect_irq(rhport); + + if (speed == TUSB_SPEED_INVALID) { + hcd_event_device_remove(rhport, true); + }else { + hcd_event_device_attach(rhport, true); + } + } + + if (hirq & HIRQ_FRAME_IRQ) { + _hcd_data.frame_count++; + } + + // clear all interrupt + if ( hirq ) { + reg_write(HIRQ_ADDR, hirq); + } } // Enable USB interrupt @@ -278,8 +311,7 @@ void hcd_int_disable(uint8_t rhport) { // Get frame number (1ms) uint32_t hcd_frame_number(uint8_t rhport) { (void) rhport; - - return 0; + return (uint32_t ) _hcd_data.frame_count; } //--------------------------------------------------------------------+ @@ -289,26 +321,26 @@ uint32_t hcd_frame_number(uint8_t rhport) { // Get the current connect status of roothub port bool hcd_port_connect_status(uint8_t rhport) { (void) rhport; - - return false; + return (_hcd_data.mode & MODE_SOFKAENAB) ? true : false; } // Reset USB bus on the port. Return immediately, bus reset sequence may not be complete. // Some port would require hcd_port_reset_end() to be invoked after 10ms to complete the reset sequence. void hcd_port_reset(uint8_t rhport) { (void) rhport; + reg_write(HCTL_ADDR, HCTL_BUSRST); } // Complete bus reset sequence, may be required by some controllers void hcd_port_reset_end(uint8_t rhport) { (void) rhport; + reg_write(HCTL_ADDR, 0); } // Get port link speed tusb_speed_t hcd_port_speed_get(uint8_t rhport) { (void) rhport; - - return TUSB_SPEED_FULL; + return (_hcd_data.mode & MODE_LOWSPEED) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; } // HCD closes all opened endpoints belong to this device From 274578ff46c31b231b3553dc9a20895646313130 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 22 Aug 2023 23:17:12 +0700 Subject: [PATCH 05/71] able to send setup packet --- .../boards/feather_nrf52840_express/board.h | 8 +- hw/bsp/nrf/family.c | 36 +++- src/host/hcd.h | 2 +- src/host/usbh.c | 32 +--- src/portable/analog/max3421e/hcd_max3421e.c | 173 ++++++++++++++---- 5 files changed, 179 insertions(+), 72 deletions(-) diff --git a/hw/bsp/nrf/boards/feather_nrf52840_express/board.h b/hw/bsp/nrf/boards/feather_nrf52840_express/board.h index 7f042142e..e6e7590ac 100644 --- a/hw/bsp/nrf/boards/feather_nrf52840_express/board.h +++ b/hw/bsp/nrf/boards/feather_nrf52840_express/board.h @@ -46,10 +46,10 @@ #define UART_TX_PIN 25 // SPI for USB host shield -#define SPI_SCK_PIN 14 -#define SPI_MOSI_PIN 13 -#define SPI_MISO_PIN 15 -#define SPI_CS_PIN 27 +#define MAX3421E_SCK_PIN 14 +#define MAX3421E_MOSI_PIN 13 +#define MAX3421E_MISO_PIN 15 +#define MAX3421E_CS_PIN 27 #define MAX3241E_INTR_PIN 26 #ifdef __cplusplus diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index e58ee845b..862f67bc7 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -96,22 +96,38 @@ TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) { #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421E) && CFG_TUH_MAX3421E static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(0); -void max2342e_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { +void max3421e_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { if ( !(pin == MAX3241E_INTR_PIN && action == NRF_GPIOTE_POLARITY_HITOLO) ) return; tuh_int_handler(1); } +static inline void max3421e_cs_assert(bool active) { + nrf_gpio_pin_write(MAX3421E_CS_PIN, active ? 0 : 1); +} + +//--------------------------------------------------------------------+ // API: SPI transfer with MAX3421E, must be implemented by application -bool tuh_max3421e_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len) { +//--------------------------------------------------------------------+ + +bool tuh_max3421e_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, + uint8_t * rx_buf, size_t rx_len, bool keep_cs) { (void) rhport; + + max3421e_cs_assert(true); + nrfx_spim_xfer_desc_t xfer = { .p_tx_buffer = tx_buf, .tx_length = tx_len, .p_rx_buffer = rx_buf, .rx_length = rx_len, }; - return nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS; + + bool ret = (nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS); + + if ( !keep_cs ) max3421e_cs_assert(false); + + return ret; } #endif @@ -203,12 +219,16 @@ void board_init(void) { #endif #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421E) && CFG_TUH_MAX3421E + // manually manage CS + nrf_gpio_cfg_output(MAX3421E_CS_PIN); + max3421e_cs_assert(false); + // USB host using max3421e usb controller via SPI nrfx_spim_config_t cfg = { - .sck_pin = SPI_SCK_PIN, - .mosi_pin = SPI_MOSI_PIN, - .miso_pin = SPI_MISO_PIN, - .ss_pin = SPI_CS_PIN, + .sck_pin = MAX3421E_SCK_PIN, + .mosi_pin = MAX3421E_MOSI_PIN, + .miso_pin = MAX3421E_MISO_PIN, + .ss_pin = NRFX_SPIM_PIN_NOT_USED, .ss_active_high = false, .irq_priority = 3, .orc = 0xFF, @@ -226,7 +246,7 @@ void board_init(void) { nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true); in_config.pull = NRF_GPIO_PIN_PULLUP; - nrfx_gpiote_in_init(MAX3241E_INTR_PIN, &in_config, max2342e_int_handler); + nrfx_gpiote_in_init(MAX3241E_INTR_PIN, &in_config, max3421e_int_handler); nrfx_gpiote_in_event_enable(MAX3241E_INTR_PIN, true); #endif diff --git a/src/host/hcd.h b/src/host/hcd.h index 1b5038ef4..079877b79 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -177,7 +177,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr); // Submit a special transfer to send 8-byte Setup Packet, when complete hcd_event_xfer_complete() must be invoked -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]); +bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8]); // clear stall, data toggle is also reset to DATA0 bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr); diff --git a/src/host/usbh.c b/src/host/usbh.c index 5423df669..7a09f5b6e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -552,8 +552,7 @@ static void _control_blocking_complete_cb(tuh_xfer_t* xfer) } // TODO timeout_ms is not supported yet -bool tuh_control_xfer (tuh_xfer_t* xfer) -{ +bool tuh_control_xfer (tuh_xfer_t* xfer) { // EP0 with setup packet TU_VERIFY(xfer->ep_addr == 0 && xfer->setup); @@ -565,8 +564,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); bool const is_idle = (_ctrl_xfer.stage == CONTROL_STAGE_IDLE); - if (is_idle) - { + if (is_idle) { _ctrl_xfer.stage = CONTROL_STAGE_SETUP; _ctrl_xfer.daddr = daddr; _ctrl_xfer.actual_len = 0; @@ -588,11 +586,9 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) TU_LOG_PTR(CFG_TUH_LOG_LEVEL, xfer->setup); TU_LOG_USBH("\r\n"); - if (xfer->complete_cb) - { + if (xfer->complete_cb) { TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t const*) &_ctrl_xfer.request) ); - }else - { + }else { // blocking if complete callback is not provided // change callback to internal blocking, and result as user argument volatile xfer_result_t result = XFER_RESULT_INVALID; @@ -656,15 +652,13 @@ static void _xfer_complete(uint8_t daddr, xfer_result_t result) } } -static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ +static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) ep_addr; const uint8_t rhport = usbh_get_rhport(dev_addr); tusb_control_request_t const * request = &_ctrl_xfer.request; - if (XFER_RESULT_SUCCESS != result) - { + if (XFER_RESULT_SUCCESS != result) { TU_LOG1("[%u:%u] Control %s, xferred_bytes = %lu\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes); #if CFG_TUSB_DEBUG == 1 TU_LOG1_PTR(request); @@ -673,13 +667,10 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result // terminate transfer if any stage failed _xfer_complete(dev_addr, result); - }else - { - switch(_ctrl_xfer.stage) - { + }else { + switch(_ctrl_xfer.stage) { case CONTROL_STAGE_SETUP: - if (request->wLength) - { + if (request->wLength) { // DATA stage: initial data toggle is always 1 _set_control_xfer_stage(CONTROL_STAGE_DATA); TU_ASSERT( hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength) ); @@ -688,8 +679,7 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result TU_ATTR_FALLTHROUGH; case CONTROL_STAGE_DATA: - if (request->wLength) - { + if (request->wLength) { TU_LOG_USBH("[%u:%u] Control data:\r\n", rhport, dev_addr); TU_LOG_MEM(CFG_TUH_LOG_LEVEL, _ctrl_xfer.buffer, xferred_bytes, 2); } @@ -1538,9 +1528,7 @@ static bool enum_new_device(hcd_event_t* event) xfer.result = XFER_RESULT_SUCCESS; xfer.user_data = ENUM_ADDR0_DEVICE_DESC; - process_enumeration(&xfer); - } #if CFG_TUH_HUB else diff --git a/src/portable/analog/max3421e/hcd_max3421e.c b/src/portable/analog/max3421e/hcd_max3421e.c index 870c616a9..c9596f695 100644 --- a/src/portable/analog/max3421e/hcd_max3421e.c +++ b/src/portable/analog/max3421e/hcd_max3421e.c @@ -136,30 +136,64 @@ enum { HRSL_JSTATUS = 1u << 7, }; +enum { + HRSL_SUCCESS = 0, + HRSL_BUSY, + HRSL_BAD_REQ, + HRSL_UNDEF, + HRSL_NAK, + HRSL_STALL, + HRSL_TOG_ERR, + HRSL_WRONG_PID, + HRSL_BAD_BYTECOUNT, + HRSL_PID_ERR, + HRSL_PKT_ERR, + HRSL_CRC_ERR, + HRSL_K_ERR, + HRSL_J_ERR, + HRSL_TIMEOUT, + HRSL_BABBLE, +}; + + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ typedef struct { + // cached register uint8_t mode; + uint8_t peraddr; + uint8_t hxfr; volatile uint16_t frame_count; + + struct { + uint16_t packet_size; + uint16_t total_len; + uint8_t xfer_type; + }ep[8][2]; } max2341e_data_t; static max2341e_data_t _hcd_data; //--------------------------------------------------------------------+ -// +// API: SPI transfer with MAX3421E, must be implemented by application //--------------------------------------------------------------------+ -// API: SPI transfer with MAX3421E, must be implemented by application -bool tuh_max3421e_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len); +bool tuh_max3421e_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, + uint8_t * rx_buf, size_t rx_len, bool keep_cs); +//void tuh_max3421e_int_enable(uint8_t rhport, bool enabled); + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ // return HIRQ register since we are in full-duplex mode static uint8_t reg_write(uint8_t reg, uint8_t data) { uint8_t tx_buf[2] = {reg | CMDBYTE_WRITE, data}; uint8_t rx_buf[2] = {0, 0}; - tuh_max3421e_spi_xfer_api(0, tx_buf, 2, rx_buf, 2); + tuh_max3421e_spi_xfer_api(0, tx_buf, 2, rx_buf, 2, false); TU_LOG2("HIRQ: %02X\r\n", rx_buf[0]); return rx_buf[0]; } @@ -167,7 +201,7 @@ static uint8_t reg_write(uint8_t reg, uint8_t data) { static uint8_t reg_read(uint8_t reg) { uint8_t tx_buf[2] = {reg, 0}; uint8_t rx_buf[2] = {0, 0}; - return tuh_max3421e_spi_xfer_api(0, tx_buf, 2, rx_buf, 2) ? rx_buf[1] : 0; + return tuh_max3421e_spi_xfer_api(0, tx_buf, 2, rx_buf, 2, false) ? rx_buf[1] : 0; } static inline uint8_t mode_write(uint8_t data) { @@ -175,6 +209,24 @@ static inline uint8_t mode_write(uint8_t data) { return reg_write(MODE_ADDR, data); } +static inline uint8_t peraddr_write(uint8_t data) { + if ( _hcd_data.peraddr == data ) return 0; // no need to change address + + _hcd_data.peraddr = data; + return reg_write(PERADDR_ADDR, data); +} + +static inline uint8_t hxfr_write(uint8_t data) { + _hcd_data.hxfr = data; + return reg_write(HXFR_ADDR, data); +} + +static void fifo_write(uint8_t reg, uint8_t const * buffer, uint16_t len) { + uint8_t tx_buf[1] = {reg | CMDBYTE_WRITE}; + tuh_max3421e_spi_xfer_api(0, tx_buf, 1, NULL, 0, true); + tuh_max3421e_spi_xfer_api(0, buffer, len, NULL, 0, false); +} + //--------------------------------------------------------------------+ // Controller API @@ -252,7 +304,7 @@ bool hcd_init(uint8_t rhport) { mode_write(MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST); // Enable Connection IRQ - reg_write(HIEN_ADDR, HIRQ_CONDET_IRQ | HIRQ_FRAME_IRQ); + reg_write(HIEN_ADDR, HIRQ_CONDET_IRQ | HIRQ_FRAME_IRQ | HIRQ_HXFRDN_IRQ); #if 0 // Note: if device is already connected, CONDET IRQ may not be triggered. @@ -271,33 +323,6 @@ bool hcd_init(uint8_t rhport) { return true; } -// Interrupt Handler -void hcd_int_handler(uint8_t rhport) { - (void) rhport; - - uint8_t hirq = reg_read(HIRQ_ADDR); - TU_LOG3_HEX(hirq); - - if (hirq & HIRQ_CONDET_IRQ) { - tusb_speed_t speed = handle_connect_irq(rhport); - - if (speed == TUSB_SPEED_INVALID) { - hcd_event_device_remove(rhport, true); - }else { - hcd_event_device_attach(rhport, true); - } - } - - if (hirq & HIRQ_FRAME_IRQ) { - _hcd_data.frame_count++; - } - - // clear all interrupt - if ( hirq ) { - reg_write(HIRQ_ADDR, hirq); - } -} - // Enable USB interrupt void hcd_int_enable (uint8_t rhport) { (void) rhport; @@ -359,7 +384,12 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const (void) dev_addr; (void) ep_desc; - return false; + uint8_t ep_num = tu_edpt_number(ep_desc->bEndpointAddress); + uint8_t ep_dir = tu_edpt_dir(ep_desc->bEndpointAddress); + + _hcd_data.ep[ep_num][ep_dir].packet_size = tu_edpt_packet_size(ep_desc); + + return true; } // Submit a transfer, when complete hcd_event_xfer_complete() must be invoked @@ -384,12 +414,18 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { } // Submit a special transfer to send 8-byte Setup Packet, when complete hcd_event_xfer_complete() must be invoked -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { +bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8]) { (void) rhport; - (void) dev_addr; + (void) daddr; (void) setup_packet; - return false; + _hcd_data.ep[0][0].total_len = 8; + + peraddr_write(daddr); + fifo_write(SUDFIFO_ADDR, setup_packet, 8); + hxfr_write(HXFR_SETUP); + + return true; } // clear stall, data toggle is also reset to DATA0 @@ -401,4 +437,67 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { return false; } +// Interrupt Handler +void hcd_int_handler(uint8_t rhport) { + uint8_t hirq = reg_read(HIRQ_ADDR); + TU_LOG3_HEX(hirq); + + if (hirq & HIRQ_CONDET_IRQ) { + tusb_speed_t speed = handle_connect_irq(rhport); + + if (speed == TUSB_SPEED_INVALID) { + hcd_event_device_remove(rhport, true); + }else { + hcd_event_device_attach(rhport, true); + } + } + + if (hirq & HIRQ_FRAME_IRQ) { + _hcd_data.frame_count++; + } + + if (hirq & HIRQ_HXFRDN_IRQ) { + uint8_t const hrsl = reg_read(HRSL_ADDR); + uint8_t const result = hrsl & HRSL_RESULT_MASK; + uint8_t xfer_result; + + TU_LOG3("HRSL: %02X\r\n", hrsl); + switch(result) { + case HRSL_SUCCESS: + xfer_result = XFER_RESULT_SUCCESS; + break; + + case HRSL_STALL: + xfer_result = XFER_RESULT_STALLED; + break; + + default: + xfer_result = XFER_RESULT_FAILED; + break; + } + + uint8_t ep_dir = 0; + uint8_t ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK; + uint8_t const xfer_type = _hcd_data.hxfr & 0xf0; + + if ( xfer_type & HXFR_SETUP ) { + // SETUP transfer + ep_dir = 0; + }else if ( !(xfer_type & HXFR_OUT_NIN) ) { + // IN transfer + ep_dir = 1; + } + + uint8_t const ep_addr = tu_edpt_addr(ep_num, ep_dir); + uint16_t xferred_len = _hcd_data.ep[ep_num][ep_dir].total_len; + + hcd_event_xfer_complete(_hcd_data.peraddr, ep_addr, xferred_len, xfer_result, true); + } + + // clear all interrupt + if ( hirq ) { + reg_write(HIRQ_ADDR, hirq); + } +} + #endif From e3f3179924f7c84c4bb3e69234720f9afc178727 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 23 Aug 2023 15:08:12 +0700 Subject: [PATCH 06/71] able to get 8 byte descriptor, but read(RCVBC) always return 0 - rename max3421e to max3421 - fix incorrect bitmask for HCTL, fix initial device connect - fix bus reset cause connect IRQ --- hw/bsp/nrf/family.c | 24 +- hw/bsp/nrf/family.cmake | 2 +- src/host/hcd.h | 2 +- .../hcd_max3421e.c => max3421/hcd_max3421.c} | 284 ++++++++++++------ 4 files changed, 208 insertions(+), 104 deletions(-) rename src/portable/analog/{max3421e/hcd_max3421e.c => max3421/hcd_max3421.c} (67%) diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 862f67bc7..45a5166a7 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -93,7 +93,7 @@ TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) { } //------------- Host using MAX2341E -------------// -#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421E) && CFG_TUH_MAX3421E +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(0); void max3421e_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { @@ -102,19 +102,17 @@ void max3421e_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { tuh_int_handler(1); } -static inline void max3421e_cs_assert(bool active) { - nrf_gpio_pin_write(MAX3421E_CS_PIN, active ? 0 : 1); -} - //--------------------------------------------------------------------+ // API: SPI transfer with MAX3421E, must be implemented by application //--------------------------------------------------------------------+ -bool tuh_max3421e_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, - uint8_t * rx_buf, size_t rx_len, bool keep_cs) { +void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { (void) rhport; + nrf_gpio_pin_write(MAX3421E_CS_PIN, active ? 0 : 1); +} - max3421e_cs_assert(true); +bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len) { + (void) rhport; nrfx_spim_xfer_desc_t xfer = { .p_tx_buffer = tx_buf, @@ -123,11 +121,7 @@ bool tuh_max3421e_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx .rx_length = rx_len, }; - bool ret = (nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS); - - if ( !keep_cs ) max3421e_cs_assert(false); - - return ret; + return (nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS); } #endif @@ -218,10 +212,10 @@ void board_init(void) { if ( usb_reg & OUTPUTRDY_Msk ) tusb_hal_nrf_power_event(USB_EVT_READY); #endif -#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421E) && CFG_TUH_MAX3421E +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 // manually manage CS nrf_gpio_cfg_output(MAX3421E_CS_PIN); - max3421e_cs_assert(false); + tuh_max3421_spi_cs_api(0, false); // USB host using max3421e usb controller via SPI nrfx_spim_config_t cfg = { diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index 8bf7bcb52..ff6b882ce 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -124,7 +124,7 @@ function(family_configure_example TARGET RTOS) family_add_tinyusb(${TARGET} OPT_MCU_NRF5X ${RTOS}) target_sources(${TARGET}-tinyusb PUBLIC ${TOP}/src/portable/nordic/nrf5x/dcd_nrf5x.c - ${TOP}/src/portable/analog/max3421e/hcd_max3421e.c + ${TOP}/src/portable/analog/max3421/hcd_max3421.c ) target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) diff --git a/src/host/hcd.h b/src/host/hcd.h index 079877b79..1f01a1a2f 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -170,7 +170,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr); bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); // Submit a transfer, when complete hcd_event_xfer_complete() must be invoked -bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); +bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); // Abort a queued transfer. Note: it can only abort transfer that has not been started // Return true if a queued transfer is aborted, false if there is no transfer to abort diff --git a/src/portable/analog/max3421e/hcd_max3421e.c b/src/portable/analog/max3421/hcd_max3421.c similarity index 67% rename from src/portable/analog/max3421e/hcd_max3421e.c rename to src/portable/analog/max3421/hcd_max3421.c index c9596f695..edcb6ca6f 100644 --- a/src/portable/analog/max3421e/hcd_max3421e.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421E) && CFG_TUH_MAX3421E +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 #include "host/hcd.h" @@ -110,14 +110,14 @@ enum { }; enum { - HCTL_BUSRST = 1u << 1, - HCTL_FRMRST = 1u << 2, - HCTL_SAMPLEBUS = 1u << 3, - HCTL_SIGRSM = 1u << 4, - HCTL_RCVTOG0 = 1u << 5, - HCTL_RCVTOG1 = 1u << 6, - HCTL_SNDTOG0 = 1u << 7, - HCTL_SNDTOG1 = 1u << 8, + HCTL_BUSRST = 1u << 0, + HCTL_FRMRST = 1u << 1, + HCTL_SAMPLEBUS = 1u << 2, + HCTL_SIGRSM = 1u << 3, + HCTL_RCVTOG0 = 1u << 4, + HCTL_RCVTOG1 = 1u << 5, + HCTL_SNDTOG0 = 1u << 6, + HCTL_SNDTOG1 = 1u << 7, }; enum { @@ -155,45 +155,73 @@ enum { HRSL_BABBLE, }; +enum { + DEFAULT_HIEN = HIRQ_CONDET_IRQ | HIRQ_FRAME_IRQ | HIRQ_HXFRDN_IRQ +}; //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ typedef struct { + uint8_t xfer_type; + uint8_t data_toggle; + uint16_t packet_size; + + uint16_t total_len; + uint16_t xferred_len; + uint8_t* buf; +} hcd_ep_t; + +typedef struct { + bool inited; + // cached register + uint8_t sndbc; uint8_t mode; uint8_t peraddr; uint8_t hxfr; volatile uint16_t frame_count; - struct { - uint16_t packet_size; - uint16_t total_len; - uint8_t xfer_type; - }ep[8][2]; -} max2341e_data_t; + hcd_ep_t ep[8][2]; +} max2341_data_t; -static max2341e_data_t _hcd_data; +static max2341_data_t _hcd_data; //--------------------------------------------------------------------+ // API: SPI transfer with MAX3421E, must be implemented by application //--------------------------------------------------------------------+ -bool tuh_max3421e_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, - uint8_t * rx_buf, size_t rx_len, bool keep_cs); +void tuh_max3421_spi_cs_api(uint8_t rhport, bool active); +bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len); + //void tuh_max3421e_int_enable(uint8_t rhport, bool enabled); //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ +static void fifo_write(uint8_t reg, uint8_t const * buffer, uint16_t len) { + reg |= CMDBYTE_WRITE; + + tuh_max3421_spi_cs_api(0, true); + + tuh_max3421_spi_xfer_api(0, ®, 1, NULL, 0); + tuh_max3421_spi_xfer_api(0, buffer, len, NULL, 0); + + tuh_max3421_spi_cs_api(0, false); +} + // return HIRQ register since we are in full-duplex mode static uint8_t reg_write(uint8_t reg, uint8_t data) { uint8_t tx_buf[2] = {reg | CMDBYTE_WRITE, data}; uint8_t rx_buf[2] = {0, 0}; - tuh_max3421e_spi_xfer_api(0, tx_buf, 2, rx_buf, 2, false); + + tuh_max3421_spi_cs_api(0, true); + tuh_max3421_spi_xfer_api(0, tx_buf, 2, rx_buf, 2); + tuh_max3421_spi_cs_api(0, false); + TU_LOG2("HIRQ: %02X\r\n", rx_buf[0]); return rx_buf[0]; } @@ -201,7 +229,12 @@ static uint8_t reg_write(uint8_t reg, uint8_t data) { static uint8_t reg_read(uint8_t reg) { uint8_t tx_buf[2] = {reg, 0}; uint8_t rx_buf[2] = {0, 0}; - return tuh_max3421e_spi_xfer_api(0, tx_buf, 2, rx_buf, 2, false) ? rx_buf[1] : 0; + + tuh_max3421_spi_cs_api(0, true); + bool ret = tuh_max3421_spi_xfer_api(0, tx_buf, 2, rx_buf, 2); + tuh_max3421_spi_cs_api(0, false); + + return ret ? rx_buf[1] : 0; } static inline uint8_t mode_write(uint8_t data) { @@ -221,10 +254,9 @@ static inline uint8_t hxfr_write(uint8_t data) { return reg_write(HXFR_ADDR, data); } -static void fifo_write(uint8_t reg, uint8_t const * buffer, uint16_t len) { - uint8_t tx_buf[1] = {reg | CMDBYTE_WRITE}; - tuh_max3421e_spi_xfer_api(0, tx_buf, 1, NULL, 0, true); - tuh_max3421e_spi_xfer_api(0, buffer, len, NULL, 0, false); +static inline uint8_t sndbc_write(uint8_t data) { + _hcd_data.sndbc = data; + return reg_write(SNDBC_ADDR, data); } @@ -290,8 +322,8 @@ bool hcd_init(uint8_t rhport) { tu_memclr(&_hcd_data, sizeof(_hcd_data)); - // full duplex, interrupt level (should be configurable) - reg_write(PINCTL_ADDR, PINCTL_FDUPSPI | PINCTL_INTLEVEL); + // full duplex, interrupt negative edge + reg_write(PINCTL_ADDR, PINCTL_FDUPSPI); // reset reg_write(USBCTL_ADDR, USBCTL_CHIPRES); @@ -303,19 +335,16 @@ bool hcd_init(uint8_t rhport) { // Mode: Host and DP/DM pull down mode_write(MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST); + // bus reset, this will trigger CONDET IRQ if device is already connected + reg_write(HCTL_ADDR, HCTL_BUSRST); + + // clear all previously pending IRQ + reg_write(HIRQ_ADDR, 0xff); + + _hcd_data.inited = true; + // Enable Connection IRQ - reg_write(HIEN_ADDR, HIRQ_CONDET_IRQ | HIRQ_FRAME_IRQ | HIRQ_HXFRDN_IRQ); - - #if 0 - // Note: if device is already connected, CONDET IRQ may not be triggered. - // We need to detect it by sampling bus signal. FIXME not working - reg_write(HCTL_ADDR, HCTL_SAMPLEBUS); - while ( reg_read(HCTL_ADDR) & HCTL_SAMPLEBUS ) {} - - if ( TUSB_SPEED_INVALID != handle_connect_irq(rhport) ) { - reg_write(HIRQ_ADDR, HIRQ_CONDET_IRQ); // clear connect irq - } - #endif + reg_write(HIEN_ADDR, DEFAULT_HIEN); // Enable Interrupt pin reg_write(CPUCTL_ADDR, CPUCTL_IE); @@ -353,6 +382,10 @@ bool hcd_port_connect_status(uint8_t rhport) { // Some port would require hcd_port_reset_end() to be invoked after 10ms to complete the reset sequence. void hcd_port_reset(uint8_t rhport) { (void) rhport; + // Bus reset will also trigger CONDET IRQ, disable it + uint8_t hien = DEFAULT_HIEN & ~HIRQ_CONDET_IRQ; + reg_write(HIEN_ADDR, hien); + reg_write(HCTL_ADDR, HCTL_BUSRST); } @@ -360,6 +393,10 @@ void hcd_port_reset(uint8_t rhport) { void hcd_port_reset_end(uint8_t rhport) { (void) rhport; reg_write(HCTL_ADDR, 0); + + // Bus reset will also trigger CONDET IRQ, clear and re-enable it after reset + reg_write(HIRQ_ADDR, HIRQ_CONDET_IRQ); + reg_write(HIEN_ADDR, DEFAULT_HIEN); } // Get port link speed @@ -393,14 +430,51 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const } // Submit a transfer, when complete hcd_event_xfer_complete() must be invoked -bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { +bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { (void) rhport; - (void) dev_addr; - (void) ep_addr; - (void) buffer; - (void) buflen; - return false; + uint8_t const ep_num = tu_edpt_number(ep_addr); + uint8_t const ep_dir = tu_edpt_dir(ep_addr); + + hcd_ep_t* ep = &_hcd_data.ep[ep_num][ep_dir]; + + ep->buf = buffer; + ep->total_len = buflen; + ep->xferred_len = 0; + + uint8_t hirq = peraddr_write(daddr); + + uint8_t hctl = 0; + uint8_t hxfr = ep_num; + if ( ep_num == 0 ) { + ep->data_toggle = 1; + if ( buffer == NULL || buflen == 0 ) { + // ZLP for ACK stage + hxfr |= HXFR_HS; + } + } else if ( ep->xfer_type == TUSB_XFER_ISOCHRONOUS ) { + hxfr |= HXFR_ISO; + } + + if ( 0 == ep_dir ) { + // Page 12: Programming BULK-OUT Transfers + TU_ASSERT(hirq & HIRQ_RCVDAV_IRQ); + + uint8_t const xact_len = (uint8_t) tu_min16(buflen, ep->packet_size); + fifo_write(SNDFIFO_ADDR, buffer, xact_len); + reg_write(SNDBC_ADDR, xact_len); + + hctl = (ep->data_toggle ? HCTL_SNDTOG1 : HCTL_SNDTOG0); + hxfr |= HXFR_OUT_NIN; + } else { + // Page 13: Programming BULK-IN Transfers + hctl = (ep->data_toggle ? HCTL_RCVTOG1 : HCTL_RCVTOG0); + } + + reg_write(HCTL_ADDR, hctl); + hxfr_write(hxfr); + + return true; } // Abort a queued transfer. Note: it can only abort transfer that has not been started @@ -416,10 +490,10 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { // Submit a special transfer to send 8-byte Setup Packet, when complete hcd_event_xfer_complete() must be invoked bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8]) { (void) rhport; - (void) daddr; - (void) setup_packet; - _hcd_data.ep[0][0].total_len = 8; + hcd_ep_t* ep = &_hcd_data.ep[0][0]; + ep->total_len = 8; + ep->xferred_len = 0; peraddr_write(daddr); fifo_write(SUDFIFO_ADDR, setup_packet, 8); @@ -437,11 +511,79 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { return false; } +static void handle_xfer_done(uint8_t rhport) { + (void) rhport; + + uint8_t const hrsl = reg_read(HRSL_ADDR); + uint8_t const result = hrsl & HRSL_RESULT_MASK; + uint8_t xfer_result; + + TU_LOG3("HRSL: %02X\r\n", hrsl); + switch(result) { + case HRSL_SUCCESS: + xfer_result = XFER_RESULT_SUCCESS; + break; + + case HRSL_STALL: + xfer_result = XFER_RESULT_STALLED; + break; + + case HRSL_BAD_REQ: + // occurred when initialized without any pending transfer. Skip for now + return; + + default: + xfer_result = XFER_RESULT_FAILED; + break; + } + + uint8_t ep_dir = 0; + uint8_t ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK; + uint8_t const xfer_type = _hcd_data.hxfr & 0xf0; + + hcd_ep_t * ep; + + if ( (xfer_type & HXFR_SETUP) || (xfer_type & HXFR_OUT_NIN) ) { + // SETUP or OUT transfer + ep_dir = 0; + ep = &_hcd_data.ep[ep_num][ep_dir]; + + uint8_t const xact_len = (xfer_type & HXFR_SETUP) ? 8 : _hcd_data.sndbc; + ep->xferred_len += xact_len; + + if ( xact_len < ep->packet_size || ep->xferred_len >= ep->total_len ) { + hcd_event_xfer_complete(_hcd_data.peraddr, ep_num, ep->xferred_len, xfer_result, true); + }else { + // more to transfer + } + } else { + // IN transfer + ep_dir = 1; + ep = &_hcd_data.ep[ep_num][ep_dir]; + uint8_t const xact_len = reg_read(RCVBC_ADDR); + ep->xferred_len += xact_len; + + // short packet or all bytes transferred + if ( xact_len < ep->packet_size || ep->xferred_len >= ep->total_len ) { + hcd_event_xfer_complete(_hcd_data.peraddr, TUSB_DIR_IN_MASK | ep_num, ep->xferred_len, xfer_result, true); + }else { + // more to transfer + } + } +} + // Interrupt Handler void hcd_int_handler(uint8_t rhport) { + // not initialized, do nothing + if ( !_hcd_data.inited ) return; + uint8_t hirq = reg_read(HIRQ_ADDR); TU_LOG3_HEX(hirq); + if (hirq & HIRQ_FRAME_IRQ) { + _hcd_data.frame_count++; + } + if (hirq & HIRQ_CONDET_IRQ) { tusb_speed_t speed = handle_connect_irq(rhport); @@ -452,49 +594,17 @@ void hcd_int_handler(uint8_t rhport) { } } - if (hirq & HIRQ_FRAME_IRQ) { - _hcd_data.frame_count++; - } - if (hirq & HIRQ_HXFRDN_IRQ) { - uint8_t const hrsl = reg_read(HRSL_ADDR); - uint8_t const result = hrsl & HRSL_RESULT_MASK; - uint8_t xfer_result; - - TU_LOG3("HRSL: %02X\r\n", hrsl); - switch(result) { - case HRSL_SUCCESS: - xfer_result = XFER_RESULT_SUCCESS; - break; - - case HRSL_STALL: - xfer_result = XFER_RESULT_STALLED; - break; - - default: - xfer_result = XFER_RESULT_FAILED; - break; - } - - uint8_t ep_dir = 0; - uint8_t ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK; - uint8_t const xfer_type = _hcd_data.hxfr & 0xf0; - - if ( xfer_type & HXFR_SETUP ) { - // SETUP transfer - ep_dir = 0; - }else if ( !(xfer_type & HXFR_OUT_NIN) ) { - // IN transfer - ep_dir = 1; - } - - uint8_t const ep_addr = tu_edpt_addr(ep_num, ep_dir); - uint16_t xferred_len = _hcd_data.ep[ep_num][ep_dir].total_len; - - hcd_event_xfer_complete(_hcd_data.peraddr, ep_addr, xferred_len, xfer_result, true); + handle_xfer_done(rhport); } - // clear all interrupt + if ( hirq & HIRQ_RCVDAV_IRQ ) { + TU_LOG3("RCVDAV\r\n"); + TU_LOG3_INT(reg_read(RCVBC_ADDR)); + } + + // clear all interrupt execept SNDBAV_IRQ + hirq &= ~HIRQ_SNDBAV_IRQ; if ( hirq ) { reg_write(HIRQ_ADDR, hirq); } From 2c237b1ae4b3ffd38fc74df29da63b01348afd1d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 23 Aug 2023 17:49:28 +0700 Subject: [PATCH 07/71] able to complete 1st get device descriptor and set address --- src/portable/analog/max3421/hcd_max3421.c | 182 +++++++++++++++------- 1 file changed, 127 insertions(+), 55 deletions(-) diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index edcb6ca6f..467d7410a 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -156,7 +156,7 @@ enum { }; enum { - DEFAULT_HIEN = HIRQ_CONDET_IRQ | HIRQ_FRAME_IRQ | HIRQ_HXFRDN_IRQ + DEFAULT_HIEN = HIRQ_CONDET_IRQ | HIRQ_FRAME_IRQ | HIRQ_HXFRDN_IRQ | HIRQ_RCVDAV_IRQ }; //--------------------------------------------------------------------+ @@ -178,6 +178,8 @@ typedef struct { // cached register uint8_t sndbc; + uint8_t hirq; + uint8_t hien; uint8_t mode; uint8_t peraddr; uint8_t hxfr; @@ -203,60 +205,86 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_ //--------------------------------------------------------------------+ static void fifo_write(uint8_t reg, uint8_t const * buffer, uint16_t len) { + uint8_t const rhport = 0; + uint8_t hirq; reg |= CMDBYTE_WRITE; - tuh_max3421_spi_cs_api(0, true); + tuh_max3421_spi_cs_api(rhport, true); - tuh_max3421_spi_xfer_api(0, ®, 1, NULL, 0); - tuh_max3421_spi_xfer_api(0, buffer, len, NULL, 0); + tuh_max3421_spi_xfer_api(rhport, ®, 1, &hirq, 1); + _hcd_data.hirq = hirq; + tuh_max3421_spi_xfer_api(rhport, buffer, len, NULL, 0); + + tuh_max3421_spi_cs_api(rhport, false); - tuh_max3421_spi_cs_api(0, false); } -// return HIRQ register since we are in full-duplex mode -static uint8_t reg_write(uint8_t reg, uint8_t data) { +static void fifo_read(uint8_t * buffer, uint16_t len) { + uint8_t const rhport = 0; + uint8_t hirq; + uint8_t const reg = RCVVFIFO_ADDR; + + tuh_max3421_spi_cs_api(rhport, true); + + tuh_max3421_spi_xfer_api(rhport, ®, 1, &hirq, 0); + _hcd_data.hirq = hirq; + tuh_max3421_spi_xfer_api(rhport, NULL, 0, buffer, len); + + tuh_max3421_spi_cs_api(rhport, false); +} + +static void reg_write(uint8_t reg, uint8_t data) { + uint8_t const rhport = 0; uint8_t tx_buf[2] = {reg | CMDBYTE_WRITE, data}; uint8_t rx_buf[2] = {0, 0}; - tuh_max3421_spi_cs_api(0, true); - tuh_max3421_spi_xfer_api(0, tx_buf, 2, rx_buf, 2); - tuh_max3421_spi_cs_api(0, false); + tuh_max3421_spi_cs_api(rhport, true); + tuh_max3421_spi_xfer_api(rhport, tx_buf, 2, rx_buf, 2); + tuh_max3421_spi_cs_api(rhport, false); - TU_LOG2("HIRQ: %02X\r\n", rx_buf[0]); - return rx_buf[0]; + // HIRQ register since we are in full-duplex mode + _hcd_data.hirq = rx_buf[0]; + TU_LOG3_HEX(_hcd_data.hirq); } static uint8_t reg_read(uint8_t reg) { + uint8_t const rhport = 0; uint8_t tx_buf[2] = {reg, 0}; uint8_t rx_buf[2] = {0, 0}; - tuh_max3421_spi_cs_api(0, true); - bool ret = tuh_max3421_spi_xfer_api(0, tx_buf, 2, rx_buf, 2); - tuh_max3421_spi_cs_api(0, false); + tuh_max3421_spi_cs_api(rhport, true); + bool ret = tuh_max3421_spi_xfer_api(rhport, tx_buf, 2, rx_buf, 2); + tuh_max3421_spi_cs_api(rhport, false); + _hcd_data.hirq = rx_buf[0]; return ret ? rx_buf[1] : 0; } -static inline uint8_t mode_write(uint8_t data) { - _hcd_data.mode = data; - return reg_write(MODE_ADDR, data); +static inline void hien_write(uint8_t data) { + _hcd_data.hien = data; + reg_write(HIEN_ADDR, data); } -static inline uint8_t peraddr_write(uint8_t data) { - if ( _hcd_data.peraddr == data ) return 0; // no need to change address +static inline void mode_write(uint8_t data) { + _hcd_data.mode = data; + reg_write(MODE_ADDR, data); +} + +static inline void peraddr_write(uint8_t data) { + if ( _hcd_data.peraddr == data ) return; // no need to change address _hcd_data.peraddr = data; - return reg_write(PERADDR_ADDR, data); + reg_write(PERADDR_ADDR, data); } -static inline uint8_t hxfr_write(uint8_t data) { +static inline void hxfr_write(uint8_t data) { _hcd_data.hxfr = data; - return reg_write(HXFR_ADDR, data); + reg_write(HXFR_ADDR, data); } -static inline uint8_t sndbc_write(uint8_t data) { +static inline void sndbc_write(uint8_t data) { _hcd_data.sndbc = data; - return reg_write(SNDBC_ADDR, data); + reg_write(SNDBC_ADDR, data); } @@ -335,16 +363,16 @@ bool hcd_init(uint8_t rhport) { // Mode: Host and DP/DM pull down mode_write(MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST); - // bus reset, this will trigger CONDET IRQ if device is already connected - reg_write(HCTL_ADDR, HCTL_BUSRST); + // frame reset & bus reset, this will trigger CONDET IRQ if device is already connected + reg_write(HCTL_ADDR, HCTL_BUSRST | HCTL_FRMRST); // clear all previously pending IRQ reg_write(HIRQ_ADDR, 0xff); _hcd_data.inited = true; - // Enable Connection IRQ - reg_write(HIEN_ADDR, DEFAULT_HIEN); + // Enable IRQ + hien_write(DEFAULT_HIEN); // Enable Interrupt pin reg_write(CPUCTL_ADDR, CPUCTL_IE); @@ -383,8 +411,8 @@ bool hcd_port_connect_status(uint8_t rhport) { void hcd_port_reset(uint8_t rhport) { (void) rhport; // Bus reset will also trigger CONDET IRQ, disable it - uint8_t hien = DEFAULT_HIEN & ~HIRQ_CONDET_IRQ; - reg_write(HIEN_ADDR, hien); + uint8_t const hien = DEFAULT_HIEN & ~HIRQ_CONDET_IRQ; + hien_write(hien); reg_write(HCTL_ADDR, HCTL_BUSRST); } @@ -396,7 +424,7 @@ void hcd_port_reset_end(uint8_t rhport) { // Bus reset will also trigger CONDET IRQ, clear and re-enable it after reset reg_write(HIRQ_ADDR, HIRQ_CONDET_IRQ); - reg_write(HIEN_ADDR, DEFAULT_HIEN); + hien_write(DEFAULT_HIEN); } // Get port link speed @@ -426,6 +454,10 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const _hcd_data.ep[ep_num][ep_dir].packet_size = tu_edpt_packet_size(ep_desc); + if (ep_desc->bEndpointAddress == 0) { + _hcd_data.ep[ep_num][1].packet_size = tu_edpt_packet_size(ep_desc); + } + return true; } @@ -442,15 +474,18 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf ep->total_len = buflen; ep->xferred_len = 0; - uint8_t hirq = peraddr_write(daddr); + peraddr_write(daddr); uint8_t hctl = 0; uint8_t hxfr = ep_num; if ( ep_num == 0 ) { ep->data_toggle = 1; if ( buffer == NULL || buflen == 0 ) { - // ZLP for ACK stage + // ZLP for ACK stage, use HS hxfr |= HXFR_HS; + hxfr |= (ep_dir ? 0 : HXFR_OUT_NIN); + hxfr_write(hxfr); + return true; } } else if ( ep->xfer_type == TUSB_XFER_ISOCHRONOUS ) { hxfr |= HXFR_ISO; @@ -458,7 +493,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf if ( 0 == ep_dir ) { // Page 12: Programming BULK-OUT Transfers - TU_ASSERT(hirq & HIRQ_RCVDAV_IRQ); + TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ); uint8_t const xact_len = (uint8_t) tu_min16(buflen, ep->packet_size); fifo_write(SNDFIFO_ADDR, buffer, xact_len); @@ -516,7 +551,7 @@ static void handle_xfer_done(uint8_t rhport) { uint8_t const hrsl = reg_read(HRSL_ADDR); uint8_t const result = hrsl & HRSL_RESULT_MASK; - uint8_t xfer_result; + xfer_result_t xfer_result; TU_LOG3("HRSL: %02X\r\n", hrsl); switch(result) { @@ -537,18 +572,21 @@ static void handle_xfer_done(uint8_t rhport) { break; } - uint8_t ep_dir = 0; uint8_t ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK; uint8_t const xfer_type = _hcd_data.hxfr & 0xf0; - hcd_ep_t * ep; - if ( (xfer_type & HXFR_SETUP) || (xfer_type & HXFR_OUT_NIN) ) { // SETUP or OUT transfer - ep_dir = 0; - ep = &_hcd_data.ep[ep_num][ep_dir]; + hcd_ep_t *ep = &_hcd_data.ep[ep_num][0]; + uint8_t xact_len; + if (xfer_type & HXFR_SETUP) { + xact_len = 8; + } else if ( xfer_type & HXFR_HS ) { + xact_len = 0; + } else { + xact_len = _hcd_data.sndbc; + } - uint8_t const xact_len = (xfer_type & HXFR_SETUP) ? 8 : _hcd_data.sndbc; ep->xferred_len += xact_len; if ( xact_len < ep->packet_size || ep->xferred_len >= ep->total_len ) { @@ -558,10 +596,27 @@ static void handle_xfer_done(uint8_t rhport) { } } else { // IN transfer - ep_dir = 1; - ep = &_hcd_data.ep[ep_num][ep_dir]; - uint8_t const xact_len = reg_read(RCVBC_ADDR); - ep->xferred_len += xact_len; + hcd_ep_t *ep = &_hcd_data.ep[ep_num][1]; + uint8_t xact_len; + + if ( xfer_type & HXFR_HS ) { + xact_len = 0; + } else { + // RCVDAV_IRQ can trigger 2 times (dual buffered) + while ( _hcd_data.hirq & HIRQ_RCVDAV_IRQ ) { + uint8_t rcvbc = reg_read(RCVBC_ADDR); + xact_len = (uint8_t) tu_min16(rcvbc, ep->total_len - ep->xferred_len); + if ( xact_len ) { + fifo_read(ep->buf, xact_len); + ep->buf += xact_len; + ep->xferred_len += xact_len; + } + + // ack RCVDVAV IRQ + reg_write(HIRQ_ADDR, HIRQ_RCVDAV_IRQ); + _hcd_data.hirq = reg_read(HIRQ_ADDR); + } + } // short packet or all bytes transferred if ( xact_len < ep->packet_size || ep->xferred_len >= ep->total_len ) { @@ -572,13 +627,35 @@ static void handle_xfer_done(uint8_t rhport) { } } +#if CFG_TUSB_DEBUG >= 3 +void print_hirq(uint8_t hirq) { + TU_LOG3_HEX(hirq); + + if (hirq & HIRQ_HXFRDN_IRQ) TU_LOG3(" HXFRDN"); + if (hirq & HIRQ_FRAME_IRQ) TU_LOG3(" FRAME"); + if (hirq & HIRQ_CONDET_IRQ) TU_LOG3(" CONDET"); + if (hirq & HIRQ_SUSDN_IRQ) TU_LOG3(" SUSDN"); + if (hirq & HIRQ_SNDBAV_IRQ) TU_LOG3(" SNDBAV"); + if (hirq & HIRQ_RCVDAV_IRQ) TU_LOG3(" RCVDAV"); + if (hirq & HIRQ_RWU_IRQ) TU_LOG3(" RWU"); + if (hirq & HIRQ_BUSEVENT_IRQ) TU_LOG3(" BUSEVENT"); + + TU_LOG3("\r\n"); +} + +#else + #define print_hirq(hirq) +#endif + // Interrupt Handler void hcd_int_handler(uint8_t rhport) { // not initialized, do nothing if ( !_hcd_data.inited ) return; - uint8_t hirq = reg_read(HIRQ_ADDR); - TU_LOG3_HEX(hirq); + uint8_t hirq = reg_read(HIRQ_ADDR) & _hcd_data.hien; + if (!hirq) return; + + print_hirq(hirq); if (hirq & HIRQ_FRAME_IRQ) { _hcd_data.frame_count++; @@ -598,13 +675,8 @@ void hcd_int_handler(uint8_t rhport) { handle_xfer_done(rhport); } - if ( hirq & HIRQ_RCVDAV_IRQ ) { - TU_LOG3("RCVDAV\r\n"); - TU_LOG3_INT(reg_read(RCVBC_ADDR)); - } - - // clear all interrupt execept SNDBAV_IRQ - hirq &= ~HIRQ_SNDBAV_IRQ; + // clear all interrupt except SNDBAV_IRQ and RCVDAV_IRQ must be clear after pulling data from FIFO + hirq &= ~ (HIRQ_SNDBAV_IRQ | HIRQ_RCVDAV_IRQ); if ( hirq ) { reg_write(HIRQ_ADDR, hirq); } From 3ed5d6c3724cfa9699d403a76a00f1b04672e2b5 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 24 Aug 2023 16:27:12 +0700 Subject: [PATCH 08/71] complete enumeration --- hw/bsp/nrf/family.c | 5 +- src/portable/analog/max3421/hcd_max3421.c | 68 ++++++++++++++--------- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 45a5166a7..368763b84 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -105,6 +105,10 @@ void max3421e_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { //--------------------------------------------------------------------+ // API: SPI transfer with MAX3421E, must be implemented by application //--------------------------------------------------------------------+ +void tuh_max3421e_int_api(uint8_t rhport, bool enabled) { + (void) rhport; + nrfx_gpiote_trigger_enable(MAX3241E_INTR_PIN, enabled); +} void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { (void) rhport; @@ -241,7 +245,6 @@ void board_init(void) { in_config.pull = NRF_GPIO_PIN_PULLUP; nrfx_gpiote_in_init(MAX3241E_INTR_PIN, &in_config, max3421e_int_handler); - nrfx_gpiote_in_event_enable(MAX3241E_INTR_PIN, true); #endif } diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 467d7410a..514cf34b7 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -166,6 +166,7 @@ enum { typedef struct { uint8_t xfer_type; uint8_t data_toggle; + uint8_t xfer_complete; uint16_t packet_size; uint16_t total_len; @@ -244,7 +245,6 @@ static void reg_write(uint8_t reg, uint8_t data) { // HIRQ register since we are in full-duplex mode _hcd_data.hirq = rx_buf[0]; - TU_LOG3_HEX(_hcd_data.hirq); } static uint8_t reg_read(uint8_t reg) { @@ -473,6 +473,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf ep->buf = buffer; ep->total_len = buflen; ep->xferred_len = 0; + ep->xfer_complete = 0; peraddr_write(daddr); @@ -595,34 +596,19 @@ static void handle_xfer_done(uint8_t rhport) { // more to transfer } } else { - // IN transfer + // IN transfer: fifo data is already received in RCVDAV IRQ hcd_ep_t *ep = &_hcd_data.ep[ep_num][1]; - uint8_t xact_len; if ( xfer_type & HXFR_HS ) { - xact_len = 0; - } else { - // RCVDAV_IRQ can trigger 2 times (dual buffered) - while ( _hcd_data.hirq & HIRQ_RCVDAV_IRQ ) { - uint8_t rcvbc = reg_read(RCVBC_ADDR); - xact_len = (uint8_t) tu_min16(rcvbc, ep->total_len - ep->xferred_len); - if ( xact_len ) { - fifo_read(ep->buf, xact_len); - ep->buf += xact_len; - ep->xferred_len += xact_len; - } - - // ack RCVDVAV IRQ - reg_write(HIRQ_ADDR, HIRQ_RCVDAV_IRQ); - _hcd_data.hirq = reg_read(HIRQ_ADDR); - } + ep->xfer_complete = 1; } // short packet or all bytes transferred - if ( xact_len < ep->packet_size || ep->xferred_len >= ep->total_len ) { + if ( ep->xfer_complete ) { hcd_event_xfer_complete(_hcd_data.peraddr, TUSB_DIR_IN_MASK | ep_num, ep->xferred_len, xfer_result, true); }else { // more to transfer + hxfr_write(_hcd_data.hxfr); } } } @@ -655,7 +641,7 @@ void hcd_int_handler(uint8_t rhport) { uint8_t hirq = reg_read(HIRQ_ADDR) & _hcd_data.hien; if (!hirq) return; - print_hirq(hirq); +// print_hirq(hirq); if (hirq & HIRQ_FRAME_IRQ) { _hcd_data.frame_count++; @@ -671,12 +657,44 @@ void hcd_int_handler(uint8_t rhport) { } } - if (hirq & HIRQ_HXFRDN_IRQ) { - handle_xfer_done(rhport); + // queue more transfer in handle_xfer_done() can cause hirq to be set again while external IRQ may not catch and/or + // not call this handler again. So we need to loop until all IRQ are cleared + while ( hirq & (HIRQ_RCVDAV_IRQ | HIRQ_HXFRDN_IRQ) ) { + if ( hirq & HIRQ_RCVDAV_IRQ ) { + uint8_t ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK; + hcd_ep_t *ep = &_hcd_data.ep[ep_num][1]; + uint8_t xact_len; + + // RCVDAV_IRQ can trigger 2 times (dual buffered) + while ( hirq & HIRQ_RCVDAV_IRQ ) { + uint8_t rcvbc = reg_read(RCVBC_ADDR); + xact_len = (uint8_t) tu_min16(rcvbc, ep->total_len - ep->xferred_len); + if ( xact_len ) { + fifo_read(ep->buf, xact_len); + ep->buf += xact_len; + ep->xferred_len += xact_len; + } + + // ack RCVDVAV IRQ + reg_write(HIRQ_ADDR, HIRQ_RCVDAV_IRQ); + hirq = reg_read(HIRQ_ADDR); + } + + if ( xact_len < ep->packet_size || ep->xferred_len >= ep->total_len ) { + ep->xfer_complete = 1; + } + } + + if ( hirq & HIRQ_HXFRDN_IRQ ) { + reg_write(HIRQ_ADDR, HIRQ_HXFRDN_IRQ); + handle_xfer_done(rhport); + } + + hirq = reg_read(HIRQ_ADDR); } - // clear all interrupt except SNDBAV_IRQ and RCVDAV_IRQ must be clear after pulling data from FIFO - hirq &= ~ (HIRQ_SNDBAV_IRQ | HIRQ_RCVDAV_IRQ); + // clear all interrupt except SNDBAV_IRQ (never clear by us). Note RCVDAV_IRQ, HXFRDN_IRQ already clear while processing + hirq &= ~HIRQ_SNDBAV_IRQ; if ( hirq ) { reg_write(HIRQ_ADDR, hirq); } From 344932d27e1f65932ce922b639370ecc4fff2153 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 24 Aug 2023 16:27:32 +0700 Subject: [PATCH 09/71] add tuh_max3421e_int_api(), retry control if received NAK --- src/portable/analog/max3421/hcd_max3421.c | 60 +++++++++++++++-------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 514cf34b7..b4f75e392 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -28,6 +28,7 @@ #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 +#include #include "host/hcd.h" //--------------------------------------------------------------------+ @@ -164,11 +165,15 @@ enum { //--------------------------------------------------------------------+ typedef struct { - uint8_t xfer_type; - uint8_t data_toggle; - uint8_t xfer_complete; uint16_t packet_size; + struct TU_ATTR_PACKED { + uint8_t is_iso : 1; + uint8_t data_toggle : 1; + uint8_t xfer_queued : 1; + uint8_t xfer_complete : 1; + }; + uint16_t total_len; uint16_t xferred_len; uint8_t* buf; @@ -176,6 +181,7 @@ typedef struct { typedef struct { bool inited; + atomic_bool busy; // busy transferring // cached register uint8_t sndbc; @@ -198,8 +204,7 @@ static max2341_data_t _hcd_data; void tuh_max3421_spi_cs_api(uint8_t rhport, bool active); bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len); - -//void tuh_max3421e_int_enable(uint8_t rhport, bool enabled); +void tuh_max3421e_int_api(uint8_t rhport, bool enabled); //--------------------------------------------------------------------+ // @@ -348,6 +353,9 @@ tusb_speed_t handle_connect_irq(uint8_t rhport) { bool hcd_init(uint8_t rhport) { (void) rhport; + TU_LOG2_INT(sizeof(hcd_ep_t)); + TU_LOG2_INT(sizeof(max2341_data_t)); + tu_memclr(&_hcd_data, sizeof(_hcd_data)); // full duplex, interrupt negative edge @@ -382,12 +390,12 @@ bool hcd_init(uint8_t rhport) { // Enable USB interrupt void hcd_int_enable (uint8_t rhport) { - (void) rhport; + tuh_max3421e_int_api(rhport, true); } // Disable USB interrupt void hcd_int_disable(uint8_t rhport) { - (void) rhport; + tuh_max3421e_int_api(rhport, false); } // Get frame number (1ms) @@ -447,17 +455,20 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { (void) rhport; (void) dev_addr; - (void) ep_desc; uint8_t ep_num = tu_edpt_number(ep_desc->bEndpointAddress); uint8_t ep_dir = tu_edpt_dir(ep_desc->bEndpointAddress); - _hcd_data.ep[ep_num][ep_dir].packet_size = tu_edpt_packet_size(ep_desc); + hcd_ep_t * ep = &_hcd_data.ep[ep_num][ep_dir]; + + ep->packet_size = tu_edpt_packet_size(ep_desc); if (ep_desc->bEndpointAddress == 0) { - _hcd_data.ep[ep_num][1].packet_size = tu_edpt_packet_size(ep_desc); + _hcd_data.ep[0][1].packet_size = ep->packet_size; } + ep->is_iso = (TUSB_XFER_ISOCHRONOUS == ep_desc->bmAttributes.xfer) ? 1 : 0; + return true; } @@ -474,11 +485,13 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf ep->total_len = buflen; ep->xferred_len = 0; ep->xfer_complete = 0; + ep->xfer_queued = 1; peraddr_write(daddr); uint8_t hctl = 0; uint8_t hxfr = ep_num; + if ( ep_num == 0 ) { ep->data_toggle = 1; if ( buffer == NULL || buflen == 0 ) { @@ -488,7 +501,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf hxfr_write(hxfr); return true; } - } else if ( ep->xfer_type == TUSB_XFER_ISOCHRONOUS ) { + } else if ( ep->is_iso ) { hxfr |= HXFR_ISO; } @@ -551,11 +564,13 @@ static void handle_xfer_done(uint8_t rhport) { (void) rhport; uint8_t const hrsl = reg_read(HRSL_ADDR); - uint8_t const result = hrsl & HRSL_RESULT_MASK; + uint8_t const hresult = hrsl & HRSL_RESULT_MASK; + uint8_t ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK; + xfer_result_t xfer_result; - TU_LOG3("HRSL: %02X\r\n", hrsl); - switch(result) { + //TU_LOG3("HRSL: %02X\r\n", hrsl); + switch(hresult) { case HRSL_SUCCESS: xfer_result = XFER_RESULT_SUCCESS; break; @@ -568,21 +583,26 @@ static void handle_xfer_done(uint8_t rhport) { // occurred when initialized without any pending transfer. Skip for now return; + case HRSL_NAK: + // NAK on control, retry immediately + if (ep_num == 0) hxfr_write(_hcd_data.hxfr); + return; + default: xfer_result = XFER_RESULT_FAILED; break; } - uint8_t ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK; - uint8_t const xfer_type = _hcd_data.hxfr & 0xf0; + uint8_t const hxfr_type = _hcd_data.hxfr & 0xf0; - if ( (xfer_type & HXFR_SETUP) || (xfer_type & HXFR_OUT_NIN) ) { + if ( (hxfr_type & HXFR_SETUP) || (hxfr_type & HXFR_OUT_NIN) ) { // SETUP or OUT transfer hcd_ep_t *ep = &_hcd_data.ep[ep_num][0]; uint8_t xact_len; - if (xfer_type & HXFR_SETUP) { + + if ( hxfr_type & HXFR_SETUP) { xact_len = 8; - } else if ( xfer_type & HXFR_HS ) { + } else if ( hxfr_type & HXFR_HS ) { xact_len = 0; } else { xact_len = _hcd_data.sndbc; @@ -599,7 +619,7 @@ static void handle_xfer_done(uint8_t rhport) { // IN transfer: fifo data is already received in RCVDAV IRQ hcd_ep_t *ep = &_hcd_data.ep[ep_num][1]; - if ( xfer_type & HXFR_HS ) { + if ( hxfr_type & HXFR_HS ) { ep->xfer_complete = 1; } From e6cf125e537125fc7303afc7d0703a3de6b8b334 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 24 Aug 2023 16:46:20 +0700 Subject: [PATCH 10/71] save data toggle, always retry NAK. work with msc device --- src/portable/analog/max3421/hcd_max3421.c | 24 ++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index b4f75e392..9579409c5 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -492,7 +492,9 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf uint8_t hctl = 0; uint8_t hxfr = ep_num; - if ( ep_num == 0 ) { + if ( ep->is_iso ) { + hxfr |= HXFR_ISO; + } else if ( ep_num == 0 ) { ep->data_toggle = 1; if ( buffer == NULL || buflen == 0 ) { // ZLP for ACK stage, use HS @@ -501,8 +503,6 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf hxfr_write(hxfr); return true; } - } else if ( ep->is_iso ) { - hxfr |= HXFR_ISO; } if ( 0 == ep_dir ) { @@ -511,7 +511,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf uint8_t const xact_len = (uint8_t) tu_min16(buflen, ep->packet_size); fifo_write(SNDFIFO_ADDR, buffer, xact_len); - reg_write(SNDBC_ADDR, xact_len); + sndbc_write(xact_len); hctl = (ep->data_toggle ? HCTL_SNDTOG1 : HCTL_SNDTOG0); hxfr |= HXFR_OUT_NIN; @@ -585,7 +585,10 @@ static void handle_xfer_done(uint8_t rhport) { case HRSL_NAK: // NAK on control, retry immediately - if (ep_num == 0) hxfr_write(_hcd_data.hxfr); + //if (ep_num == 0) + { + hxfr_write(_hcd_data.hxfr); + } return; default: @@ -609,8 +612,14 @@ static void handle_xfer_done(uint8_t rhport) { } ep->xferred_len += xact_len; + ep->buf += xact_len; if ( xact_len < ep->packet_size || ep->xferred_len >= ep->total_len ) { + if ( ep_num ) { + // save data toggle for non-control + ep->data_toggle = (hrsl & HRSL_SNDTOGRD) ? 1 : 0; + } + hcd_event_xfer_complete(_hcd_data.peraddr, ep_num, ep->xferred_len, xfer_result, true); }else { // more to transfer @@ -625,6 +634,11 @@ static void handle_xfer_done(uint8_t rhport) { // short packet or all bytes transferred if ( ep->xfer_complete ) { + if ( ep_num ) { + // save data toggle for non-control + ep->data_toggle = (hrsl & HRSL_RCVTOGRD) ? 1 : 0; + } + hcd_event_xfer_complete(_hcd_data.peraddr, TUSB_DIR_IN_MASK | ep_num, ep->xferred_len, xfer_result, true); }else { // more to transfer From f5ebc1700f4bde1cc166bf5f3d8eb69d8832722a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 25 Aug 2023 12:12:44 +0700 Subject: [PATCH 11/71] add spi lock with interrupt enable/disable --- src/portable/analog/max3421/hcd_max3421.c | 176 +++++++++++----------- 1 file changed, 91 insertions(+), 85 deletions(-) diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 9579409c5..0144deca6 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -180,7 +180,6 @@ typedef struct { } hcd_ep_t; typedef struct { - bool inited; atomic_bool busy; // busy transferring // cached register @@ -194,6 +193,8 @@ typedef struct { volatile uint16_t frame_count; hcd_ep_t ep[8][2]; + + OSAL_MUTEX_DEF(spi_mutex); } max2341_data_t; static max2341_data_t _hcd_data; @@ -210,86 +211,106 @@ void tuh_max3421e_int_api(uint8_t rhport, bool enabled); // //--------------------------------------------------------------------+ -static void fifo_write(uint8_t reg, uint8_t const * buffer, uint16_t len) { - uint8_t const rhport = 0; +static void max3421_spi_lock(uint8_t rhport, bool in_isr) { + // disable interrupt and mutex lock (for pre-emptive RTOS) if not in_isr + if (!in_isr) { + tuh_max3421e_int_api(rhport, false); + } + + // assert CS + tuh_max3421_spi_cs_api(rhport, true); +} + +static void max3421_spi_unlock(uint8_t rhport, bool in_isr) { + // de-assert CS + tuh_max3421_spi_cs_api(rhport, false); + + // mutex unlock and re-enable interrupt + if (!in_isr) { + tuh_max3421e_int_api(rhport, true); + } +} + +static void fifo_write(uint8_t rhport, uint8_t reg, uint8_t const * buffer, uint16_t len, bool in_isr) { uint8_t hirq; reg |= CMDBYTE_WRITE; - tuh_max3421_spi_cs_api(rhport, true); + max3421_spi_lock(rhport, in_isr); tuh_max3421_spi_xfer_api(rhport, ®, 1, &hirq, 1); _hcd_data.hirq = hirq; tuh_max3421_spi_xfer_api(rhport, buffer, len, NULL, 0); - tuh_max3421_spi_cs_api(rhport, false); + max3421_spi_unlock(rhport, in_isr); } -static void fifo_read(uint8_t * buffer, uint16_t len) { - uint8_t const rhport = 0; +static void fifo_read(uint8_t rhport, uint8_t * buffer, uint16_t len, bool in_isr) { uint8_t hirq; uint8_t const reg = RCVVFIFO_ADDR; - tuh_max3421_spi_cs_api(rhport, true); + max3421_spi_lock(rhport, in_isr); tuh_max3421_spi_xfer_api(rhport, ®, 1, &hirq, 0); _hcd_data.hirq = hirq; tuh_max3421_spi_xfer_api(rhport, NULL, 0, buffer, len); - tuh_max3421_spi_cs_api(rhport, false); + max3421_spi_unlock(rhport, in_isr); } -static void reg_write(uint8_t reg, uint8_t data) { - uint8_t const rhport = 0; +static void reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr) { uint8_t tx_buf[2] = {reg | CMDBYTE_WRITE, data}; uint8_t rx_buf[2] = {0, 0}; - tuh_max3421_spi_cs_api(rhport, true); + max3421_spi_lock(rhport, in_isr); + tuh_max3421_spi_xfer_api(rhport, tx_buf, 2, rx_buf, 2); - tuh_max3421_spi_cs_api(rhport, false); + + max3421_spi_unlock(rhport, in_isr); // HIRQ register since we are in full-duplex mode _hcd_data.hirq = rx_buf[0]; } -static uint8_t reg_read(uint8_t reg) { - uint8_t const rhport = 0; +static uint8_t reg_read(uint8_t rhport, uint8_t reg, bool in_isr) { uint8_t tx_buf[2] = {reg, 0}; uint8_t rx_buf[2] = {0, 0}; - tuh_max3421_spi_cs_api(rhport, true); + max3421_spi_lock(rhport, in_isr); + bool ret = tuh_max3421_spi_xfer_api(rhport, tx_buf, 2, rx_buf, 2); - tuh_max3421_spi_cs_api(rhport, false); + + max3421_spi_unlock(rhport, in_isr); _hcd_data.hirq = rx_buf[0]; return ret ? rx_buf[1] : 0; } -static inline void hien_write(uint8_t data) { +static inline void hien_write(uint8_t rhport, uint8_t data, bool in_isr) { _hcd_data.hien = data; - reg_write(HIEN_ADDR, data); + reg_write(rhport, HIEN_ADDR, data, in_isr); } -static inline void mode_write(uint8_t data) { +static inline void mode_write(uint8_t rhport, uint8_t data, bool in_isr) { _hcd_data.mode = data; - reg_write(MODE_ADDR, data); + reg_write(rhport, MODE_ADDR, data, in_isr); } -static inline void peraddr_write(uint8_t data) { +static inline void peraddr_write(uint8_t rhport, uint8_t data, bool in_isr) { if ( _hcd_data.peraddr == data ) return; // no need to change address _hcd_data.peraddr = data; - reg_write(PERADDR_ADDR, data); + reg_write(rhport, PERADDR_ADDR, data, in_isr); } -static inline void hxfr_write(uint8_t data) { +static inline void hxfr_write(uint8_t rhport, uint8_t data, bool in_isr) { _hcd_data.hxfr = data; - reg_write(HXFR_ADDR, data); + reg_write(rhport, HXFR_ADDR, data, in_isr); } -static inline void sndbc_write(uint8_t data) { +static inline void sndbc_write(uint8_t rhport, uint8_t data, bool in_isr) { _hcd_data.sndbc = data; - reg_write(SNDBC_ADDR, data); + reg_write(rhport, SNDBC_ADDR, data, in_isr); } @@ -307,9 +328,7 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { } tusb_speed_t handle_connect_irq(uint8_t rhport) { - (void) rhport; - - uint8_t const hrsl = reg_read(HRSL_ADDR); + uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, true); uint8_t const jk = hrsl & (HRSL_JSTATUS | HRSL_KSTATUS); tusb_speed_t speed; @@ -328,7 +347,7 @@ tusb_speed_t handle_connect_irq(uint8_t rhport) { default: { // Low speed if (LS = 1 and J-state) or (LS = 0 and K-State) - uint8_t const mode = reg_read(MODE_ADDR); + uint8_t const mode = reg_read(rhport, MODE_ADDR, true); uint8_t const ls_bit = mode & MODE_LOWSPEED; if ( (ls_bit && (jk == HRSL_JSTATUS)) || (!ls_bit && (jk == HRSL_KSTATUS)) ) { @@ -344,7 +363,7 @@ tusb_speed_t handle_connect_irq(uint8_t rhport) { } } - mode_write(new_mode); + mode_write(rhport, new_mode, true); TU_LOG2_INT(speed); return speed; } @@ -358,32 +377,32 @@ bool hcd_init(uint8_t rhport) { tu_memclr(&_hcd_data, sizeof(_hcd_data)); + hcd_int_disable(rhport); + // full duplex, interrupt negative edge - reg_write(PINCTL_ADDR, PINCTL_FDUPSPI); + reg_write(rhport, PINCTL_ADDR, PINCTL_FDUPSPI, false); // reset - reg_write(USBCTL_ADDR, USBCTL_CHIPRES); - reg_write(USBCTL_ADDR, 0); - while( !(reg_read(USBIRQ_ADDR) & USBIRQ_OSCOK_IRQ) ) { + reg_write(rhport, USBCTL_ADDR, USBCTL_CHIPRES, false); + reg_write(rhport, USBCTL_ADDR, 0, false); + while( !(reg_read(rhport, USBIRQ_ADDR, false) & USBIRQ_OSCOK_IRQ) ) { // wait for oscillator to stabilize } // Mode: Host and DP/DM pull down - mode_write(MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST); + mode_write(rhport, MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST, false); // frame reset & bus reset, this will trigger CONDET IRQ if device is already connected - reg_write(HCTL_ADDR, HCTL_BUSRST | HCTL_FRMRST); + reg_write(rhport, HCTL_ADDR, HCTL_BUSRST | HCTL_FRMRST, false); // clear all previously pending IRQ - reg_write(HIRQ_ADDR, 0xff); - - _hcd_data.inited = true; + reg_write(rhport, HIRQ_ADDR, 0xff, false); // Enable IRQ - hien_write(DEFAULT_HIEN); + hien_write(rhport, DEFAULT_HIEN, false); // Enable Interrupt pin - reg_write(CPUCTL_ADDR, CPUCTL_IE); + reg_write(rhport, CPUCTL_ADDR, CPUCTL_IE, false); return true; } @@ -417,22 +436,20 @@ bool hcd_port_connect_status(uint8_t rhport) { // Reset USB bus on the port. Return immediately, bus reset sequence may not be complete. // Some port would require hcd_port_reset_end() to be invoked after 10ms to complete the reset sequence. void hcd_port_reset(uint8_t rhport) { - (void) rhport; // Bus reset will also trigger CONDET IRQ, disable it uint8_t const hien = DEFAULT_HIEN & ~HIRQ_CONDET_IRQ; - hien_write(hien); + hien_write(rhport, hien, false); - reg_write(HCTL_ADDR, HCTL_BUSRST); + reg_write(rhport, HCTL_ADDR, HCTL_BUSRST, false); } // Complete bus reset sequence, may be required by some controllers void hcd_port_reset_end(uint8_t rhport) { - (void) rhport; - reg_write(HCTL_ADDR, 0); + reg_write(rhport, HCTL_ADDR, 0, false); // Bus reset will also trigger CONDET IRQ, clear and re-enable it after reset - reg_write(HIRQ_ADDR, HIRQ_CONDET_IRQ); - hien_write(DEFAULT_HIEN); + reg_write(rhport, HIRQ_ADDR, HIRQ_CONDET_IRQ, false); + hien_write(rhport, DEFAULT_HIEN, false); } // Get port link speed @@ -487,7 +504,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf ep->xfer_complete = 0; ep->xfer_queued = 1; - peraddr_write(daddr); + peraddr_write(rhport, daddr, false); uint8_t hctl = 0; uint8_t hxfr = ep_num; @@ -500,7 +517,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf // ZLP for ACK stage, use HS hxfr |= HXFR_HS; hxfr |= (ep_dir ? 0 : HXFR_OUT_NIN); - hxfr_write(hxfr); + hxfr_write(rhport, hxfr, false); return true; } } @@ -510,8 +527,8 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ); uint8_t const xact_len = (uint8_t) tu_min16(buflen, ep->packet_size); - fifo_write(SNDFIFO_ADDR, buffer, xact_len); - sndbc_write(xact_len); + fifo_write(rhport, SNDFIFO_ADDR, buffer, xact_len, false); + sndbc_write(rhport, xact_len, false); hctl = (ep->data_toggle ? HCTL_SNDTOG1 : HCTL_SNDTOG0); hxfr |= HXFR_OUT_NIN; @@ -520,8 +537,8 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf hctl = (ep->data_toggle ? HCTL_RCVTOG1 : HCTL_RCVTOG0); } - reg_write(HCTL_ADDR, hctl); - hxfr_write(hxfr); + reg_write(rhport, HCTL_ADDR, hctl, false); + hxfr_write(rhport, hxfr, false); return true; } @@ -544,9 +561,9 @@ bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8] ep->total_len = 8; ep->xferred_len = 0; - peraddr_write(daddr); - fifo_write(SUDFIFO_ADDR, setup_packet, 8); - hxfr_write(HXFR_SETUP); + peraddr_write(rhport, daddr, false); + fifo_write(rhport, SUDFIFO_ADDR, setup_packet, 8, false); + hxfr_write(rhport, HXFR_SETUP, false); return true; } @@ -561,9 +578,7 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { } static void handle_xfer_done(uint8_t rhport) { - (void) rhport; - - uint8_t const hrsl = reg_read(HRSL_ADDR); + uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, true); uint8_t const hresult = hrsl & HRSL_RESULT_MASK; uint8_t ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK; @@ -587,7 +602,7 @@ static void handle_xfer_done(uint8_t rhport) { // NAK on control, retry immediately //if (ep_num == 0) { - hxfr_write(_hcd_data.hxfr); + hxfr_write(rhport, _hcd_data.hxfr, true); } return; @@ -615,11 +630,8 @@ static void handle_xfer_done(uint8_t rhport) { ep->buf += xact_len; if ( xact_len < ep->packet_size || ep->xferred_len >= ep->total_len ) { - if ( ep_num ) { - // save data toggle for non-control - ep->data_toggle = (hrsl & HRSL_SNDTOGRD) ? 1 : 0; - } - + // save data toggle + ep->data_toggle = (hrsl & HRSL_SNDTOGRD) ? 1 : 0; hcd_event_xfer_complete(_hcd_data.peraddr, ep_num, ep->xferred_len, xfer_result, true); }else { // more to transfer @@ -634,15 +646,12 @@ static void handle_xfer_done(uint8_t rhport) { // short packet or all bytes transferred if ( ep->xfer_complete ) { - if ( ep_num ) { - // save data toggle for non-control - ep->data_toggle = (hrsl & HRSL_RCVTOGRD) ? 1 : 0; - } - + // save data toggle + ep->data_toggle = (hrsl & HRSL_RCVTOGRD) ? 1 : 0; hcd_event_xfer_complete(_hcd_data.peraddr, TUSB_DIR_IN_MASK | ep_num, ep->xferred_len, xfer_result, true); }else { // more to transfer - hxfr_write(_hcd_data.hxfr); + hxfr_write(rhport, _hcd_data.hxfr, true); } } } @@ -669,10 +678,7 @@ void print_hirq(uint8_t hirq) { // Interrupt Handler void hcd_int_handler(uint8_t rhport) { - // not initialized, do nothing - if ( !_hcd_data.inited ) return; - - uint8_t hirq = reg_read(HIRQ_ADDR) & _hcd_data.hien; + uint8_t hirq = reg_read(rhport, HIRQ_ADDR, true) & _hcd_data.hien; if (!hirq) return; // print_hirq(hirq); @@ -701,17 +707,17 @@ void hcd_int_handler(uint8_t rhport) { // RCVDAV_IRQ can trigger 2 times (dual buffered) while ( hirq & HIRQ_RCVDAV_IRQ ) { - uint8_t rcvbc = reg_read(RCVBC_ADDR); + uint8_t rcvbc = reg_read(rhport, RCVBC_ADDR, true); xact_len = (uint8_t) tu_min16(rcvbc, ep->total_len - ep->xferred_len); if ( xact_len ) { - fifo_read(ep->buf, xact_len); + fifo_read(rhport, ep->buf, xact_len, true); ep->buf += xact_len; ep->xferred_len += xact_len; } // ack RCVDVAV IRQ - reg_write(HIRQ_ADDR, HIRQ_RCVDAV_IRQ); - hirq = reg_read(HIRQ_ADDR); + reg_write(rhport, HIRQ_ADDR, HIRQ_RCVDAV_IRQ, true); + hirq = reg_read(rhport, HIRQ_ADDR, true); } if ( xact_len < ep->packet_size || ep->xferred_len >= ep->total_len ) { @@ -720,17 +726,17 @@ void hcd_int_handler(uint8_t rhport) { } if ( hirq & HIRQ_HXFRDN_IRQ ) { - reg_write(HIRQ_ADDR, HIRQ_HXFRDN_IRQ); + reg_write(rhport, HIRQ_ADDR, HIRQ_HXFRDN_IRQ, true); handle_xfer_done(rhport); } - hirq = reg_read(HIRQ_ADDR); + hirq = reg_read(rhport, HIRQ_ADDR, true); } // clear all interrupt except SNDBAV_IRQ (never clear by us). Note RCVDAV_IRQ, HXFRDN_IRQ already clear while processing hirq &= ~HIRQ_SNDBAV_IRQ; if ( hirq ) { - reg_write(HIRQ_ADDR, hirq); + reg_write(rhport, HIRQ_ADDR, hirq, true); } } From 09ceaa6cf37d29e605495716fc2497ed5228a37f Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 25 Aug 2023 13:18:47 +0700 Subject: [PATCH 12/71] add osal mutex for spi --- src/portable/analog/max3421/hcd_max3421.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 0144deca6..09845ffe4 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -194,7 +194,10 @@ typedef struct { hcd_ep_t ep[8][2]; - OSAL_MUTEX_DEF(spi_mutex); + OSAL_MUTEX_DEF(spi_mutexdef); +#if OSAL_MUTEX_REQUIRED + osal_mutex_t spi_mutex; +#endif } max2341_data_t; static max2341_data_t _hcd_data; @@ -215,6 +218,7 @@ static void max3421_spi_lock(uint8_t rhport, bool in_isr) { // disable interrupt and mutex lock (for pre-emptive RTOS) if not in_isr if (!in_isr) { tuh_max3421e_int_api(rhport, false); + (void) osal_mutex_lock(_hcd_data.spi_mutex, OSAL_TIMEOUT_WAIT_FOREVER); } // assert CS @@ -228,6 +232,7 @@ static void max3421_spi_unlock(uint8_t rhport, bool in_isr) { // mutex unlock and re-enable interrupt if (!in_isr) { tuh_max3421e_int_api(rhport, true); + (void) osal_mutex_unlock(_hcd_data.spi_mutex); } } @@ -372,12 +377,16 @@ tusb_speed_t handle_connect_irq(uint8_t rhport) { bool hcd_init(uint8_t rhport) { (void) rhport; + hcd_int_disable(rhport); + TU_LOG2_INT(sizeof(hcd_ep_t)); TU_LOG2_INT(sizeof(max2341_data_t)); tu_memclr(&_hcd_data, sizeof(_hcd_data)); - hcd_int_disable(rhport); +#if OSAL_MUTEX_REQUIRED + _hcd_data.spi_mutex = osal_mutex_create(&_hcd_data.spi_mutexdef); +#endif // full duplex, interrupt negative edge reg_write(rhport, PINCTL_ADDR, PINCTL_FDUPSPI, false); From ecf2f910424b53fecc3ca82ae410f054518cc752 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 25 Aug 2023 16:36:28 +0700 Subject: [PATCH 13/71] use endpoint pool for more flexible multiple devices support --- src/portable/analog/max3421/hcd_max3421.c | 180 +++++++++++++++------- 1 file changed, 122 insertions(+), 58 deletions(-) diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 09845ffe4..b0325f240 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -165,22 +165,26 @@ enum { //--------------------------------------------------------------------+ typedef struct { - uint16_t packet_size; - struct TU_ATTR_PACKED { + uint8_t ep_dir : 1; uint8_t is_iso : 1; uint8_t data_toggle : 1; - uint8_t xfer_queued : 1; + uint8_t xfer_pending : 1; uint8_t xfer_complete : 1; }; + struct TU_ATTR_PACKED { + uint8_t daddr : 4; + uint8_t ep_num : 4; + }; + uint16_t packet_size; uint16_t total_len; uint16_t xferred_len; uint8_t* buf; -} hcd_ep_t; +} max3421_ep_t; typedef struct { - atomic_bool busy; // busy transferring + atomic_flag busy; // busy transferring // cached register uint8_t sndbc; @@ -192,15 +196,16 @@ typedef struct { volatile uint16_t frame_count; - hcd_ep_t ep[8][2]; + max3421_ep_t ep0_addr0; // control endpoint for addr0 + max3421_ep_t ep[CFG_TUH_MAX3421_ENDPOINT_TOTAL]; OSAL_MUTEX_DEF(spi_mutexdef); #if OSAL_MUTEX_REQUIRED osal_mutex_t spi_mutex; #endif -} max2341_data_t; +} max3421_data_t; -static max2341_data_t _hcd_data; +static max3421_data_t _hcd_data; //--------------------------------------------------------------------+ // API: SPI transfer with MAX3421E, must be implemented by application @@ -211,7 +216,7 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_ void tuh_max3421e_int_api(uint8_t rhport, bool enabled); //--------------------------------------------------------------------+ -// +// SPI Helper //--------------------------------------------------------------------+ static void max3421_spi_lock(uint8_t rhport, bool in_isr) { @@ -318,6 +323,44 @@ static inline void sndbc_write(uint8_t rhport, uint8_t data, bool in_isr) { reg_write(rhport, SNDBC_ADDR, data, in_isr); } +//--------------------------------------------------------------------+ +// Endpoint helper +//--------------------------------------------------------------------+ + +static max3421_ep_t* find_ep_not_addr0(uint8_t daddr, uint8_t ep_num, uint8_t ep_dir) { + for(size_t i=0; idaddr && ep_num == ep->ep_num && (ep_dir == ep->ep_dir || ep_num == 0) ) { + return ep; + } + } + + return NULL; +} + +// daddr = 0 and ep_num = 0 means find a free (allocate) endpoint +TU_ATTR_ALWAYS_INLINE static inline max3421_ep_t * allocate_ep(void) { + return find_ep_not_addr0(0, 0, 0); +} + +// free all endpoints belong to device address +static void free_ep(uint8_t daddr) { + for (size_t i=0; idaddr == daddr) { + tu_memclr(ep, sizeof(max3421_ep_t)); + } + } +} + +TU_ATTR_ALWAYS_INLINE static inline max3421_ep_t * find_opened_ep(uint8_t daddr, uint8_t ep_num, uint8_t ep_dir) { + if (daddr == 0 && ep_num == 0) { + return &_hcd_data.ep0_addr0; + }else{ + return find_ep_not_addr0(daddr, ep_num, ep_dir); + } +} //--------------------------------------------------------------------+ // Controller API @@ -379,8 +422,8 @@ bool hcd_init(uint8_t rhport) { hcd_int_disable(rhport); - TU_LOG2_INT(sizeof(hcd_ep_t)); - TU_LOG2_INT(sizeof(max2341_data_t)); + TU_LOG2_INT(sizeof(max3421_ep_t)); + TU_LOG2_INT(sizeof(max3421_data_t)); tu_memclr(&_hcd_data, sizeof(_hcd_data)); @@ -478,22 +521,29 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { //--------------------------------------------------------------------+ // Open an endpoint -bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { +bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * ep_desc) { (void) rhport; - (void) dev_addr; + (void) daddr; uint8_t ep_num = tu_edpt_number(ep_desc->bEndpointAddress); uint8_t ep_dir = tu_edpt_dir(ep_desc->bEndpointAddress); - hcd_ep_t * ep = &_hcd_data.ep[ep_num][ep_dir]; - - ep->packet_size = tu_edpt_packet_size(ep_desc); - - if (ep_desc->bEndpointAddress == 0) { - _hcd_data.ep[0][1].packet_size = ep->packet_size; + max3421_ep_t * ep; + if (daddr == 0 && ep_num == 0) { + ep = &_hcd_data.ep0_addr0; + }else { + ep = allocate_ep(); + TU_ASSERT(ep); + ep->daddr = daddr; + ep->ep_num = ep_num; + ep->ep_dir = ep_dir; } - ep->is_iso = (TUSB_XFER_ISOCHRONOUS == ep_desc->bmAttributes.xfer) ? 1 : 0; + if ( TUSB_XFER_ISOCHRONOUS == ep_desc->bmAttributes.xfer ) { + ep->is_iso = 1; + } + + ep->packet_size = tu_edpt_packet_size(ep_desc); return true; } @@ -505,50 +555,55 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf uint8_t const ep_num = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); - hcd_ep_t* ep = &_hcd_data.ep[ep_num][ep_dir]; + max3421_ep_t* ep = find_opened_ep(daddr, ep_num, ep_dir); + TU_ASSERT(ep); ep->buf = buffer; ep->total_len = buflen; ep->xferred_len = 0; ep->xfer_complete = 0; - ep->xfer_queued = 1; + ep->xfer_pending = 1; - peraddr_write(rhport, daddr, false); + // carry out transfer if not busy +// if ( atomic_flag_test_and_set(&_hcd_data.busy) ) + { + peraddr_write(rhport, daddr, false); - uint8_t hctl = 0; - uint8_t hxfr = ep_num; + uint8_t hctl = 0; + uint8_t hxfr = ep_num; - if ( ep->is_iso ) { - hxfr |= HXFR_ISO; - } else if ( ep_num == 0 ) { - ep->data_toggle = 1; - if ( buffer == NULL || buflen == 0 ) { - // ZLP for ACK stage, use HS - hxfr |= HXFR_HS; - hxfr |= (ep_dir ? 0 : HXFR_OUT_NIN); - hxfr_write(rhport, hxfr, false); - return true; + if ( ep->is_iso ) { + hxfr |= HXFR_ISO; + } else if ( ep_num == 0 ) { + ep->data_toggle = 1; + if ( buffer == NULL || buflen == 0 ) { + // ZLP for ACK stage, use HS + hxfr |= HXFR_HS; + hxfr |= (ep_dir ? 0 : HXFR_OUT_NIN); + hxfr_write(rhport, hxfr, false); + return true; + } } + + if ( 0 == ep_dir ) { + // Page 12: Programming BULK-OUT Transfers + TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ); + + uint8_t const xact_len = (uint8_t) tu_min16(buflen, ep->packet_size); + fifo_write(rhport, SNDFIFO_ADDR, buffer, xact_len, false); + sndbc_write(rhport, xact_len, false); + + hctl = (ep->data_toggle ? HCTL_SNDTOG1 : HCTL_SNDTOG0); + hxfr |= HXFR_OUT_NIN; + } else { + // Page 13: Programming BULK-IN Transfers + hctl = (ep->data_toggle ? HCTL_RCVTOG1 : HCTL_RCVTOG0); + } + + reg_write(rhport, HCTL_ADDR, hctl, false); + hxfr_write(rhport, hxfr, false); } - if ( 0 == ep_dir ) { - // Page 12: Programming BULK-OUT Transfers - TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ); - - uint8_t const xact_len = (uint8_t) tu_min16(buflen, ep->packet_size); - fifo_write(rhport, SNDFIFO_ADDR, buffer, xact_len, false); - sndbc_write(rhport, xact_len, false); - - hctl = (ep->data_toggle ? HCTL_SNDTOG1 : HCTL_SNDTOG0); - hxfr |= HXFR_OUT_NIN; - } else { - // Page 13: Programming BULK-IN Transfers - hctl = (ep->data_toggle ? HCTL_RCVTOG1 : HCTL_RCVTOG0); - } - - reg_write(rhport, HCTL_ADDR, hctl, false); - hxfr_write(rhport, hxfr, false); - return true; } @@ -566,7 +621,7 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8]) { (void) rhport; - hcd_ep_t* ep = &_hcd_data.ep[0][0]; + max3421_ep_t* ep = find_opened_ep(daddr, 0, 0); ep->total_len = 8; ep->xferred_len = 0; @@ -624,7 +679,7 @@ static void handle_xfer_done(uint8_t rhport) { if ( (hxfr_type & HXFR_SETUP) || (hxfr_type & HXFR_OUT_NIN) ) { // SETUP or OUT transfer - hcd_ep_t *ep = &_hcd_data.ep[ep_num][0]; + max3421_ep_t *ep = find_opened_ep(_hcd_data.peraddr, ep_num, 0); uint8_t xact_len; if ( hxfr_type & HXFR_SETUP) { @@ -644,10 +699,15 @@ static void handle_xfer_done(uint8_t rhport) { hcd_event_xfer_complete(_hcd_data.peraddr, ep_num, ep->xferred_len, xfer_result, true); }else { // more to transfer + xact_len = (uint8_t) tu_min16(ep->total_len - ep->xferred_len, ep->packet_size); + fifo_write(rhport, SNDFIFO_ADDR, ep->buf, xact_len, true); + sndbc_write(rhport, xact_len, true); + + hxfr_write(rhport, _hcd_data.hxfr, true); } } else { // IN transfer: fifo data is already received in RCVDAV IRQ - hcd_ep_t *ep = &_hcd_data.ep[ep_num][1]; + max3421_ep_t *ep = find_opened_ep(_hcd_data.peraddr, ep_num, 1); if ( hxfr_type & HXFR_HS ) { ep->xfer_complete = 1; @@ -702,6 +762,10 @@ void hcd_int_handler(uint8_t rhport) { if (speed == TUSB_SPEED_INVALID) { hcd_event_device_remove(rhport, true); }else { + // FIXME multiple MAX3421 rootdevice address is not 1 + uint8_t const daddr = 1; + free_ep(daddr); + hcd_event_device_attach(rhport, true); } } @@ -710,8 +774,8 @@ void hcd_int_handler(uint8_t rhport) { // not call this handler again. So we need to loop until all IRQ are cleared while ( hirq & (HIRQ_RCVDAV_IRQ | HIRQ_HXFRDN_IRQ) ) { if ( hirq & HIRQ_RCVDAV_IRQ ) { - uint8_t ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK; - hcd_ep_t *ep = &_hcd_data.ep[ep_num][1]; + uint8_t const ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK; + max3421_ep_t *ep = find_opened_ep(_hcd_data.peraddr, ep_num, 1); uint8_t xact_len; // RCVDAV_IRQ can trigger 2 times (dual buffered) From ac00b9147298184ca0bd1eadac3a02e7e867085d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 25 Aug 2023 17:26:57 +0700 Subject: [PATCH 14/71] add xact_out(), xact_in() to manage transfer --- src/portable/analog/max3421/hcd_max3421.c | 149 +++++++++++++--------- 1 file changed, 92 insertions(+), 57 deletions(-) diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index b0325f240..00b36201c 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -331,7 +331,7 @@ static max3421_ep_t* find_ep_not_addr0(uint8_t daddr, uint8_t ep_num, uint8_t ep for(size_t i=0; idaddr && ep_num == ep->ep_num && (ep_dir == ep->ep_dir || ep_num == 0) ) { + if (daddr == ep->daddr && ep_num == ep->ep_num && (ep_dir == ep->ep_dir || ep_num == 0)) { return ep; } } @@ -362,6 +362,28 @@ TU_ATTR_ALWAYS_INLINE static inline max3421_ep_t * find_opened_ep(uint8_t daddr, } } +//static max3421_ep_t * find_next_pending_ep(max3421_ep_t * cur_ep) { +// size_t idx = cur_ep - _hcd_data.ep; +// +// // starting from next endpoint +// for (size_t i = idx + 1; i < CFG_TUH_MAX3421_ENDPOINT_TOTAL; i++) { +// max3421_ep_t* ep = &_hcd_data.ep[i]; +// if (ep->xfer_pending) { +// return ep; +// } +// } +// +// // wrap around including current endpoint +// for (size_t i = 0; i <= idx; i++) { +// max3421_ep_t* ep = &_hcd_data.ep[i]; +// if (ep->xfer_pending) { +// return ep; +// } +// } +// +// return NULL; +//} + //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ @@ -548,6 +570,37 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * e return true; } +void xact_out(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { + // Page 12: Programming BULK-OUT Transfers + // TODO double buffered + if (switch_ep) { + peraddr_write(rhport, ep->daddr, in_isr); + + uint8_t const hctl = (ep->data_toggle ? HCTL_SNDTOG1 : HCTL_SNDTOG0); + reg_write(rhport, HCTL_ADDR, hctl, in_isr); + } + + uint8_t const xact_len = (uint8_t) tu_min16(ep->total_len - ep->xferred_len, ep->packet_size); + fifo_write(rhport, SNDFIFO_ADDR, ep->buf, xact_len, in_isr); + sndbc_write(rhport, xact_len, in_isr); + + uint8_t const hxfr = ep->ep_num | HXFR_OUT_NIN | (ep->is_iso ? HXFR_ISO : 0); + hxfr_write(rhport, hxfr, in_isr); +} + +void xact_in(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { + // Page 13: Programming BULK-IN Transfers + if (switch_ep) { + peraddr_write(rhport, ep->daddr, in_isr); + + uint8_t const hctl = (ep->data_toggle ? HCTL_RCVTOG1 : HCTL_RCVTOG0); + reg_write(rhport, HCTL_ADDR, hctl, in_isr); + } + + uint8_t const hxfr = ep->ep_num | (ep->is_iso ? HXFR_ISO : 0); + hxfr_write(rhport, hxfr, in_isr); +} + // Submit a transfer, when complete hcd_event_xfer_complete() must be invoked bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { (void) rhport; @@ -567,17 +620,14 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf // carry out transfer if not busy // if ( atomic_flag_test_and_set(&_hcd_data.busy) ) { - peraddr_write(rhport, daddr, false); - - uint8_t hctl = 0; uint8_t hxfr = ep_num; - if ( ep->is_iso ) { - hxfr |= HXFR_ISO; - } else if ( ep_num == 0 ) { + if ( ep_num == 0 ) { ep->data_toggle = 1; if ( buffer == NULL || buflen == 0 ) { // ZLP for ACK stage, use HS + peraddr_write(rhport, daddr, false); + hxfr |= HXFR_HS; hxfr |= (ep_dir ? 0 : HXFR_OUT_NIN); hxfr_write(rhport, hxfr, false); @@ -586,22 +636,11 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf } if ( 0 == ep_dir ) { - // Page 12: Programming BULK-OUT Transfers TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ); - - uint8_t const xact_len = (uint8_t) tu_min16(buflen, ep->packet_size); - fifo_write(rhport, SNDFIFO_ADDR, buffer, xact_len, false); - sndbc_write(rhport, xact_len, false); - - hctl = (ep->data_toggle ? HCTL_SNDTOG1 : HCTL_SNDTOG0); - hxfr |= HXFR_OUT_NIN; + xact_out(rhport, ep, true, false); } else { - // Page 13: Programming BULK-IN Transfers - hctl = (ep->data_toggle ? HCTL_RCVTOG1 : HCTL_RCVTOG0); + xact_in(rhport, ep, true, false); } - - reg_write(rhport, HCTL_ADDR, hctl, false); - hxfr_write(rhport, hxfr, false); } return true; @@ -644,7 +683,12 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { static void handle_xfer_done(uint8_t rhport) { uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, true); uint8_t const hresult = hrsl & HRSL_RESULT_MASK; - uint8_t ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK; + + uint8_t const ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK; + uint8_t const hxfr_type = _hcd_data.hxfr & 0xf0; + uint8_t const ep_dir = ((hxfr_type & HXFR_SETUP) || (hxfr_type & HXFR_OUT_NIN)) ? 0 : 1; + + max3421_ep_t *ep = find_opened_ep(_hcd_data.peraddr, ep_num, ep_dir); xfer_result_t xfer_result; @@ -663,10 +707,11 @@ static void handle_xfer_done(uint8_t rhport) { return; case HRSL_NAK: - // NAK on control, retry immediately - //if (ep_num == 0) - { + if (ep_num == 0) { + // NAK on control, retry immediately hxfr_write(rhport, _hcd_data.hxfr, true); + }else { + // NAK on non-control, find next pending to switch } return; @@ -675,40 +720,8 @@ static void handle_xfer_done(uint8_t rhport) { break; } - uint8_t const hxfr_type = _hcd_data.hxfr & 0xf0; - - if ( (hxfr_type & HXFR_SETUP) || (hxfr_type & HXFR_OUT_NIN) ) { - // SETUP or OUT transfer - max3421_ep_t *ep = find_opened_ep(_hcd_data.peraddr, ep_num, 0); - uint8_t xact_len; - - if ( hxfr_type & HXFR_SETUP) { - xact_len = 8; - } else if ( hxfr_type & HXFR_HS ) { - xact_len = 0; - } else { - xact_len = _hcd_data.sndbc; - } - - ep->xferred_len += xact_len; - ep->buf += xact_len; - - if ( xact_len < ep->packet_size || ep->xferred_len >= ep->total_len ) { - // save data toggle - ep->data_toggle = (hrsl & HRSL_SNDTOGRD) ? 1 : 0; - hcd_event_xfer_complete(_hcd_data.peraddr, ep_num, ep->xferred_len, xfer_result, true); - }else { - // more to transfer - xact_len = (uint8_t) tu_min16(ep->total_len - ep->xferred_len, ep->packet_size); - fifo_write(rhport, SNDFIFO_ADDR, ep->buf, xact_len, true); - sndbc_write(rhport, xact_len, true); - - hxfr_write(rhport, _hcd_data.hxfr, true); - } - } else { + if (ep_dir) { // IN transfer: fifo data is already received in RCVDAV IRQ - max3421_ep_t *ep = find_opened_ep(_hcd_data.peraddr, ep_num, 1); - if ( hxfr_type & HXFR_HS ) { ep->xfer_complete = 1; } @@ -722,6 +735,28 @@ static void handle_xfer_done(uint8_t rhport) { // more to transfer hxfr_write(rhport, _hcd_data.hxfr, true); } + } else { + // SETUP or OUT transfer + uint8_t xact_len; + + if (hxfr_type & HXFR_SETUP) { + xact_len = 8; + } else if (hxfr_type & HXFR_HS) { + xact_len = 0; + } else { + xact_len = _hcd_data.sndbc; + } + + ep->xferred_len += xact_len; + ep->buf += xact_len; + + if (xact_len < ep->packet_size || ep->xferred_len >= ep->total_len) { + // save data toggle + ep->data_toggle = (hrsl & HRSL_SNDTOGRD) ? 1 : 0; + hcd_event_xfer_complete(_hcd_data.peraddr, ep_num, ep->xferred_len, xfer_result, true); + } else { + xact_out(rhport, ep, false, true); + } } } From cd7464a8847db5efa14f568bdf8746d898fc7eb4 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 25 Aug 2023 17:37:09 +0700 Subject: [PATCH 15/71] try next endpoint when received NAK --- src/portable/analog/max3421/hcd_max3421.c | 58 +++++++++++++++-------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 00b36201c..e546f99ce 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -362,27 +362,27 @@ TU_ATTR_ALWAYS_INLINE static inline max3421_ep_t * find_opened_ep(uint8_t daddr, } } -//static max3421_ep_t * find_next_pending_ep(max3421_ep_t * cur_ep) { -// size_t idx = cur_ep - _hcd_data.ep; -// -// // starting from next endpoint -// for (size_t i = idx + 1; i < CFG_TUH_MAX3421_ENDPOINT_TOTAL; i++) { -// max3421_ep_t* ep = &_hcd_data.ep[i]; -// if (ep->xfer_pending) { -// return ep; -// } -// } -// -// // wrap around including current endpoint -// for (size_t i = 0; i <= idx; i++) { -// max3421_ep_t* ep = &_hcd_data.ep[i]; -// if (ep->xfer_pending) { -// return ep; -// } -// } -// -// return NULL; -//} +static max3421_ep_t * find_next_pending_ep(max3421_ep_t * cur_ep) { + size_t idx = cur_ep - _hcd_data.ep; + + // starting from next endpoint + for (size_t i = idx + 1; i < CFG_TUH_MAX3421_ENDPOINT_TOTAL; i++) { + max3421_ep_t* ep = &_hcd_data.ep[i]; + if (ep->xfer_pending) { + return ep; + } + } + + // wrap around including current endpoint + for (size_t i = 0; i <= idx; i++) { + max3421_ep_t* ep = &_hcd_data.ep[i]; + if (ep->xfer_pending) { + return ep; + } + } + + return NULL; +} //--------------------------------------------------------------------+ // Controller API @@ -443,6 +443,7 @@ bool hcd_init(uint8_t rhport) { (void) rhport; hcd_int_disable(rhport); + tuh_max3421_spi_cs_api(rhport, false); TU_LOG2_INT(sizeof(max3421_ep_t)); TU_LOG2_INT(sizeof(max3421_data_t)); @@ -689,6 +690,7 @@ static void handle_xfer_done(uint8_t rhport) { uint8_t const ep_dir = ((hxfr_type & HXFR_SETUP) || (hxfr_type & HXFR_OUT_NIN)) ? 0 : 1; max3421_ep_t *ep = find_opened_ep(_hcd_data.peraddr, ep_num, ep_dir); + TU_ASSERT(ep, ); xfer_result_t xfer_result; @@ -712,6 +714,20 @@ static void handle_xfer_done(uint8_t rhport) { hxfr_write(rhport, _hcd_data.hxfr, true); }else { // NAK on non-control, find next pending to switch + max3421_ep_t *next_ep = find_next_pending_ep(ep); + TU_ASSERT(next_ep, ); + + if (ep == next_ep) { + // only one pending, retry immediately + hxfr_write(rhport, _hcd_data.hxfr, true); + }else { + // switch to next pending TODO could have issue with double buffered if not clear previously out data + if ( ep_dir ) { + xact_in(rhport, next_ep, true, true); + } else { + xact_out(rhport, next_ep, true, true); + } + } } return; From 502b1bdda62f0f207d9a51daf134574e455f3aa2 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 27 Aug 2023 23:45:34 +0700 Subject: [PATCH 16/71] more update to transaction --- examples/host/cdc_msc_hid/src/tusb_config.h | 9 ++-- .../host/msc_file_explorer/src/tusb_config.h | 10 ++-- src/common/tusb_mcu.h | 12 +++++ src/host/hcd.h | 4 +- src/host/usbh.c | 1 + src/portable/analog/max3421/hcd_max3421.c | 51 ++++++++++++------- 6 files changed, 62 insertions(+), 25 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index abb75f068..7d621d466 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -35,9 +35,12 @@ //--------------------------------------------------------------------+ #if CFG_TUSB_MCU == OPT_MCU_RP2040 -// change to 1 if using pico-pio-usb as host controller for raspberry rp2040 -#define CFG_TUH_RPI_PIO_USB 0 -#define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB + // change to 1 if using pico-pio-usb as host controller for raspberry rp2040 + #define CFG_TUH_RPI_PIO_USB 0 + #define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB +#elif CFG_TUSB_MCU == OPT_MCU_NRF5X + // Use external USB controller (via SPI) MAX3421E (aka usb host shield) + #define CFG_TUH_MAX3421 1 #endif // RHPort number used for host can be defined by board.mk, default to port 0 diff --git a/examples/host/msc_file_explorer/src/tusb_config.h b/examples/host/msc_file_explorer/src/tusb_config.h index 1e0d067bf..bb2fd4cf5 100644 --- a/examples/host/msc_file_explorer/src/tusb_config.h +++ b/examples/host/msc_file_explorer/src/tusb_config.h @@ -35,11 +35,15 @@ //--------------------------------------------------------------------+ #if CFG_TUSB_MCU == OPT_MCU_RP2040 -// change to 1 if using pico-pio-usb as host controller for raspberry rp2040 -#define CFG_TUH_RPI_PIO_USB 0 -#define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB + // change to 1 if using pico-pio-usb as host controller for raspberry rp2040 + #define CFG_TUH_RPI_PIO_USB 0 + #define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_US +#elif CFG_TUSB_MCU == OPT_MCU_NRF5X + // Use external USB controller (via SPI) MAX3421E (aka usb host shield) + #define CFG_TUH_MAX3421 1 #endif + // RHPort number used for host can be defined by board.mk, default to port 0 #ifndef BOARD_TUH_RHPORT #define BOARD_TUH_RHPORT 0 diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 35f94efbc..21939df7c 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -385,6 +385,18 @@ #define TUP_RHPORT_HIGHSPEED 1 #endif + +//--------------------------------------------------------------------+ +// External USB controller +//--------------------------------------------------------------------+ + +#if defined(CFG_TUH_MAX3421) & CFG_TUH_MAX3421 + #ifndef CFG_TUH_MAX3421_ENDPOINT_TOTAL + #define CFG_TUH_MAX3421_ENDPOINT_TOTAL (8 + 4*(CFG_TUH_DEVICE_MAX-1)) + #endif +#endif + + //--------------------------------------------------------------------+ // Default Values //--------------------------------------------------------------------+ diff --git a/src/host/hcd.h b/src/host/hcd.h index 1f01a1a2f..e25b20ea3 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -39,7 +39,7 @@ // Configuration //--------------------------------------------------------------------+ -// Max number of endpoints per device +// Max number of endpoints pair per device // TODO optimize memory usage #ifndef CFG_TUH_ENDPOINT_MAX #define CFG_TUH_ENDPOINT_MAX 16 @@ -167,7 +167,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr); //--------------------------------------------------------------------+ // Open an endpoint -bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); +bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * ep_desc); // Submit a transfer, when complete hcd_event_xfer_complete() must be invoked bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); diff --git a/src/host/usbh.c b/src/host/usbh.c index 7a09f5b6e..12a7f5839 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -919,6 +919,7 @@ TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) switch (event->event_id) { // case HCD_EVENT_DEVICE_REMOVE: +// // FIXME device remove from a hub need an HCD API for hcd to free up endpoint // // mark device as removing to prevent further xfer before the event is processed in usbh task // break; diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index e546f99ce..574cca788 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -582,6 +582,7 @@ void xact_out(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { } uint8_t const xact_len = (uint8_t) tu_min16(ep->total_len - ep->xferred_len, ep->packet_size); + TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ, ); fifo_write(rhport, SNDFIFO_ADDR, ep->buf, xact_len, in_isr); sndbc_write(rhport, xact_len, in_isr); @@ -602,6 +603,28 @@ void xact_in(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { hxfr_write(rhport, hxfr, in_isr); } +TU_ATTR_ALWAYS_INLINE static inline void xact_inout(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { + if (ep->ep_dir) { + xact_in(rhport, ep, switch_ep, in_isr); + }else { + xact_out(rhport, ep, switch_ep, in_isr); + } +} + +void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t result, uint8_t data_toggle) { + (void) rhport; + (void) result; + ep->xfer_pending = 0; + ep->data_toggle = data_toggle; + //uint8_t const ep_addr = tu_edpt_addr(ep->ep_num, ep->ep_dir); + //hcd_event_xfer_complete(rhport, ep_addr, ep->xferred_len, result, true); + +// max3421_ep_t *next_ep = find_next_pending_ep(ep); +// if (next_ep) { +// xact_inout(rhport, next_ep, true, true); +// } +} + // Submit a transfer, when complete hcd_event_xfer_complete() must be invoked bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { (void) rhport; @@ -612,6 +635,9 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf max3421_ep_t* ep = find_opened_ep(daddr, ep_num, ep_dir); TU_ASSERT(ep); + // control transfer can switch direction + ep->ep_dir = ep_dir; + ep->buf = buffer; ep->total_len = buflen; ep->xferred_len = 0; @@ -636,12 +662,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf } } - if ( 0 == ep_dir ) { - TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ); - xact_out(rhport, ep, true, false); - } else { - xact_in(rhport, ep, true, false); - } + xact_inout(rhport, ep, true, false); } return true; @@ -662,6 +683,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8] (void) rhport; max3421_ep_t* ep = find_opened_ep(daddr, 0, 0); + ep->ep_dir = 0; ep->total_len = 8; ep->xferred_len = 0; @@ -715,18 +737,13 @@ static void handle_xfer_done(uint8_t rhport) { }else { // NAK on non-control, find next pending to switch max3421_ep_t *next_ep = find_next_pending_ep(ep); - TU_ASSERT(next_ep, ); if (ep == next_ep) { // only one pending, retry immediately hxfr_write(rhport, _hcd_data.hxfr, true); - }else { + }else if (next_ep) { // switch to next pending TODO could have issue with double buffered if not clear previously out data - if ( ep_dir ) { - xact_in(rhport, next_ep, true, true); - } else { - xact_out(rhport, next_ep, true, true); - } + xact_inout(rhport, next_ep, true, true); } } return; @@ -744,8 +761,8 @@ static void handle_xfer_done(uint8_t rhport) { // short packet or all bytes transferred if ( ep->xfer_complete ) { - // save data toggle - ep->data_toggle = (hrsl & HRSL_RCVTOGRD) ? 1 : 0; + uint8_t const dt = (hrsl & HRSL_RCVTOGRD) ? 1 : 0; // save data toggle + xfer_complete_isr(rhport, ep, xfer_result, dt); hcd_event_xfer_complete(_hcd_data.peraddr, TUSB_DIR_IN_MASK | ep_num, ep->xferred_len, xfer_result, true); }else { // more to transfer @@ -767,8 +784,8 @@ static void handle_xfer_done(uint8_t rhport) { ep->buf += xact_len; if (xact_len < ep->packet_size || ep->xferred_len >= ep->total_len) { - // save data toggle - ep->data_toggle = (hrsl & HRSL_SNDTOGRD) ? 1 : 0; + uint8_t const dt = (hrsl & HRSL_SNDTOGRD) ? 1 : 0; // save data toggle + xfer_complete_isr(rhport, ep, xfer_result, dt); hcd_event_xfer_complete(_hcd_data.peraddr, ep_num, ep->xferred_len, xfer_result, true); } else { xact_out(rhport, ep, false, true); From 84df3b04db47d34b53ef002b056b6b324394de52 Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 27 Aug 2023 23:54:24 +0700 Subject: [PATCH 17/71] minor update --- .idea/cmake.xml | 5 +++-- .idea/runConfigurations/nrf52840.xml | 2 +- examples/host/cdc_msc_hid/src/tusb_config.h | 6 +++--- examples/host/msc_file_explorer/src/tusb_config.h | 6 +++--- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.idea/cmake.xml b/.idea/cmake.xml index 8ee7f09a0..86e7c6606 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -30,9 +30,10 @@ - - + + + diff --git a/.idea/runConfigurations/nrf52840.xml b/.idea/runConfigurations/nrf52840.xml index 084669c39..2f3f1876a 100644 --- a/.idea/runConfigurations/nrf52840.xml +++ b/.idea/runConfigurations/nrf52840.xml @@ -1,5 +1,5 @@ - + diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 7d621d466..8d3ef8891 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -38,9 +38,9 @@ // change to 1 if using pico-pio-usb as host controller for raspberry rp2040 #define CFG_TUH_RPI_PIO_USB 0 #define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB -#elif CFG_TUSB_MCU == OPT_MCU_NRF5X - // Use external USB controller (via SPI) MAX3421E (aka usb host shield) - #define CFG_TUH_MAX3421 1 +//#elif CFG_TUSB_MCU == OPT_MCU_NRF5X +// // Use external USB controller (via SPI) MAX3421E (aka usb host shield) +// #define CFG_TUH_MAX3421 1 #endif // RHPort number used for host can be defined by board.mk, default to port 0 diff --git a/examples/host/msc_file_explorer/src/tusb_config.h b/examples/host/msc_file_explorer/src/tusb_config.h index bb2fd4cf5..28e130c0e 100644 --- a/examples/host/msc_file_explorer/src/tusb_config.h +++ b/examples/host/msc_file_explorer/src/tusb_config.h @@ -38,9 +38,9 @@ // change to 1 if using pico-pio-usb as host controller for raspberry rp2040 #define CFG_TUH_RPI_PIO_USB 0 #define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_US -#elif CFG_TUSB_MCU == OPT_MCU_NRF5X - // Use external USB controller (via SPI) MAX3421E (aka usb host shield) - #define CFG_TUH_MAX3421 1 +//#elif CFG_TUSB_MCU == OPT_MCU_NRF5X +// // Use external USB controller (via SPI) MAX3421E (aka usb host shield) +// #define CFG_TUH_MAX3421 1 #endif From b31924e13edff0f29829056152348a9255e72169 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 28 Aug 2023 12:41:44 +0700 Subject: [PATCH 18/71] - add xfer_complete_isr() - merge addr0 ep to pool - add control status to xact in/out - use atomic flag busy to ensure only 1 transfer is active at any time - execute pending transfer after one is complete (or clear busy flag) - change rtt mode to block if full --- hw/bsp/family_support.cmake | 1 + src/portable/analog/max3421/hcd_max3421.c | 118 +++++++++++----------- 2 files changed, 62 insertions(+), 57 deletions(-) diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 7c89427c0..1cbcfb2a7 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -216,6 +216,7 @@ function(family_configure_common TARGET RTOS) if (NOT TARGET segger_rtt) add_library(segger_rtt STATIC ${TOP}/lib/SEGGER_RTT/RTT/SEGGER_RTT.c) target_include_directories(segger_rtt PUBLIC ${TOP}/lib/SEGGER_RTT/RTT) + target_compile_definitions(segger_rtt PUBLIC SEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) endif() target_link_libraries(${TARGET} PUBLIC segger_rtt) endif () diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 574cca788..262dbca0f 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -195,9 +195,7 @@ typedef struct { uint8_t hxfr; volatile uint16_t frame_count; - - max3421_ep_t ep0_addr0; // control endpoint for addr0 - max3421_ep_t ep[CFG_TUH_MAX3421_ENDPOINT_TOTAL]; + max3421_ep_t ep[CFG_TUH_MAX3421_ENDPOINT_TOTAL]; // [0] is reserved for addr0 OSAL_MUTEX_DEF(spi_mutexdef); #if OSAL_MUTEX_REQUIRED @@ -328,7 +326,7 @@ static inline void sndbc_write(uint8_t rhport, uint8_t data, bool in_isr) { //--------------------------------------------------------------------+ static max3421_ep_t* find_ep_not_addr0(uint8_t daddr, uint8_t ep_num, uint8_t ep_dir) { - for(size_t i=0; idaddr && ep_num == ep->ep_num && (ep_dir == ep->ep_dir || ep_num == 0)) { @@ -344,9 +342,17 @@ TU_ATTR_ALWAYS_INLINE static inline max3421_ep_t * allocate_ep(void) { return find_ep_not_addr0(0, 0, 0); } +TU_ATTR_ALWAYS_INLINE static inline max3421_ep_t * find_opened_ep(uint8_t daddr, uint8_t ep_num, uint8_t ep_dir) { + if (daddr == 0 && ep_num == 0) { + return &_hcd_data.ep[0]; + }else{ + return find_ep_not_addr0(daddr, ep_num, ep_dir); + } +} + // free all endpoints belong to device address static void free_ep(uint8_t daddr) { - for (size_t i=0; idaddr == daddr) { tu_memclr(ep, sizeof(max3421_ep_t)); @@ -354,16 +360,8 @@ static void free_ep(uint8_t daddr) { } } -TU_ATTR_ALWAYS_INLINE static inline max3421_ep_t * find_opened_ep(uint8_t daddr, uint8_t ep_num, uint8_t ep_dir) { - if (daddr == 0 && ep_num == 0) { - return &_hcd_data.ep0_addr0; - }else{ - return find_ep_not_addr0(daddr, ep_num, ep_dir); - } -} - static max3421_ep_t * find_next_pending_ep(max3421_ep_t * cur_ep) { - size_t idx = cur_ep - _hcd_data.ep; + size_t const idx = cur_ep - _hcd_data.ep; // starting from next endpoint for (size_t i = idx + 1; i < CFG_TUH_MAX3421_ENDPOINT_TOTAL; i++) { @@ -553,7 +551,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * e max3421_ep_t * ep; if (daddr == 0 && ep_num == 0) { - ep = &_hcd_data.ep0_addr0; + ep = &_hcd_data.ep[0]; }else { ep = allocate_ep(); TU_ASSERT(ep); @@ -581,12 +579,20 @@ void xact_out(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { reg_write(rhport, HCTL_ADDR, hctl, in_isr); } - uint8_t const xact_len = (uint8_t) tu_min16(ep->total_len - ep->xferred_len, ep->packet_size); - TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ, ); - fifo_write(rhport, SNDFIFO_ADDR, ep->buf, xact_len, in_isr); - sndbc_write(rhport, xact_len, in_isr); + uint8_t hxfr = ep->ep_num | HXFR_OUT_NIN | (ep->is_iso ? HXFR_ISO : 0); + + if (ep->ep_num == 0 && (ep->buf == NULL || ep->total_len == 0)) { + // Control ZLP status use HS + hxfr |= HXFR_HS; + } else { + uint8_t const xact_len = (uint8_t) tu_min16(ep->total_len - ep->xferred_len, ep->packet_size); + TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ,); + if (xact_len) { + fifo_write(rhport, SNDFIFO_ADDR, ep->buf, xact_len, in_isr); + } + sndbc_write(rhport, xact_len, in_isr); + } - uint8_t const hxfr = ep->ep_num | HXFR_OUT_NIN | (ep->is_iso ? HXFR_ISO : 0); hxfr_write(rhport, hxfr, in_isr); } @@ -599,7 +605,12 @@ void xact_in(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { reg_write(rhport, HCTL_ADDR, hctl, in_isr); } - uint8_t const hxfr = ep->ep_num | (ep->is_iso ? HXFR_ISO : 0); + uint8_t hxfr = ep->ep_num | (ep->is_iso ? HXFR_ISO : 0); + if (ep->ep_num == 0 && (ep->buf == NULL || ep->total_len == 0)) { + // Control ZLP status use HS + hxfr |= HXFR_HS; + } + hxfr_write(rhport, hxfr, in_isr); } @@ -611,24 +622,8 @@ TU_ATTR_ALWAYS_INLINE static inline void xact_inout(uint8_t rhport, max3421_ep_t } } -void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t result, uint8_t data_toggle) { - (void) rhport; - (void) result; - ep->xfer_pending = 0; - ep->data_toggle = data_toggle; - //uint8_t const ep_addr = tu_edpt_addr(ep->ep_num, ep->ep_dir); - //hcd_event_xfer_complete(rhport, ep_addr, ep->xferred_len, result, true); - -// max3421_ep_t *next_ep = find_next_pending_ep(ep); -// if (next_ep) { -// xact_inout(rhport, next_ep, true, true); -// } -} - // Submit a transfer, when complete hcd_event_xfer_complete() must be invoked bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { - (void) rhport; - uint8_t const ep_num = tu_edpt_number(ep_addr); uint8_t const ep_dir = tu_edpt_dir(ep_addr); @@ -644,24 +639,12 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf ep->xfer_complete = 0; ep->xfer_pending = 1; + if ( ep_num == 0 ) { + ep->data_toggle = 1; + } + // carry out transfer if not busy -// if ( atomic_flag_test_and_set(&_hcd_data.busy) ) - { - uint8_t hxfr = ep_num; - - if ( ep_num == 0 ) { - ep->data_toggle = 1; - if ( buffer == NULL || buflen == 0 ) { - // ZLP for ACK stage, use HS - peraddr_write(rhport, daddr, false); - - hxfr |= HXFR_HS; - hxfr |= (ep_dir ? 0 : HXFR_OUT_NIN); - hxfr_write(rhport, hxfr, false); - return true; - } - } - + if ( !atomic_flag_test_and_set(&_hcd_data.busy) ) { xact_inout(rhport, ep, true, false); } @@ -683,6 +666,8 @@ bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8] (void) rhport; max3421_ep_t* ep = find_opened_ep(daddr, 0, 0); + TU_ASSERT(ep); + ep->ep_dir = 0; ep->total_len = 8; ep->xferred_len = 0; @@ -703,6 +688,26 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { return false; } +//--------------------------------------------------------------------+ +// Interrupt Handler +//--------------------------------------------------------------------+ + +static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t result, uint8_t data_toggle) { + uint8_t const ep_addr = tu_edpt_addr(ep->ep_num, ep->ep_dir); + ep->data_toggle = data_toggle; + ep->xfer_pending = 0; + hcd_event_xfer_complete(ep->daddr, ep_addr, ep->xferred_len, result, true); + + // Find next pending endpoint + max3421_ep_t *next_ep = find_next_pending_ep(ep); + if (next_ep) { + xact_inout(rhport, next_ep, true, true); + }else { + // no more pending + atomic_flag_clear(&_hcd_data.busy); + } +} + static void handle_xfer_done(uint8_t rhport) { uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, true); uint8_t const hresult = hrsl & HRSL_RESULT_MASK; @@ -739,7 +744,7 @@ static void handle_xfer_done(uint8_t rhport) { max3421_ep_t *next_ep = find_next_pending_ep(ep); if (ep == next_ep) { - // only one pending, retry immediately + // this endpoint is only one pending, retry immediately hxfr_write(rhport, _hcd_data.hxfr, true); }else if (next_ep) { // switch to next pending TODO could have issue with double buffered if not clear previously out data @@ -763,7 +768,6 @@ static void handle_xfer_done(uint8_t rhport) { if ( ep->xfer_complete ) { uint8_t const dt = (hrsl & HRSL_RCVTOGRD) ? 1 : 0; // save data toggle xfer_complete_isr(rhport, ep, xfer_result, dt); - hcd_event_xfer_complete(_hcd_data.peraddr, TUSB_DIR_IN_MASK | ep_num, ep->xferred_len, xfer_result, true); }else { // more to transfer hxfr_write(rhport, _hcd_data.hxfr, true); @@ -786,8 +790,8 @@ static void handle_xfer_done(uint8_t rhport) { if (xact_len < ep->packet_size || ep->xferred_len >= ep->total_len) { uint8_t const dt = (hrsl & HRSL_SNDTOGRD) ? 1 : 0; // save data toggle xfer_complete_isr(rhport, ep, xfer_result, dt); - hcd_event_xfer_complete(_hcd_data.peraddr, ep_num, ep->xferred_len, xfer_result, true); } else { + // more to transfer xact_out(rhport, ep, false, true); } } From c35061603836353e2e13c7bceafdafced1785dde Mon Sep 17 00:00:00 2001 From: yuxiaojun Date: Mon, 28 Aug 2023 15:24:14 +0800 Subject: [PATCH 19/71] fix:Resource leak: fp Signed-off-by: yuxiaojun --- hw/mcu/sony/cxd56/mkspk/mkspk.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/mcu/sony/cxd56/mkspk/mkspk.c b/hw/mcu/sony/cxd56/mkspk/mkspk.c index c447ad7da..3feb235f6 100644 --- a/hw/mcu/sony/cxd56/mkspk/mkspk.c +++ b/hw/mcu/sony/cxd56/mkspk/mkspk.c @@ -172,6 +172,7 @@ static struct elf_file *load_elf(const char *filename) ef = (struct elf_file *)malloc(sizeof(*ef)); if (!ef) { + fclose(fp); return NULL; } @@ -182,6 +183,7 @@ static struct elf_file *load_elf(const char *filename) buf = (char *)malloc(fsize); if (!buf) { + fclose(fp); return NULL; } From 3740a3287ad5965df34639e90bfa890b36c0fd60 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 29 Aug 2023 18:22:21 +0700 Subject: [PATCH 20/71] - correct tuh_max3421e_int_api() for nrf52 - hcd_int_disable/enable is software only to reduce interrupt lag --- hw/bsp/nrf/boards/pca10056/board.h | 9 +++ hw/bsp/nrf/family.c | 20 +++++- src/portable/analog/max3421/hcd_max3421.c | 86 ++++++++++++++++------- 3 files changed, 87 insertions(+), 28 deletions(-) diff --git a/hw/bsp/nrf/boards/pca10056/board.h b/hw/bsp/nrf/boards/pca10056/board.h index f4368f830..16d31addb 100644 --- a/hw/bsp/nrf/boards/pca10056/board.h +++ b/hw/bsp/nrf/boards/pca10056/board.h @@ -31,6 +31,8 @@ extern "C" { #endif +#define _PINNUM(port, pin) ((port)*32 + (pin)) + // LED #define LED_PIN 13 #define LED_STATE_ON 0 @@ -43,6 +45,13 @@ #define UART_RX_PIN 8 #define UART_TX_PIN 6 +// SPI for USB host shield +#define MAX3421E_SCK_PIN _PINNUM(1, 15) +#define MAX3421E_MOSI_PIN _PINNUM(1, 13) +#define MAX3421E_MISO_PIN _PINNUM(1, 14) +#define MAX3421E_CS_PIN _PINNUM(1, 12) +#define MAX3241E_INTR_PIN _PINNUM(1, 11) + #ifdef __cplusplus } #endif diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 368763b84..083efc235 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -107,7 +107,12 @@ void max3421e_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { //--------------------------------------------------------------------+ void tuh_max3421e_int_api(uint8_t rhport, bool enabled) { (void) rhport; - nrfx_gpiote_trigger_enable(MAX3241E_INTR_PIN, enabled); + + if (enabled) { + nrfx_gpiote_trigger_enable(MAX3241E_INTR_PIN, true); + }else { + nrfx_gpiote_trigger_disable(MAX3241E_INTR_PIN); + } } void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { @@ -217,6 +222,19 @@ void board_init(void) { #endif #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + // MAX3421 need 3.3v signal + if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) != UICR_REGOUT0_VOUT_3V3) { + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos; + while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} + + NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~UICR_REGOUT0_VOUT_Msk) | UICR_REGOUT0_VOUT_3V3; + + NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos; + while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} + + NVIC_SystemReset(); + } + // manually manage CS nrf_gpio_cfg_output(MAX3421E_CS_PIN); tuh_max3421_spi_cs_api(0, false); diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 262dbca0f..cb7911992 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -184,8 +184,6 @@ typedef struct { } max3421_ep_t; typedef struct { - atomic_flag busy; // busy transferring - // cached register uint8_t sndbc; uint8_t hirq; @@ -194,7 +192,10 @@ typedef struct { uint8_t peraddr; uint8_t hxfr; + atomic_flag busy; // busy transferring + volatile uint8_t intr_disable_count; volatile uint16_t frame_count; + max3421_ep_t ep[CFG_TUH_MAX3421_ENDPOINT_TOTAL]; // [0] is reserved for addr0 OSAL_MUTEX_DEF(spi_mutexdef); @@ -220,8 +221,8 @@ void tuh_max3421e_int_api(uint8_t rhport, bool enabled); static void max3421_spi_lock(uint8_t rhport, bool in_isr) { // disable interrupt and mutex lock (for pre-emptive RTOS) if not in_isr if (!in_isr) { - tuh_max3421e_int_api(rhport, false); (void) osal_mutex_lock(_hcd_data.spi_mutex, OSAL_TIMEOUT_WAIT_FOREVER); + tuh_max3421e_int_api(rhport, false); } // assert CS @@ -294,6 +295,12 @@ static uint8_t reg_read(uint8_t rhport, uint8_t reg, bool in_isr) { return ret ? rx_buf[1] : 0; } +static inline void hirq_write(uint8_t rhport, uint8_t data, bool in_isr) { + reg_write(rhport, HIRQ_ADDR, data, in_isr); + // HIRQ write 1 is clear + _hcd_data.hirq &= ~data; +} + static inline void hien_write(uint8_t rhport, uint8_t data, bool in_isr) { _hcd_data.hien = data; reg_write(rhport, HIEN_ADDR, data, in_isr); @@ -440,13 +447,14 @@ tusb_speed_t handle_connect_irq(uint8_t rhport) { bool hcd_init(uint8_t rhport) { (void) rhport; - hcd_int_disable(rhport); + tuh_max3421e_int_api(rhport, false); tuh_max3421_spi_cs_api(rhport, false); TU_LOG2_INT(sizeof(max3421_ep_t)); TU_LOG2_INT(sizeof(max3421_data_t)); tu_memclr(&_hcd_data, sizeof(_hcd_data)); + _hcd_data.peraddr = 0xff; // invalid #if OSAL_MUTEX_REQUIRED _hcd_data.spi_mutex = osal_mutex_create(&_hcd_data.spi_mutexdef); @@ -469,11 +477,13 @@ bool hcd_init(uint8_t rhport) { reg_write(rhport, HCTL_ADDR, HCTL_BUSRST | HCTL_FRMRST, false); // clear all previously pending IRQ - reg_write(rhport, HIRQ_ADDR, 0xff, false); + hirq_write(rhport, 0xff, false); // Enable IRQ hien_write(rhport, DEFAULT_HIEN, false); + tuh_max3421e_int_api(rhport, true); + // Enable Interrupt pin reg_write(rhport, CPUCTL_ADDR, CPUCTL_IE, false); @@ -481,13 +491,21 @@ bool hcd_init(uint8_t rhport) { } // Enable USB interrupt +// Not actually enable GPIO interrupt, just set variable to prevent handler to process void hcd_int_enable (uint8_t rhport) { - tuh_max3421e_int_api(rhport, true); + (void) rhport; + // tuh_max3421e_int_api(rhport, true); + if (_hcd_data.intr_disable_count) { + _hcd_data.intr_disable_count--; + } } // Disable USB interrupt +// Not actually disable GPIO interrupt, just set variable to prevent handler to process void hcd_int_disable(uint8_t rhport) { - tuh_max3421e_int_api(rhport, false); + (void) rhport; + //tuh_max3421e_int_api(rhport, false); + _hcd_data.intr_disable_count++; } // Get frame number (1ms) @@ -521,7 +539,7 @@ void hcd_port_reset_end(uint8_t rhport) { reg_write(rhport, HCTL_ADDR, 0, false); // Bus reset will also trigger CONDET IRQ, clear and re-enable it after reset - reg_write(rhport, HIRQ_ADDR, HIRQ_CONDET_IRQ, false); + hirq_write(rhport, HIRQ_CONDET_IRQ, false); hien_write(rhport, DEFAULT_HIEN, false); } @@ -572,19 +590,23 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * e void xact_out(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { // Page 12: Programming BULK-OUT Transfers // TODO double buffered - if (switch_ep) { - peraddr_write(rhport, ep->daddr, in_isr); - - uint8_t const hctl = (ep->data_toggle ? HCTL_SNDTOG1 : HCTL_SNDTOG0); - reg_write(rhport, HCTL_ADDR, hctl, in_isr); - } uint8_t hxfr = ep->ep_num | HXFR_OUT_NIN | (ep->is_iso ? HXFR_ISO : 0); - if (ep->ep_num == 0 && (ep->buf == NULL || ep->total_len == 0)) { // Control ZLP status use HS hxfr |= HXFR_HS; - } else { + } + + if (switch_ep) { + peraddr_write(rhport, ep->daddr, in_isr); + + if ( 0 == (hxfr & HXFR_HS) ) { + uint8_t const hctl = (ep->data_toggle ? HCTL_SNDTOG1 : HCTL_SNDTOG0); + reg_write(rhport, HCTL_ADDR, hctl, in_isr); + } + } + + if ( 0 == (hxfr & HXFR_HS) ) { uint8_t const xact_len = (uint8_t) tu_min16(ep->total_len - ep->xferred_len, ep->packet_size); TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ,); if (xact_len) { @@ -598,12 +620,6 @@ void xact_out(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { void xact_in(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { // Page 13: Programming BULK-IN Transfers - if (switch_ep) { - peraddr_write(rhport, ep->daddr, in_isr); - - uint8_t const hctl = (ep->data_toggle ? HCTL_RCVTOG1 : HCTL_RCVTOG0); - reg_write(rhport, HCTL_ADDR, hctl, in_isr); - } uint8_t hxfr = ep->ep_num | (ep->is_iso ? HXFR_ISO : 0); if (ep->ep_num == 0 && (ep->buf == NULL || ep->total_len == 0)) { @@ -611,6 +627,15 @@ void xact_in(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { hxfr |= HXFR_HS; } + if (switch_ep) { + peraddr_write(rhport, ep->daddr, in_isr); + + if ( 0 == (hxfr & HXFR_HS) ) { + uint8_t const hctl = (ep->data_toggle ? HCTL_RCVTOG1 : HCTL_RCVTOG0); + reg_write(rhport, HCTL_ADDR, hctl, in_isr); + } + } + hxfr_write(rhport, hxfr, in_isr); } @@ -721,7 +746,7 @@ static void handle_xfer_done(uint8_t rhport) { xfer_result_t xfer_result; - //TU_LOG3("HRSL: %02X\r\n", hrsl); +// TU_LOG3("HRSL: %02X\r\n", hrsl); switch(hresult) { case HRSL_SUCCESS: xfer_result = XFER_RESULT_SUCCESS; @@ -821,13 +846,20 @@ void print_hirq(uint8_t hirq) { void hcd_int_handler(uint8_t rhport) { uint8_t hirq = reg_read(rhport, HIRQ_ADDR, true) & _hcd_data.hien; if (!hirq) return; - // print_hirq(hirq); if (hirq & HIRQ_FRAME_IRQ) { _hcd_data.frame_count++; } + // interrupt is disabled, only ack FRAME IRQ and skip the rest + if (_hcd_data.intr_disable_count) { + if (hirq & HIRQ_FRAME_IRQ) { + hirq_write(rhport, HIRQ_FRAME_IRQ, true); + } + return; + } + if (hirq & HIRQ_CONDET_IRQ) { tusb_speed_t speed = handle_connect_irq(rhport); @@ -861,7 +893,7 @@ void hcd_int_handler(uint8_t rhport) { } // ack RCVDVAV IRQ - reg_write(rhport, HIRQ_ADDR, HIRQ_RCVDAV_IRQ, true); + hirq_write(rhport, HIRQ_RCVDAV_IRQ, true); hirq = reg_read(rhport, HIRQ_ADDR, true); } @@ -871,7 +903,7 @@ void hcd_int_handler(uint8_t rhport) { } if ( hirq & HIRQ_HXFRDN_IRQ ) { - reg_write(rhport, HIRQ_ADDR, HIRQ_HXFRDN_IRQ, true); + hirq_write(rhport, HIRQ_HXFRDN_IRQ, true); handle_xfer_done(rhport); } @@ -881,7 +913,7 @@ void hcd_int_handler(uint8_t rhport) { // clear all interrupt except SNDBAV_IRQ (never clear by us). Note RCVDAV_IRQ, HXFRDN_IRQ already clear while processing hirq &= ~HIRQ_SNDBAV_IRQ; if ( hirq ) { - reg_write(rhport, HIRQ_ADDR, hirq, true); + hirq_write(rhport, hirq, true); } } From 2a814a99af32bf084cbb730d97e3c9cb31a3fa85 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 29 Aug 2023 20:27:37 +0700 Subject: [PATCH 21/71] - hcd_setup_send() also check for busy flag - xact_inout() to support send setup --- src/portable/analog/max3421/hcd_max3421.c | 71 +++++++++++++---------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index cb7911992..461e02593 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -168,6 +168,7 @@ typedef struct { struct TU_ATTR_PACKED { uint8_t ep_dir : 1; uint8_t is_iso : 1; + uint8_t is_setup : 1; uint8_t data_toggle : 1; uint8_t xfer_pending : 1; uint8_t xfer_complete : 1; @@ -590,56 +591,55 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * e void xact_out(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { // Page 12: Programming BULK-OUT Transfers // TODO double buffered - - uint8_t hxfr = ep->ep_num | HXFR_OUT_NIN | (ep->is_iso ? HXFR_ISO : 0); - if (ep->ep_num == 0 && (ep->buf == NULL || ep->total_len == 0)) { - // Control ZLP status use HS - hxfr |= HXFR_HS; - } - if (switch_ep) { peraddr_write(rhport, ep->daddr, in_isr); - if ( 0 == (hxfr & HXFR_HS) ) { - uint8_t const hctl = (ep->data_toggle ? HCTL_SNDTOG1 : HCTL_SNDTOG0); - reg_write(rhport, HCTL_ADDR, hctl, in_isr); - } + uint8_t const hctl = (ep->data_toggle ? HCTL_SNDTOG1 : HCTL_SNDTOG0); + reg_write(rhport, HCTL_ADDR, hctl, in_isr); } - if ( 0 == (hxfr & HXFR_HS) ) { - uint8_t const xact_len = (uint8_t) tu_min16(ep->total_len - ep->xferred_len, ep->packet_size); - TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ,); - if (xact_len) { - fifo_write(rhport, SNDFIFO_ADDR, ep->buf, xact_len, in_isr); - } - sndbc_write(rhport, xact_len, in_isr); + uint8_t const xact_len = (uint8_t) tu_min16(ep->total_len - ep->xferred_len, ep->packet_size); + TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ,); + if (xact_len) { + fifo_write(rhport, SNDFIFO_ADDR, ep->buf, xact_len, in_isr); } + sndbc_write(rhport, xact_len, in_isr); + uint8_t hxfr = ep->ep_num | HXFR_OUT_NIN | (ep->is_iso ? HXFR_ISO : 0); hxfr_write(rhport, hxfr, in_isr); } void xact_in(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { // Page 13: Programming BULK-IN Transfers - - uint8_t hxfr = ep->ep_num | (ep->is_iso ? HXFR_ISO : 0); - if (ep->ep_num == 0 && (ep->buf == NULL || ep->total_len == 0)) { - // Control ZLP status use HS - hxfr |= HXFR_HS; - } - if (switch_ep) { peraddr_write(rhport, ep->daddr, in_isr); - if ( 0 == (hxfr & HXFR_HS) ) { - uint8_t const hctl = (ep->data_toggle ? HCTL_RCVTOG1 : HCTL_RCVTOG0); - reg_write(rhport, HCTL_ADDR, hctl, in_isr); - } + uint8_t const hctl = (ep->data_toggle ? HCTL_RCVTOG1 : HCTL_RCVTOG0); + reg_write(rhport, HCTL_ADDR, hctl, in_isr); } + uint8_t hxfr = ep->ep_num | (ep->is_iso ? HXFR_ISO : 0); hxfr_write(rhport, hxfr, in_isr); } TU_ATTR_ALWAYS_INLINE static inline void xact_inout(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { + if (ep->ep_num == 0 ) { + // setup + if (ep->is_setup) { + peraddr_write(rhport, ep->daddr, in_isr); + hxfr_write(rhport, HXFR_SETUP, in_isr); + return; + } + + // status + if (ep->buf == NULL || ep->total_len == 0) { + uint8_t const hxfr = HXFR_HS | (ep->ep_dir ? 0 : HXFR_OUT_NIN); + peraddr_write(rhport, ep->daddr, in_isr); + hxfr_write(rhport, hxfr, in_isr); + return; + } + } + if (ep->ep_dir) { xact_in(rhport, ep, switch_ep, in_isr); }else { @@ -665,12 +665,15 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf ep->xfer_pending = 1; if ( ep_num == 0 ) { + ep->is_setup = 0; ep->data_toggle = 1; } // carry out transfer if not busy if ( !atomic_flag_test_and_set(&_hcd_data.busy) ) { xact_inout(rhport, ep, true, false); + } else { + return true; } return true; @@ -694,12 +697,16 @@ bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8] TU_ASSERT(ep); ep->ep_dir = 0; - ep->total_len = 8; + ep->total_len = 8; ep->xferred_len = 0; + ep->is_setup = 1; - peraddr_write(rhport, daddr, false); fifo_write(rhport, SUDFIFO_ADDR, setup_packet, 8, false); - hxfr_write(rhport, HXFR_SETUP, false); + + // carry out transfer if not busy + if ( !atomic_flag_test_and_set(&_hcd_data.busy) ) { + xact_inout(rhport, ep, true, false); + } return true; } From 1ab488eb06ef4cb8ad9c0cff91e6b0caf76f73c4 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 30 Aug 2023 16:04:18 +0700 Subject: [PATCH 22/71] call xfer_complete_isr() when result is not successful (stalled or failed) --- hw/bsp/nrf/boards/pca10095/board.h | 9 +++++ hw/bsp/nrf/family.c | 7 ++-- hw/bsp/nrf/nrfx_config.h | 2 +- src/common/tusb_mcu.h | 2 +- src/portable/analog/max3421/hcd_max3421.c | 43 ++++++++++++++++------- 5 files changed, 47 insertions(+), 16 deletions(-) diff --git a/hw/bsp/nrf/boards/pca10095/board.h b/hw/bsp/nrf/boards/pca10095/board.h index fd3c63d6a..b9d3a19dc 100644 --- a/hw/bsp/nrf/boards/pca10095/board.h +++ b/hw/bsp/nrf/boards/pca10095/board.h @@ -31,6 +31,8 @@ extern "C" { #endif +#define _PINNUM(port, pin) ((port)*32 + (pin)) + // LED #define LED_PIN 28 #define LED_STATE_ON 0 @@ -43,6 +45,13 @@ #define UART_RX_PIN 32 #define UART_TX_PIN 33 +// SPI for USB host shield +#define MAX3421E_SCK_PIN _PINNUM(1, 15) +#define MAX3421E_MOSI_PIN _PINNUM(1, 13) +#define MAX3421E_MISO_PIN _PINNUM(1, 14) +#define MAX3421E_CS_PIN _PINNUM(1, 12) +#define MAX3241E_INTR_PIN _PINNUM(1, 11) + #ifdef __cplusplus } #endif diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 083efc235..2b4260083 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -34,6 +34,7 @@ #pragma GCC diagnostic ignored "-Wcast-align" #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wundef" +#pragma GCC diagnostic ignored "-Wredundant-decls" #endif #include "nrfx.h" @@ -94,7 +95,7 @@ TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) { //------------- Host using MAX2341E -------------// #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 -static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(0); +static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(1); void max3421e_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { if ( !(pin == MAX3241E_INTR_PIN && action == NRF_GPIOTE_POLARITY_HITOLO) ) return; @@ -222,7 +223,8 @@ void board_init(void) { #endif #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 - // MAX3421 need 3.3v signal + // MAX3421 need 3.3v signal (may not be needed) + #if defined(UICR_REGOUT0_VOUT_Msk) && 0 if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) != UICR_REGOUT0_VOUT_3V3) { NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos; while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} @@ -234,6 +236,7 @@ void board_init(void) { NVIC_SystemReset(); } + #endif // manually manage CS nrf_gpio_cfg_output(MAX3421E_CS_PIN); diff --git a/hw/bsp/nrf/nrfx_config.h b/hw/bsp/nrf/nrfx_config.h index e3d0ea91b..95ef33ce4 100644 --- a/hw/bsp/nrf/nrfx_config.h +++ b/hw/bsp/nrf/nrfx_config.h @@ -11,7 +11,7 @@ #define NRFX_UARTE0_ENABLED 1 #define NRFX_SPIM_ENABLED 1 -#define NRFX_SPIM0_ENABLED 1 +#define NRFX_SPIM1_ENABLED 1 // use SPI1 since nrf5340 share uart with spi #define NRFX_PRS_ENABLED 0 #define NRFX_USBREG_ENABLED 1 diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 21939df7c..8807ff8aa 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -390,7 +390,7 @@ // External USB controller //--------------------------------------------------------------------+ -#if defined(CFG_TUH_MAX3421) & CFG_TUH_MAX3421 +#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 #ifndef CFG_TUH_MAX3421_ENDPOINT_TOTAL #define CFG_TUH_MAX3421_ENDPOINT_TOTAL (8 + 4*(CFG_TUH_DEVICE_MAX-1)) #endif diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 461e02593..705bb5bfd 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -374,7 +374,8 @@ static max3421_ep_t * find_next_pending_ep(max3421_ep_t * cur_ep) { // starting from next endpoint for (size_t i = idx + 1; i < CFG_TUH_MAX3421_ENDPOINT_TOTAL; i++) { max3421_ep_t* ep = &_hcd_data.ep[i]; - if (ep->xfer_pending) { + if (ep->xfer_pending && ep->packet_size) { +// TU_LOG3("next pending i = %u\n", i); return ep; } } @@ -382,7 +383,8 @@ static max3421_ep_t * find_next_pending_ep(max3421_ep_t * cur_ep) { // wrap around including current endpoint for (size_t i = 0; i <= idx; i++) { max3421_ep_t* ep = &_hcd_data.ep[i]; - if (ep->xfer_pending) { + if (ep->xfer_pending && ep->packet_size) { +// TU_LOG3("next pending i = %u\n", i); return ep; } } @@ -464,6 +466,10 @@ bool hcd_init(uint8_t rhport) { // full duplex, interrupt negative edge reg_write(rhport, PINCTL_ADDR, PINCTL_FDUPSPI, false); + // V1 is 0x01, V2 is 0x12, V3 is 0x13 + // uint8_t const revision = reg_read(rhport, REVISION_ADDR, false); + // TU_LOG2_HEX(revision); + // reset reg_write(rhport, USBCTL_ADDR, USBCTL_CHIPRES, false); reg_write(rhport, USBCTL_ADDR, 0, false); @@ -699,6 +705,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8] ep->ep_dir = 0; ep->total_len = 8; ep->xferred_len = 0; + ep->xfer_pending = 1; ep->is_setup = 1; fifo_write(rhport, SUDFIFO_ADDR, setup_packet, 8, false); @@ -724,9 +731,16 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { // Interrupt Handler //--------------------------------------------------------------------+ -static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t result, uint8_t data_toggle) { +static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t result, uint8_t hrsl) { uint8_t const ep_addr = tu_edpt_addr(ep->ep_num, ep->ep_dir); - ep->data_toggle = data_toggle; + + // save data toggle + if (ep->ep_dir) { + ep->data_toggle = (hrsl & HRSL_RCVTOGRD) ? 1 : 0; + }else { + ep->data_toggle = (hrsl & HRSL_SNDTOGRD) ? 1 : 0; + } + ep->xfer_pending = 0; hcd_event_xfer_complete(ep->daddr, ep_addr, ep->xferred_len, result, true); @@ -763,10 +777,6 @@ static void handle_xfer_done(uint8_t rhport) { xfer_result = XFER_RESULT_STALLED; break; - case HRSL_BAD_REQ: - // occurred when initialized without any pending transfer. Skip for now - return; - case HRSL_NAK: if (ep_num == 0) { // NAK on control, retry immediately @@ -781,15 +791,26 @@ static void handle_xfer_done(uint8_t rhport) { }else if (next_ep) { // switch to next pending TODO could have issue with double buffered if not clear previously out data xact_inout(rhport, next_ep, true, true); + }else { + TU_ASSERT(false,); } } return; + case HRSL_BAD_REQ: + // occurred when initialized without any pending transfer. Skip for now + return; + default: xfer_result = XFER_RESULT_FAILED; break; } + if (xfer_result != XFER_RESULT_SUCCESS) { + xfer_complete_isr(rhport, ep, xfer_result, hrsl); + return; + } + if (ep_dir) { // IN transfer: fifo data is already received in RCVDAV IRQ if ( hxfr_type & HXFR_HS ) { @@ -798,8 +819,7 @@ static void handle_xfer_done(uint8_t rhport) { // short packet or all bytes transferred if ( ep->xfer_complete ) { - uint8_t const dt = (hrsl & HRSL_RCVTOGRD) ? 1 : 0; // save data toggle - xfer_complete_isr(rhport, ep, xfer_result, dt); + xfer_complete_isr(rhport, ep, xfer_result, hrsl); }else { // more to transfer hxfr_write(rhport, _hcd_data.hxfr, true); @@ -820,8 +840,7 @@ static void handle_xfer_done(uint8_t rhport) { ep->buf += xact_len; if (xact_len < ep->packet_size || ep->xferred_len >= ep->total_len) { - uint8_t const dt = (hrsl & HRSL_SNDTOGRD) ? 1 : 0; // save data toggle - xfer_complete_isr(rhport, ep, xfer_result, dt); + xfer_complete_isr(rhport, ep, xfer_result, hrsl); } else { // more to transfer xact_out(rhport, ep, false, true); From 41493426b38c8ce44b1f7720b907538bc5402f98 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 30 Aug 2023 16:21:43 +0700 Subject: [PATCH 23/71] use ep buf to keep setup packet, work well with hid device --- examples/host/msc_file_explorer/src/tusb_config.h | 2 +- src/portable/analog/max3421/hcd_max3421.c | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/host/msc_file_explorer/src/tusb_config.h b/examples/host/msc_file_explorer/src/tusb_config.h index 28e130c0e..e6186ba46 100644 --- a/examples/host/msc_file_explorer/src/tusb_config.h +++ b/examples/host/msc_file_explorer/src/tusb_config.h @@ -37,7 +37,7 @@ #if CFG_TUSB_MCU == OPT_MCU_RP2040 // change to 1 if using pico-pio-usb as host controller for raspberry rp2040 #define CFG_TUH_RPI_PIO_USB 0 - #define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_US + #define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB //#elif CFG_TUSB_MCU == OPT_MCU_NRF5X // // Use external USB controller (via SPI) MAX3421E (aka usb host shield) // #define CFG_TUH_MAX3421 1 diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 705bb5bfd..d644390da 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -633,6 +633,7 @@ TU_ATTR_ALWAYS_INLINE static inline void xact_inout(uint8_t rhport, max3421_ep_t // setup if (ep->is_setup) { peraddr_write(rhport, ep->daddr, in_isr); + fifo_write(rhport, SUDFIFO_ADDR, ep->buf, 8, in_isr); hxfr_write(rhport, HXFR_SETUP, in_isr); return; } @@ -703,12 +704,12 @@ bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8] TU_ASSERT(ep); ep->ep_dir = 0; + ep->is_setup = 1; + ep->buf = (uint8_t*)(uintptr_t) setup_packet; ep->total_len = 8; ep->xferred_len = 0; + ep->xfer_complete = 0; ep->xfer_pending = 1; - ep->is_setup = 1; - - fifo_write(rhport, SUDFIFO_ADDR, setup_packet, 8, false); // carry out transfer if not busy if ( !atomic_flag_test_and_set(&_hcd_data.busy) ) { From 3b7d5aa0421f3d3a7ac199de0138dc40141fbddd Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 31 Aug 2023 16:52:09 +0700 Subject: [PATCH 24/71] improve connection & disconnection detection. But there is still issue when CONDETIRQ occurs but we are disabled interrupt (for osal queue access). --- hw/bsp/board.c | 26 +++---- hw/bsp/nrf/family.c | 49 ++++++------- src/host/usbh.c | 2 +- src/portable/analog/max3421/hcd_max3421.c | 89 +++++++++++------------ 4 files changed, 74 insertions(+), 92 deletions(-) diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 417630a03..562792625 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -44,17 +44,16 @@ // If using SES IDE, use the Syscalls/SEGGER_RTT_Syscalls_SES.c instead #if !(defined __SES_ARM) && !(defined __SES_RISCV) && !(defined __CROSSWORKS_ARM) + #include "SEGGER_RTT.h" -TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) -{ +TU_ATTR_USED int sys_write(int fhdl, const void *buf, size_t count) { (void) fhdl; - SEGGER_RTT_Write(0, (const char*) buf, (int) count); + SEGGER_RTT_Write(0, (const char *) buf, (int) count); return count; } -TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) -{ +TU_ATTR_USED int sys_read(int fhdl, char *buf, size_t count) { (void) fhdl; int rd = (int) SEGGER_RTT_Read(0, buf, count); return (rd > 0) ? rd : -1; @@ -67,8 +66,7 @@ TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) #include "board_mcu.h" -TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) -{ +TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) { (void) fhdl; uint8_t const* buf8 = (uint8_t const*) buf; @@ -79,8 +77,7 @@ TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) return (int) count; } -TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) -{ +TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) { (void) fhdl; (void) buf; (void) count; @@ -90,14 +87,12 @@ TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) #else // Default logging with on-board UART -TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) -{ +TU_ATTR_USED int sys_write (int fhdl, const void *buf, size_t count) { (void) fhdl; return board_uart_write(buf, (int) count); } -TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) -{ +TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) { (void) fhdl; int rd = board_uart_read((uint8_t*) buf, (int) count); return (rd > 0) ? rd : -1; @@ -105,8 +100,7 @@ TU_ATTR_USED int sys_read (int fhdl, char *buf, size_t count) #endif -int board_getchar(void) -{ +int board_getchar(void) { char c; - return ( sys_read(0, &c, 1) > 0 ) ? (int) c : (-1); + return (sys_read(0, &c, 1) > 0) ? (int) c : (-1); } diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 2b4260083..7358458ce 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -98,7 +98,7 @@ TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) { static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(1); void max3421e_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { - if ( !(pin == MAX3241E_INTR_PIN && action == NRF_GPIOTE_POLARITY_HITOLO) ) return; + if (!(pin == MAX3241E_INTR_PIN && action == NRF_GPIOTE_POLARITY_HITOLO)) return; tuh_int_handler(1); } @@ -111,7 +111,7 @@ void tuh_max3421e_int_api(uint8_t rhport, bool enabled) { if (enabled) { nrfx_gpiote_trigger_enable(MAX3241E_INTR_PIN, true); - }else { + } else { nrfx_gpiote_trigger_disable(MAX3241E_INTR_PIN); } } @@ -121,7 +121,7 @@ void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { nrf_gpio_pin_write(MAX3421E_CS_PIN, active ? 0 : 1); } -bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len) { +bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { (void) rhport; nrfx_spim_xfer_desc_t xfer = { @@ -157,21 +157,21 @@ void board_init(void) { nrf_gpio_cfg_input(BUTTON_PIN, NRF_GPIO_PIN_PULLUP); // 1ms tick timer - SysTick_Config(SystemCoreClock/1000); + SysTick_Config(SystemCoreClock / 1000); // UART nrfx_uarte_config_t uart_cfg = { - .pseltxd = UART_TX_PIN, - .pselrxd = UART_RX_PIN, - .pselcts = NRF_UARTE_PSEL_DISCONNECTED, - .pselrts = NRF_UARTE_PSEL_DISCONNECTED, - .p_context = NULL, - .baudrate = NRF_UARTE_BAUDRATE_115200, // CFG_BOARD_UART_BAUDRATE - .interrupt_priority = 7, - .hal_cfg = { - .hwfc = NRF_UARTE_HWFC_DISABLED, - .parity = NRF_UARTE_PARITY_EXCLUDED, - } + .pseltxd = UART_TX_PIN, + .pselrxd = UART_RX_PIN, + .pselcts = NRF_UARTE_PSEL_DISCONNECTED, + .pselrts = NRF_UARTE_PSEL_DISCONNECTED, + .p_context = NULL, + .baudrate = NRF_UARTE_BAUDRATE_115200, // CFG_BOARD_UART_BAUDRATE + .interrupt_priority = 7, + .hal_cfg = { + .hwfc = NRF_UARTE_HWFC_DISABLED, + .parity = NRF_UARTE_PARITY_EXCLUDED, + } }; nrfx_uarte_init(&_uart_id, &uart_cfg, NULL); //uart_handler); @@ -211,11 +211,11 @@ void board_init(void) { // USB power may already be ready at this time -> no event generated // We need to invoke the handler based on the status initially - #ifdef NRF5340_XXAA +#ifdef NRF5340_XXAA usb_reg = NRF_USBREGULATOR->USBREGSTATUS; - #else +#else usb_reg = NRF_POWER->USBREGSTATUS; - #endif +#endif } if ( usb_reg & VBUSDETECT_Msk ) tusb_hal_nrf_power_event(USB_EVT_DETECTED); @@ -308,8 +308,7 @@ uint32_t board_millis(void) { #ifdef SOFTDEVICE_PRESENT // process SOC event from SD -uint32_t proc_soc(void) -{ +uint32_t proc_soc(void) { uint32_t soc_evt; uint32_t err = sd_evt_get(&soc_evt); @@ -326,18 +325,14 @@ uint32_t proc_soc(void) return err; } -uint32_t proc_ble(void) -{ +uint32_t proc_ble(void) { // do nothing with ble return NRF_ERROR_NOT_FOUND; } -void SD_EVT_IRQHandler(void) -{ +void SD_EVT_IRQHandler(void) { // process BLE and SOC until there is no more events - while( (NRF_ERROR_NOT_FOUND != proc_ble()) || (NRF_ERROR_NOT_FOUND != proc_soc()) ) - { - + while( (NRF_ERROR_NOT_FOUND != proc_ble()) || (NRF_ERROR_NOT_FOUND != proc_soc()) ) { } } diff --git a/src/host/usbh.c b/src/host/usbh.c index 12a7f5839..bacb3a719 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -852,7 +852,7 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * b ep_state->busy = 0; ep_state->claimed = 0; TU_LOG1("Failed\r\n"); - TU_BREAKPOINT(); +// TU_BREAKPOINT(); return false; } } diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index d644390da..56d3aea45 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -405,45 +405,46 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { return false; } -tusb_speed_t handle_connect_irq(uint8_t rhport) { +static void handle_connect_irq(uint8_t rhport) { uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, true); uint8_t const jk = hrsl & (HRSL_JSTATUS | HRSL_KSTATUS); - tusb_speed_t speed; uint8_t new_mode = MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST; + TU_LOG2_HEX(jk); switch(jk) { - case 0x00: - // SEO is disconnected - speed = TUSB_SPEED_INVALID; - break; - - case (HRSL_JSTATUS | HRSL_KSTATUS): - // SE1 is illegal - speed = TUSB_SPEED_INVALID; + case 0x00: // SEO is disconnected + case (HRSL_JSTATUS | HRSL_KSTATUS): // SE1 is illegal + mode_write(rhport, new_mode, true); + hcd_event_device_remove(rhport, true); break; default: { - // Low speed if (LS = 1 and J-state) or (LS = 0 and K-State) - uint8_t const mode = reg_read(rhport, MODE_ADDR, true); - uint8_t const ls_bit = mode & MODE_LOWSPEED; - - if ( (ls_bit && (jk == HRSL_JSTATUS)) || (!ls_bit && (jk == HRSL_KSTATUS)) ) { - speed = TUSB_SPEED_LOW; - new_mode |= MODE_LOWSPEED; - } else { - speed = TUSB_SPEED_FULL; + // Bus Reset also cause CONDET IRQ, skip if we are already connected and doing bus reset + if ((_hcd_data.hirq & HIRQ_BUSEVENT_IRQ) && (_hcd_data.mode & MODE_SOFKAENAB)) { + break; } - new_mode |= MODE_SOFKAENAB; // enable SOF since there is new device + // Low speed if (LS = 1 and J-state) or (LS = 0 and K-State) + // However, since we are always in full speed mode, we can just check J-state + if (jk == HRSL_KSTATUS) { + new_mode |= MODE_LOWSPEED; + TU_LOG3("Low speed\n"); + }else { + TU_LOG3("Full speed\n"); + } + new_mode |= MODE_SOFKAENAB; + mode_write(rhport, new_mode, true); + + // FIXME multiple MAX3421 rootdevice address is not 1 + uint8_t const daddr = 1; + free_ep(daddr); + + hcd_event_device_attach(rhport, true); break; } } - - mode_write(rhport, new_mode, true); - TU_LOG2_INT(speed); - return speed; } // Initialize controller to host mode @@ -500,8 +501,9 @@ bool hcd_init(uint8_t rhport) { // Enable USB interrupt // Not actually enable GPIO interrupt, just set variable to prevent handler to process void hcd_int_enable (uint8_t rhport) { +// tuh_max3421e_int_api(rhport, true); + (void) rhport; - // tuh_max3421e_int_api(rhport, true); if (_hcd_data.intr_disable_count) { _hcd_data.intr_disable_count--; } @@ -510,8 +512,8 @@ void hcd_int_enable (uint8_t rhport) { // Disable USB interrupt // Not actually disable GPIO interrupt, just set variable to prevent handler to process void hcd_int_disable(uint8_t rhport) { - (void) rhport; //tuh_max3421e_int_api(rhport, false); + (void) rhport; _hcd_data.intr_disable_count++; } @@ -534,20 +536,12 @@ bool hcd_port_connect_status(uint8_t rhport) { // Reset USB bus on the port. Return immediately, bus reset sequence may not be complete. // Some port would require hcd_port_reset_end() to be invoked after 10ms to complete the reset sequence. void hcd_port_reset(uint8_t rhport) { - // Bus reset will also trigger CONDET IRQ, disable it - uint8_t const hien = DEFAULT_HIEN & ~HIRQ_CONDET_IRQ; - hien_write(rhport, hien, false); - reg_write(rhport, HCTL_ADDR, HCTL_BUSRST, false); } // Complete bus reset sequence, may be required by some controllers void hcd_port_reset_end(uint8_t rhport) { reg_write(rhport, HCTL_ADDR, 0, false); - - // Bus reset will also trigger CONDET IRQ, clear and re-enable it after reset - hirq_write(rhport, HIRQ_CONDET_IRQ, false); - hien_write(rhport, DEFAULT_HIEN, false); } // Get port link speed @@ -660,7 +654,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf uint8_t const ep_dir = tu_edpt_dir(ep_addr); max3421_ep_t* ep = find_opened_ep(daddr, ep_num, ep_dir); - TU_ASSERT(ep); + TU_VERIFY(ep); // control transfer can switch direction ep->ep_dir = ep_dir; @@ -767,8 +761,6 @@ static void handle_xfer_done(uint8_t rhport) { TU_ASSERT(ep, ); xfer_result_t xfer_result; - -// TU_LOG3("HRSL: %02X\r\n", hrsl); switch(hresult) { case HRSL_SUCCESS: xfer_result = XFER_RESULT_SUCCESS; @@ -803,6 +795,7 @@ static void handle_xfer_done(uint8_t rhport) { return; default: + TU_LOG3("HRSL: %02X\r\n", hrsl); xfer_result = XFER_RESULT_FAILED; break; } @@ -875,30 +868,30 @@ void hcd_int_handler(uint8_t rhport) { if (!hirq) return; // print_hirq(hirq); +// uint8_t hirq = reg_read(rhport, HIRQ_ADDR, true); + if (hirq & HIRQ_FRAME_IRQ) { _hcd_data.frame_count++; } + #if 1 // interrupt is disabled, only ack FRAME IRQ and skip the rest if (_hcd_data.intr_disable_count) { if (hirq & HIRQ_FRAME_IRQ) { hirq_write(rhport, HIRQ_FRAME_IRQ, true); } + + if ((hirq & HIRQ_CONDET_IRQ) && !(_hcd_data.mode & MODE_SOFKAENAB)) { + // connection when interrupt is disabled + TU_LOG3_INT(_hcd_data.intr_disable_count); + return; + } return; } + #endif if (hirq & HIRQ_CONDET_IRQ) { - tusb_speed_t speed = handle_connect_irq(rhport); - - if (speed == TUSB_SPEED_INVALID) { - hcd_event_device_remove(rhport, true); - }else { - // FIXME multiple MAX3421 rootdevice address is not 1 - uint8_t const daddr = 1; - free_ep(daddr); - - hcd_event_device_attach(rhport, true); - } + handle_connect_irq(rhport); } // queue more transfer in handle_xfer_done() can cause hirq to be set again while external IRQ may not catch and/or From ed0a233d4830baa8a767fcc20dcbfedbb09b7b41 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 31 Aug 2023 21:28:27 +0700 Subject: [PATCH 25/71] vastly improve attach/detach device, still have issue where thing is still hanged occasionally. --- src/portable/analog/max3421/hcd_max3421.c | 126 ++++++++++++---------- 1 file changed, 70 insertions(+), 56 deletions(-) diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 56d3aea45..c61389cb9 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -215,6 +215,9 @@ void tuh_max3421_spi_cs_api(uint8_t rhport, bool active); bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len); void tuh_max3421e_int_api(uint8_t rhport, bool enabled); +static void handle_connect_irq(uint8_t rhport, bool in_isr); +static inline void hirq_write(uint8_t rhport, uint8_t data, bool in_isr); + //--------------------------------------------------------------------+ // SPI Helper //--------------------------------------------------------------------+ @@ -238,6 +241,14 @@ static void max3421_spi_unlock(uint8_t rhport, bool in_isr) { if (!in_isr) { tuh_max3421e_int_api(rhport, true); (void) osal_mutex_unlock(_hcd_data.spi_mutex); + + // when re-enable interrupt, we may miss INTR edge (usually via GPIO detection interrupt). + // It would be ok if we are operating since SOF will re-trigger interrupt. + // However, for CONDET_IRQ i.e host not operating therefore we need to manually handle it here. + if (_hcd_data.hirq & HIRQ_CONDET_IRQ) { + handle_connect_irq(rhport, false); + hirq_write(rhport, HIRQ_CONDET_IRQ, false); + } } } @@ -405,48 +416,6 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { return false; } -static void handle_connect_irq(uint8_t rhport) { - uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, true); - uint8_t const jk = hrsl & (HRSL_JSTATUS | HRSL_KSTATUS); - - uint8_t new_mode = MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST; - TU_LOG2_HEX(jk); - - switch(jk) { - case 0x00: // SEO is disconnected - case (HRSL_JSTATUS | HRSL_KSTATUS): // SE1 is illegal - mode_write(rhport, new_mode, true); - hcd_event_device_remove(rhport, true); - break; - - default: { - // Bus Reset also cause CONDET IRQ, skip if we are already connected and doing bus reset - if ((_hcd_data.hirq & HIRQ_BUSEVENT_IRQ) && (_hcd_data.mode & MODE_SOFKAENAB)) { - break; - } - - // Low speed if (LS = 1 and J-state) or (LS = 0 and K-State) - // However, since we are always in full speed mode, we can just check J-state - if (jk == HRSL_KSTATUS) { - new_mode |= MODE_LOWSPEED; - TU_LOG3("Low speed\n"); - }else { - TU_LOG3("Full speed\n"); - } - new_mode |= MODE_SOFKAENAB; - mode_write(rhport, new_mode, true); - - // FIXME multiple MAX3421 rootdevice address is not 1 - uint8_t const daddr = 1; - free_ep(daddr); - - hcd_event_device_attach(rhport, true); - - break; - } - } -} - // Initialize controller to host mode bool hcd_init(uint8_t rhport) { (void) rhport; @@ -507,6 +476,14 @@ void hcd_int_enable (uint8_t rhport) { if (_hcd_data.intr_disable_count) { _hcd_data.intr_disable_count--; } + + // when re-enable interrupt, we may miss INTR edge (usually via GPIO detection interrupt). + // It would be ok if we are operating since SOF will re-trigger interrupt. + // However, for CONDET_IRQ i.e host not operating therefore we need to manually handle it here. +// if (_hcd_data.hirq & HIRQ_CONDET_IRQ) { +// handle_connect_irq(rhport, false); +// hirq_write(rhport, HIRQ_CONDET_IRQ, false); +// } } // Disable USB interrupt @@ -726,6 +703,54 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { // Interrupt Handler //--------------------------------------------------------------------+ +static void handle_connect_irq(uint8_t rhport, bool in_isr) { + uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, in_isr); + uint8_t const jk = hrsl & (HRSL_JSTATUS | HRSL_KSTATUS); + + uint8_t new_mode = MODE_DPPULLDN | MODE_DMPULLDN | MODE_HOST; + TU_LOG2_HEX(jk); + + switch(jk) { + case 0x00: // SEO is disconnected + case (HRSL_JSTATUS | HRSL_KSTATUS): // SE1 is illegal + mode_write(rhport, new_mode, in_isr); + + // port reset anyway, this will help to stable bus signal for next connection + reg_write(rhport, HCTL_ADDR, HCTL_BUSRST, in_isr); + + hcd_event_device_remove(rhport, in_isr); + + reg_write(rhport, HCTL_ADDR, 0, in_isr); + break; + + default: { + // Bus Reset also cause CONDET IRQ, skip if we are already connected and doing bus reset + if ((_hcd_data.hirq & HIRQ_BUSEVENT_IRQ) && (_hcd_data.mode & MODE_SOFKAENAB)) { + break; + } + + // Low speed if (LS = 1 and J-state) or (LS = 0 and K-State) + // However, since we are always in full speed mode, we can just check J-state + if (jk == HRSL_KSTATUS) { + new_mode |= MODE_LOWSPEED; + TU_LOG3("Low speed\n"); + }else { + TU_LOG3("Full speed\n"); + } + new_mode |= MODE_SOFKAENAB; + mode_write(rhport, new_mode, in_isr); + + // FIXME multiple MAX3421 rootdevice address is not 1 + uint8_t const daddr = 1; + free_ep(daddr); + + hcd_event_device_attach(rhport, in_isr); + + break; + } + } +} + static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t result, uint8_t hrsl) { uint8_t const ep_addr = tu_edpt_addr(ep->ep_num, ep->ep_dir); @@ -758,7 +783,7 @@ static void handle_xfer_done(uint8_t rhport) { uint8_t const ep_dir = ((hxfr_type & HXFR_SETUP) || (hxfr_type & HXFR_OUT_NIN)) ? 0 : 1; max3421_ep_t *ep = find_opened_ep(_hcd_data.peraddr, ep_num, ep_dir); - TU_ASSERT(ep, ); + TU_VERIFY(ep, ); xfer_result_t xfer_result; switch(hresult) { @@ -857,7 +882,6 @@ void print_hirq(uint8_t hirq) { TU_LOG3("\r\n"); } - #else #define print_hirq(hirq) #endif @@ -868,30 +892,20 @@ void hcd_int_handler(uint8_t rhport) { if (!hirq) return; // print_hirq(hirq); -// uint8_t hirq = reg_read(rhport, HIRQ_ADDR, true); - if (hirq & HIRQ_FRAME_IRQ) { _hcd_data.frame_count++; } - #if 1 - // interrupt is disabled, only ack FRAME IRQ and skip the rest + // interrupt is disabled by usbh task: only ack FRAME IRQ and skip the rest if (_hcd_data.intr_disable_count) { if (hirq & HIRQ_FRAME_IRQ) { hirq_write(rhport, HIRQ_FRAME_IRQ, true); } - - if ((hirq & HIRQ_CONDET_IRQ) && !(_hcd_data.mode & MODE_SOFKAENAB)) { - // connection when interrupt is disabled - TU_LOG3_INT(_hcd_data.intr_disable_count); - return; - } return; } - #endif if (hirq & HIRQ_CONDET_IRQ) { - handle_connect_irq(rhport); + handle_connect_irq(rhport, true); } // queue more transfer in handle_xfer_done() can cause hirq to be set again while external IRQ may not catch and/or From 1b9108ea0dc237835e801d26cc7eef052acad987 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 6 Sep 2023 17:11:35 +0700 Subject: [PATCH 26/71] minor debug clean up --- src/common/tusb_common.h | 6 ++---- src/common/tusb_debug.h | 37 ++++++++++++++----------------------- src/device/usbd.c | 2 +- src/device/usbd_pvt.h | 15 ++++++--------- src/host/usbh.c | 6 ++---- 5 files changed, 25 insertions(+), 41 deletions(-) diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index c303c6eaf..6fffed11c 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -122,13 +122,11 @@ TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, c //------------- Bytes -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) { return ( ((uint32_t) b3) << 24) | ( ((uint32_t) b2) << 16) | ( ((uint32_t) b1) << 8) | b0; } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) -{ +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_u16(uint8_t high, uint8_t low) { return (uint16_t) ((((uint16_t) high) << 8) | low); } diff --git a/src/common/tusb_debug.h b/src/common/tusb_debug.h index 36507041f..99176c02a 100644 --- a/src/common/tusb_debug.h +++ b/src/common/tusb_debug.h @@ -58,16 +58,14 @@ void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); #define tu_printf printf #endif -static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize) -{ +static inline void tu_print_buf(uint8_t const* buf, uint32_t bufsize) { for(uint32_t i=0; i= 2 #define TU_LOG2 TU_LOG1 #define TU_LOG2_MEM TU_LOG1_MEM - #define TU_LOG2_ARR TU_LOG1_ARR - #define TU_LOG2_PTR TU_LOG1_PTR + #define TU_LOG2_BUF TU_LOG1_BUF #define TU_LOG2_INT TU_LOG1_INT #define TU_LOG2_HEX TU_LOG1_HEX #endif @@ -95,30 +91,25 @@ static inline void tu_print_arr(uint8_t const* buf, uint32_t bufsize) #if CFG_TUSB_DEBUG >= 3 #define TU_LOG3 TU_LOG1 #define TU_LOG3_MEM TU_LOG1_MEM - #define TU_LOG3_ARR TU_LOG1_ARR - #define TU_LOG3_PTR TU_LOG1_PTR + #define TU_LOG3_BUF TU_LOG1_BUF #define TU_LOG3_INT TU_LOG1_INT #define TU_LOG3_HEX TU_LOG1_HEX #endif -typedef struct -{ +typedef struct { uint32_t key; const char* data; } tu_lookup_entry_t; -typedef struct -{ +typedef struct { uint16_t count; tu_lookup_entry_t const* items; } tu_lookup_table_t; -static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) -{ +static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) { tu_static char not_found[11]; - for(uint16_t i=0; icount; i++) - { + for(uint16_t i=0; icount; i++) { if (p_table->items[i].key == key) return p_table->items[i].data; } @@ -133,7 +124,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #ifndef TU_LOG #define TU_LOG(n, ...) #define TU_LOG_MEM(n, ...) - #define TU_LOG_PTR(n, ...) + #define TU_LOG_BUF(n, ...) #define TU_LOG_INT(n, ...) #define TU_LOG_HEX(n, ...) #define TU_LOG_LOCATION() @@ -144,14 +135,14 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #define TU_LOG0(...) #define TU_LOG0_MEM(...) -#define TU_LOG0_PTR(...) +#define TU_LOG0_BUF(...) #define TU_LOG0_INT(...) #define TU_LOG0_HEX(...) #ifndef TU_LOG1 #define TU_LOG1(...) #define TU_LOG1_MEM(...) - #define TU_LOG1_PTR(...) + #define TU_LOG1_BUF(...) #define TU_LOG1_INT(...) #define TU_LOG1_HEX(...) #endif @@ -159,7 +150,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #ifndef TU_LOG2 #define TU_LOG2(...) #define TU_LOG2_MEM(...) - #define TU_LOG2_PTR(...) + #define TU_LOG2_BUF(...) #define TU_LOG2_INT(...) #define TU_LOG2_HEX(...) #endif @@ -167,7 +158,7 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 #ifndef TU_LOG3 #define TU_LOG3(...) #define TU_LOG3_MEM(...) - #define TU_LOG3_PTR(...) + #define TU_LOG3_BUF(...) #define TU_LOG3_INT(...) #define TU_LOG3_HEX(...) #endif diff --git a/src/device/usbd.c b/src/device/usbd.c index f0d9fba52..50941c46f 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -506,7 +506,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) break; case DCD_EVENT_SETUP_RECEIVED: - TU_LOG_PTR(CFG_TUD_LOG_LEVEL, &event.setup_received); + TU_LOG_BUF(CFG_TUD_LOG_LEVEL, &event.setup_received, 8); TU_LOG_USBD("\r\n"); // Mark as connected after receiving 1st setup packet. diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 16585167f..153be7cee 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -23,8 +23,8 @@ * * This file is part of the TinyUSB stack. */ -#ifndef USBD_PVT_H_ -#define USBD_PVT_H_ +#ifndef _TUSB_USBD_PVT_H_ +#define _TUSB_USBD_PVT_H_ #include "osal/osal.h" #include "common/tusb_fifo.h" @@ -44,8 +44,7 @@ // Class Driver API //--------------------------------------------------------------------+ -typedef struct -{ +typedef struct { #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL char const* name; #endif @@ -111,8 +110,7 @@ bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endp // Check if endpoint is ready (not busy and not stalled) TU_ATTR_ALWAYS_INLINE static inline -bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) -{ +bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) { return !usbd_edpt_busy(rhport, ep_addr) && !usbd_edpt_stalled(rhport, ep_addr); } @@ -124,11 +122,10 @@ void usbd_sof_enable(uint8_t rhport, bool en); *------------------------------------------------------------------*/ bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in); -void usbd_defer_func( osal_task_func_t func, void* param, bool in_isr ); - +void usbd_defer_func(osal_task_func_t func, void *param, bool in_isr); #ifdef __cplusplus } #endif -#endif /* USBD_PVT_H_ */ +#endif diff --git a/src/host/usbh.c b/src/host/usbh.c index bacb3a719..e60e680c2 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -583,7 +583,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) { TU_LOG_USBH("[%u:%u] %s: ", rhport, daddr, (xfer->setup->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && xfer->setup->bRequest <= TUSB_REQ_SYNCH_FRAME) ? tu_str_std_request[xfer->setup->bRequest] : "Class Request"); - TU_LOG_PTR(CFG_TUH_LOG_LEVEL, xfer->setup); + TU_LOG_BUF(CFG_TUH_LOG_LEVEL, xfer->setup, 8); TU_LOG_USBH("\r\n"); if (xfer->complete_cb) { @@ -660,10 +660,8 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result if (XFER_RESULT_SUCCESS != result) { TU_LOG1("[%u:%u] Control %s, xferred_bytes = %lu\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes); - #if CFG_TUSB_DEBUG == 1 - TU_LOG1_PTR(request); + TU_LOG1_BUF(request, 8); TU_LOG1("\r\n"); - #endif // terminate transfer if any stage failed _xfer_complete(dev_addr, result); From 21ab40bab2e2fee28fa595f648a17944696c3d65 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 7 Sep 2023 12:38:18 +0700 Subject: [PATCH 27/71] - wrap up hcd max3421, work well with nrf52840 - also add usbh_defer_func() --- hw/bsp/nrf/family.c | 7 +++-- src/host/usbh.c | 26 +++++++++------- src/host/usbh_pvt.h | 10 +++---- src/portable/analog/max3421/hcd_max3421.c | 36 ++--------------------- 4 files changed, 27 insertions(+), 52 deletions(-) diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 7358458ce..39ce179e8 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -109,10 +109,12 @@ void max3421e_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { void tuh_max3421e_int_api(uint8_t rhport, bool enabled) { (void) rhport; + // use NVIC_Enable/Disable instead since nrfx_gpiote_trigger_enable/disable clear pending and can miss interrupt + // when disabled if (enabled) { - nrfx_gpiote_trigger_enable(MAX3241E_INTR_PIN, true); + NVIC_EnableIRQ(GPIOTE_IRQn); } else { - nrfx_gpiote_trigger_disable(MAX3241E_INTR_PIN); + NVIC_DisableIRQ(GPIOTE_IRQn); } } @@ -266,6 +268,7 @@ void board_init(void) { in_config.pull = NRF_GPIO_PIN_PULLUP; nrfx_gpiote_in_init(MAX3241E_INTR_PIN, &in_config, max3421e_int_handler); + nrfx_gpiote_trigger_enable(MAX3241E_INTR_PIN, true); #endif } diff --git a/src/host/usbh.c b/src/host/usbh.c index e60e680c2..e332f35cc 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -753,29 +753,33 @@ bool tuh_edpt_abort_xfer(uint8_t daddr, uint8_t ep_addr) { // USBH API For Class Driver //--------------------------------------------------------------------+ -uint8_t usbh_get_rhport(uint8_t dev_addr) -{ - usbh_device_t* dev = get_device(dev_addr); +uint8_t usbh_get_rhport(uint8_t dev_addr) { + usbh_device_t *dev = get_device(dev_addr); return dev ? dev->rhport : _dev0.rhport; } -uint8_t* usbh_get_enum_buf(void) -{ +uint8_t *usbh_get_enum_buf(void) { return _usbh_ctrl_buf; } -void usbh_int_set(bool enabled) -{ +void usbh_int_set(bool enabled) { // TODO all host controller if multiple are used since they shared the same event queue - if (enabled) - { + if (enabled) { hcd_int_enable(_usbh_controller); - }else - { + } else { hcd_int_disable(_usbh_controller); } } +void usbh_defer_func(osal_task_func_t func, void *param, bool in_isr) { + hcd_event_t event = { 0 }; + event.event_id = USBH_EVENT_FUNC_CALL; + event.func_call.func = func; + event.func_call.param = param; + + osal_queue_send(_usbh_q, &event, in_isr); +} + //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h index 0b58a91bc..2b61a77db 100644 --- a/src/host/usbh_pvt.h +++ b/src/host/usbh_pvt.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_USBH_CLASSDRIVER_H_ -#define _TUSB_USBH_CLASSDRIVER_H_ +#ifndef _TUSB_USBH_PVT_H_ +#define _TUSB_USBH_PVT_H_ #include "osal/osal.h" #include "common/tusb_fifo.h" @@ -76,6 +76,8 @@ uint8_t* usbh_get_enum_buf(void); void usbh_int_set(bool enabled); +void usbh_defer_func(osal_task_func_t func, void *param, bool in_isr); + //--------------------------------------------------------------------+ // USBH Endpoint API //--------------------------------------------------------------------+ @@ -85,12 +87,10 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * b tuh_xfer_cb_t complete_cb, uintptr_t user_data); TU_ATTR_ALWAYS_INLINE -static inline bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) -{ +static inline bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) { return usbh_edpt_xfer_with_callback(dev_addr, ep_addr, buffer, total_bytes, NULL, 0); } - // Claim an endpoint before submitting a transfer. // If caller does not make any transfer, it must release endpoint for others. bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr); diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index c61389cb9..95cf5516e 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -194,7 +194,6 @@ typedef struct { uint8_t hxfr; atomic_flag busy; // busy transferring - volatile uint8_t intr_disable_count; volatile uint16_t frame_count; max3421_ep_t ep[CFG_TUH_MAX3421_ENDPOINT_TOTAL]; // [0] is reserved for addr0 @@ -241,14 +240,6 @@ static void max3421_spi_unlock(uint8_t rhport, bool in_isr) { if (!in_isr) { tuh_max3421e_int_api(rhport, true); (void) osal_mutex_unlock(_hcd_data.spi_mutex); - - // when re-enable interrupt, we may miss INTR edge (usually via GPIO detection interrupt). - // It would be ok if we are operating since SOF will re-trigger interrupt. - // However, for CONDET_IRQ i.e host not operating therefore we need to manually handle it here. - if (_hcd_data.hirq & HIRQ_CONDET_IRQ) { - handle_connect_irq(rhport, false); - hirq_write(rhport, HIRQ_CONDET_IRQ, false); - } } } @@ -470,28 +461,13 @@ bool hcd_init(uint8_t rhport) { // Enable USB interrupt // Not actually enable GPIO interrupt, just set variable to prevent handler to process void hcd_int_enable (uint8_t rhport) { -// tuh_max3421e_int_api(rhport, true); - - (void) rhport; - if (_hcd_data.intr_disable_count) { - _hcd_data.intr_disable_count--; - } - - // when re-enable interrupt, we may miss INTR edge (usually via GPIO detection interrupt). - // It would be ok if we are operating since SOF will re-trigger interrupt. - // However, for CONDET_IRQ i.e host not operating therefore we need to manually handle it here. -// if (_hcd_data.hirq & HIRQ_CONDET_IRQ) { -// handle_connect_irq(rhport, false); -// hirq_write(rhport, HIRQ_CONDET_IRQ, false); -// } + tuh_max3421e_int_api(rhport, true); } // Disable USB interrupt // Not actually disable GPIO interrupt, just set variable to prevent handler to process void hcd_int_disable(uint8_t rhport) { - //tuh_max3421e_int_api(rhport, false); - (void) rhport; - _hcd_data.intr_disable_count++; + tuh_max3421e_int_api(rhport, false); } // Get frame number (1ms) @@ -896,14 +872,6 @@ void hcd_int_handler(uint8_t rhport) { _hcd_data.frame_count++; } - // interrupt is disabled by usbh task: only ack FRAME IRQ and skip the rest - if (_hcd_data.intr_disable_count) { - if (hirq & HIRQ_FRAME_IRQ) { - hirq_write(rhport, HIRQ_FRAME_IRQ, true); - } - return; - } - if (hirq & HIRQ_CONDET_IRQ) { handle_connect_irq(rhport, true); } From bb5d43e9c5c909a1becc1224c768d3aa1a09b051 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 7 Sep 2023 15:31:43 +0700 Subject: [PATCH 28/71] add samd51 to cmake --- .github/workflows/build_arm.yml | 2 +- .github/workflows/cmake_arm.yml | 1 + .idea/cmake.xml | 5 +- hw/bsp/samd51/FreeRTOSConfig/FreeRTOSConfig.h | 165 ++++++++++++++++++ .../boards/feather_m4_express/board.cmake | 8 + hw/bsp/samd51/boards/itsybitsy_m4/board.cmake | 8 + .../boards/metro_m4_express/board.cmake | 8 + hw/bsp/samd51/boards/pybadge/board.cmake | 8 + hw/bsp/samd51/boards/pyportal/board.cmake | 8 + hw/bsp/samd51/family.c | 11 ++ hw/bsp/samd51/family.cmake | 104 +++++++++++ 11 files changed, 325 insertions(+), 3 deletions(-) create mode 100644 hw/bsp/samd51/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/samd51/boards/feather_m4_express/board.cmake create mode 100644 hw/bsp/samd51/boards/itsybitsy_m4/board.cmake create mode 100644 hw/bsp/samd51/boards/metro_m4_express/board.cmake create mode 100644 hw/bsp/samd51/boards/pybadge/board.cmake create mode 100644 hw/bsp/samd51/boards/pyportal/board.cmake create mode 100644 hw/bsp/samd51/family.cmake diff --git a/.github/workflows/build_arm.yml b/.github/workflows/build_arm.yml index 2621e7372..377fc44d9 100644 --- a/.github/workflows/build_arm.yml +++ b/.github/workflows/build_arm.yml @@ -40,7 +40,7 @@ jobs: - 'mm32 msp432e4' - 'nrf' - 'samd11 samd21' - - 'samd51 same5x' + - 'same5x' - 'saml2x' - 'stm32f2 stm32f3' - 'stm32l0 stm32u5 stm32wb' diff --git a/.github/workflows/cmake_arm.yml b/.github/workflows/cmake_arm.yml index 8eeae928c..6f7d024bd 100644 --- a/.github/workflows/cmake_arm.yml +++ b/.github/workflows/cmake_arm.yml @@ -40,6 +40,7 @@ jobs: - 'mcx' - 'ra' - 'rp2040' + - 'samd51' - 'stm32f0' - 'stm32f1' - 'stm32f4' diff --git a/.idea/cmake.xml b/.idea/cmake.xml index 8ee7f09a0..a060f18eb 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -30,8 +30,8 @@ - - + + @@ -52,6 +52,7 @@ + \ No newline at end of file diff --git a/hw/bsp/samd51/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/samd51/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..e3ee529cf --- /dev/null +++ b/hw/bsp/samd51/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,165 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + #include "sam.h" +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* Define to trap errors during development. */ +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 +#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) + #define configASSERT(_exp) \ + do {\ + if ( !(_exp) ) { \ + volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ + if ( (*ARM_CM_DHCSR) & 1UL ) { /* Only halt mcu if debugger is attached */ \ + taskDISABLE_INTERRUPTS(); \ + __asm("BKPT #0\n"); \ + }\ + }\ + } while(0) +#else + #define configASSERT( x ) +#endif + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +#define configPRIO_BITS 3 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< Date: Thu, 7 Sep 2023 16:58:40 +0700 Subject: [PATCH 29/71] add cmake support for samd21. update ci cmake --- .github/workflows/build_arm.yml | 4 +- .github/workflows/cmake_arm.yml | 1 + .idea/cmake.xml | 3 +- hw/bsp/samd21/FreeRTOSConfig/FreeRTOSConfig.h | 165 ++++++++++++++++++ .../samd21/boards/atsamd21_xpro/board.cmake | 9 + .../circuitplayground_express/board.cmake | 9 + .../samd21/boards/curiosity_nano/board.cmake | 10 ++ hw/bsp/samd21/boards/cynthion_d21/board.cmake | 12 ++ .../boards/feather_m0_express/board.cmake | 9 + hw/bsp/samd21/boards/itsybitsy_m0/board.cmake | 9 + .../boards/metro_m0_express/board.cmake | 9 + hw/bsp/samd21/boards/qtpy/board.cmake | 9 + .../samd21/boards/seeeduino_xiao/board.cmake | 9 + hw/bsp/samd21/boards/trinket_m0/board.cmake | 9 + hw/bsp/samd21/family.c | 10 ++ hw/bsp/samd21/family.cmake | 105 +++++++++++ 16 files changed, 378 insertions(+), 4 deletions(-) create mode 100644 hw/bsp/samd21/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/samd21/boards/atsamd21_xpro/board.cmake create mode 100644 hw/bsp/samd21/boards/circuitplayground_express/board.cmake create mode 100644 hw/bsp/samd21/boards/curiosity_nano/board.cmake create mode 100644 hw/bsp/samd21/boards/cynthion_d21/board.cmake create mode 100644 hw/bsp/samd21/boards/feather_m0_express/board.cmake create mode 100644 hw/bsp/samd21/boards/itsybitsy_m0/board.cmake create mode 100644 hw/bsp/samd21/boards/metro_m0_express/board.cmake create mode 100644 hw/bsp/samd21/boards/qtpy/board.cmake create mode 100644 hw/bsp/samd21/boards/seeeduino_xiao/board.cmake create mode 100644 hw/bsp/samd21/boards/trinket_m0/board.cmake create mode 100644 hw/bsp/samd21/family.cmake diff --git a/.github/workflows/build_arm.yml b/.github/workflows/build_arm.yml index 377fc44d9..70385bc1b 100644 --- a/.github/workflows/build_arm.yml +++ b/.github/workflows/build_arm.yml @@ -39,9 +39,7 @@ jobs: - 'lpc51 lpc54' - 'mm32 msp432e4' - 'nrf' - - 'samd11 samd21' - - 'same5x' - - 'saml2x' + - 'samd11 same5x saml2x' - 'stm32f2 stm32f3' - 'stm32l0 stm32u5 stm32wb' - 'tm4c123 xmc4000' diff --git a/.github/workflows/cmake_arm.yml b/.github/workflows/cmake_arm.yml index 6f7d024bd..e3a00f9c5 100644 --- a/.github/workflows/cmake_arm.yml +++ b/.github/workflows/cmake_arm.yml @@ -40,6 +40,7 @@ jobs: - 'mcx' - 'ra' - 'rp2040' + - 'samd21' - 'samd51' - 'stm32f0' - 'stm32f1' diff --git a/.idea/cmake.xml b/.idea/cmake.xml index a060f18eb..15dd85f93 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -52,7 +52,8 @@ - + + \ No newline at end of file diff --git a/hw/bsp/samd21/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/samd21/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..02e868741 --- /dev/null +++ b/hw/bsp/samd21/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,165 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + #include "sam.h" +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* Define to trap errors during development. */ +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 +#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) + #define configASSERT(_exp) \ + do {\ + if ( !(_exp) ) { \ + volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ + if ( (*ARM_CM_DHCSR) & 1UL ) { /* Only halt mcu if debugger is attached */ \ + taskDISABLE_INTERRUPTS(); \ + __asm("BKPT #0\n"); \ + }\ + }\ + } while(0) +#else + #define configASSERT( x ) +#endif + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +#define configPRIO_BITS 2 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< Date: Thu, 7 Sep 2023 17:09:25 +0700 Subject: [PATCH 30/71] fix ci --- .idea/cmake.xml | 4 ++-- hw/bsp/samd21/boards/cynthion_d21/board.cmake | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.idea/cmake.xml b/.idea/cmake.xml index 15dd85f93..2a7babf3f 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -52,8 +52,8 @@ - - + + \ No newline at end of file diff --git a/hw/bsp/samd21/boards/cynthion_d21/board.cmake b/hw/bsp/samd21/boards/cynthion_d21/board.cmake index 67aef67ad..89e821edd 100644 --- a/hw/bsp/samd21/boards/cynthion_d21/board.cmake +++ b/hw/bsp/samd21/boards/cynthion_d21/board.cmake @@ -7,6 +7,6 @@ function(update_board TARGET) CFG_EXAMPLE_VIDEO_READONLY ) target_link_options(${TARGET} PUBLIC - --defsym=BOOTLOADER_SIZE=0x800 + "LINKER:--defsym=BOOTLOADER_SIZE=0x800" ) endfunction() From d3c08ecc3ab53b5e1b4fbcb18eb2aab78a5b840e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 7 Sep 2023 17:20:07 +0700 Subject: [PATCH 31/71] more ci fix --- hw/bsp/samd21/boards/cynthion_d21/board.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/bsp/samd21/boards/cynthion_d21/board.cmake b/hw/bsp/samd21/boards/cynthion_d21/board.cmake index 89e821edd..fb54b7561 100644 --- a/hw/bsp/samd21/boards/cynthion_d21/board.cmake +++ b/hw/bsp/samd21/boards/cynthion_d21/board.cmake @@ -1,5 +1,5 @@ set(JLINK_DEVICE ATSAMD21G18) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/${BOARD}.ld) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/samd21g18a_flash.ld) function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC From 7ce4cfa638a86bfabd7ce8147ea5468d69c1af21 Mon Sep 17 00:00:00 2001 From: maidnl Date: Fri, 8 Sep 2023 10:12:03 +0200 Subject: [PATCH 32/71] renesas: added wait function for IN transaction This fixes a problem found on MSD class where data read from from disks were sometimes partially overwritten by the status MSD message ("USBS..."). The function introduced wait for the hw fifo pipe to be empty, that prevent that new writing in the fife overwrite data which are not yet be transmitted by hw. --- src/portable/renesas/rusb2/dcd_rusb2.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index 3ec1b70b5..68ef5890f 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -266,6 +266,13 @@ static void pipe_read_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void tu_fifo_advance_write_pointer(f, count); } + +static void wait_pipe_fifo_empty(rusb2_reg_t* rusb, uint8_t num) { + TU_ASSERT(num); + while( (rusb->PIPE_CTR[num-1] & RUSB2_PIPE_CTR_INBUFM_Msk) > 0 ) {} +} + + //--------------------------------------------------------------------+ // Pipe Transfer //--------------------------------------------------------------------+ @@ -339,6 +346,7 @@ static bool pipe_xfer_in(rusb2_reg_t* rusb, unsigned num) const unsigned rem = pipe->remaining; if (!rem) { + wait_pipe_fifo_empty(rusb, num); pipe->buf = NULL; return true; } From bcc77a60e047837a82b0719ffa95a4d6f688468d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 Sep 2023 17:40:00 +0700 Subject: [PATCH 33/71] get spi working for metro m4 express --- hw/bsp/nrf/family.c | 73 +++--- hw/bsp/samd51/boards/metro_m4_express/board.h | 9 + hw/bsp/samd51/family.c | 231 ++++++++++++++---- hw/bsp/samd51/family.cmake | 1 + 4 files changed, 238 insertions(+), 76 deletions(-) diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 39ce179e8..47c765a96 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -102,40 +102,6 @@ void max3421e_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { tuh_int_handler(1); } - -//--------------------------------------------------------------------+ -// API: SPI transfer with MAX3421E, must be implemented by application -//--------------------------------------------------------------------+ -void tuh_max3421e_int_api(uint8_t rhport, bool enabled) { - (void) rhport; - - // use NVIC_Enable/Disable instead since nrfx_gpiote_trigger_enable/disable clear pending and can miss interrupt - // when disabled - if (enabled) { - NVIC_EnableIRQ(GPIOTE_IRQn); - } else { - NVIC_DisableIRQ(GPIOTE_IRQn); - } -} - -void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { - (void) rhport; - nrf_gpio_pin_write(MAX3421E_CS_PIN, active ? 0 : 1); -} - -bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { - (void) rhport; - - nrfx_spim_xfer_desc_t xfer = { - .p_tx_buffer = tx_buf, - .tx_length = tx_len, - .p_rx_buffer = rx_buf, - .rx_length = rx_len, - }; - - return (nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS); -} - #endif @@ -242,7 +208,7 @@ void board_init(void) { // manually manage CS nrf_gpio_cfg_output(MAX3421E_CS_PIN); - tuh_max3421_spi_cs_api(0, false); + nrf_gpio_pin_write(MAX3421E_CS_PIN, 1); // USB host using max3421e usb controller via SPI nrfx_spim_config_t cfg = { @@ -345,3 +311,40 @@ void nrf_error_cb(uint32_t id, uint32_t pc, uint32_t info) { (void) info; } #endif + +//--------------------------------------------------------------------+ +// API: SPI transfer with MAX3421E, must be implemented by application +//--------------------------------------------------------------------+ +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + +void tuh_max3421e_int_api(uint8_t rhport, bool enabled) { + (void) rhport; + + // use NVIC_Enable/Disable instead since nrfx_gpiote_trigger_enable/disable clear pending and can miss interrupt + // when disabled and re-enabled. + if (enabled) { + NVIC_EnableIRQ(GPIOTE_IRQn); + } else { + NVIC_DisableIRQ(GPIOTE_IRQn); + } +} + +void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { + (void) rhport; + nrf_gpio_pin_write(MAX3421E_CS_PIN, active ? 0 : 1); +} + +bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { + (void) rhport; + + nrfx_spim_xfer_desc_t xfer = { + .p_tx_buffer = tx_buf, + .tx_length = tx_len, + .p_rx_buffer = rx_buf, + .rx_length = rx_len, + }; + + return (nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS); +} + +#endif diff --git a/hw/bsp/samd51/boards/metro_m4_express/board.h b/hw/bsp/samd51/boards/metro_m4_express/board.h index 5d7734576..3441d03e9 100644 --- a/hw/bsp/samd51/boards/metro_m4_express/board.h +++ b/hw/bsp/samd51/boards/metro_m4_express/board.h @@ -43,6 +43,15 @@ #define UART_TX_PIN 23 #define UART_RX_PIN 22 +// SPI for USB host shield +#define MAX3421E_SERCOM SERCOM2 +#define MAX3421E_SCK_PIN 13 +#define MAX3421E_MOSI_PIN 12 +#define MAX3421E_MISO_PIN 14 +#define MAX3421E_CS_PIN 18 // D10 +#define MAX3241E_INTR_PIN 20 // D9 + + #ifdef __cplusplus } #endif diff --git a/hw/bsp/samd51/family.c b/hw/bsp/samd51/family.c index 2df9cbafb..45a9aa5e0 100644 --- a/hw/bsp/samd51/family.c +++ b/hw/bsp/samd51/family.c @@ -43,30 +43,6 @@ #pragma GCC diagnostic pop #endif - -//--------------------------------------------------------------------+ -// Forward USB interrupt events to TinyUSB IRQ Handler -//--------------------------------------------------------------------+ -void USB_0_Handler (void) -{ - tud_int_handler(0); -} - -void USB_1_Handler (void) -{ - tud_int_handler(0); -} - -void USB_2_Handler (void) -{ - tud_int_handler(0); -} - -void USB_3_Handler (void) -{ - tud_int_handler(0); -} - //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ @@ -77,8 +53,81 @@ void USB_3_Handler (void) /* Not referenced GCLKs, initialized last */ #define _GCLK_INIT_LAST (~_GCLK_INIT_1ST) -void board_init(void) +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_0_Handler(void) { + tud_int_handler(0); +} + +void USB_1_Handler(void) { + tud_int_handler(0); +} + +void USB_2_Handler(void) { + tud_int_handler(0); +} + +void USB_3_Handler(void) { + tud_int_handler(0); +} + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 +void max3421_init(void) { + //------------- SPI Init -------------// + + // Enable the APB clock for SERCOM2 + MCLK->APBBMASK.reg |= MCLK_APBBMASK_SERCOM2; + + // Configure GCLK for SERCOM2, initClockNVIC() + GCLK->PCHCTRL[SERCOM2_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); + GCLK->PCHCTRL[SERCOM2_GCLK_ID_SLOW].reg = GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); + + // Disable the SPI module + SERCOM2->SPI.CTRLA.bit.ENABLE = 0; + + // Reset the SPI module + SERCOM2->SPI.CTRLA.bit.SWRST = 1; + while (SERCOM2->SPI.SYNCBUSY.bit.SWRST); + + // Set up SPI in master mode, MSB first, SPI mode 0 + uint8_t const mosi_pad = 0; + uint8_t const miso_pad = 2; + SERCOM2->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE(3) | SERCOM_SPI_CTRLA_DOPO(mosi_pad) | SERCOM_SPI_CTRLA_DIPO(miso_pad); + + SERCOM2->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN; + while( SERCOM2->SPI.SYNCBUSY.bit.CTRLB == 1 ); + + // Set the baud rate + uint32_t baudrate = 4000000u; + SERCOM2->SPI.BAUD.reg = (uint8_t)(SystemCoreClock / (2 * baudrate) - 1); // Replace 1000000 with your desired baud rate + + // Configure PA12 as MOSI (PAD0), PA13 as SCK (PAD1), PA14 as MISO (PAD2) + // 2 function C: PIO_SERCOM + gpio_set_pin_direction(MAX3421E_SCK_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_pull_mode(MAX3421E_SCK_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421E_SCK_PIN, 2); + + gpio_set_pin_direction(MAX3421E_MOSI_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_pull_mode(MAX3421E_MOSI_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421E_MOSI_PIN, 2); + + gpio_set_pin_direction(MAX3421E_MISO_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(MAX3421E_MISO_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421E_MISO_PIN, 2); + + // Enable the SPI module + SERCOM2->SPI.CTRLA.bit.ENABLE = 1; + while (SERCOM2->SPI.SYNCBUSY.bit.ENABLE); +} +#endif + +void board_init(void) { // Clock init ( follow hpl_init.c ) hri_nvmctrl_set_CTRLA_RWS_bf(NVMCTRL, 0); @@ -104,7 +153,7 @@ void board_init(void) gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN); gpio_set_pin_pull_mode(BUTTON_PIN, GPIO_PULL_UP); -#if CFG_TUSB_OS == OPT_OS_FREERTOS +#if CFG_TUSB_OS == OPT_OS_FREERTOS // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) NVIC_SetPriority(USB_0_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); NVIC_SetPriority(USB_1_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); @@ -129,45 +178,145 @@ void board_init(void) gpio_set_pin_function(PIN_PA24, PINMUX_PA24H_USB_DM); gpio_set_pin_function(PIN_PA25, PINMUX_PA25H_USB_DP); + +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + // CS pin + gpio_set_pin_direction(MAX3421E_CS_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_level(MAX3421E_CS_PIN, 1); + + // SPI + max3421_init(); + + // INT pin with external interrupt + gpio_set_pin_direction(MAX3241E_INTR_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(MAX3241E_INTR_PIN, GPIO_PULL_UP); + + // Enable the APB clock for EIC (External Interrupt Controller) + MCLK->APBAMASK.reg |= MCLK_APBAMASK_EIC; + + // Configure GCLK for EIC + GCLK->PCHCTRL[EIC_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); + + // Configure PA20 as an input + PORT->Group[0].DIRCLR.reg = PORT_PA20; + PORT->Group[0].PINCFG[20].reg = PORT_PINCFG_INEN | PORT_PINCFG_PULLEN; + PORT->Group[0].OUTSET.reg = PORT_PA20; // Enable pull-up + + // Configure PA20 to use EIC + PORT->Group[0].PMUX[10].bit.PMUXE = MUX_PA20A_EIC_EXTINT4; + PORT->Group[0].PINCFG[20].bit.PMUXEN = 1; + + // Disable EIC + EIC->CTRLA.bit.ENABLE = 0; + while (EIC->SYNCBUSY.bit.ENABLE); + + // Configure EXTINT4 (PA20) to trigger on falling edge + EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE4_FALL; + + // Enable EXTINT4 + EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << 4); + + // Enable EIC + EIC->CTRLA.bit.ENABLE = 1; + while (EIC->SYNCBUSY.bit.ENABLE); + +#endif } //--------------------------------------------------------------------+ // Board porting API //--------------------------------------------------------------------+ -void board_led_write(bool state) -{ +void board_led_write(bool state) { gpio_set_pin_level(LED_PIN, state); } -uint32_t board_button_read(void) -{ +uint32_t board_button_read(void) { // button is active low return gpio_get_pin_level(BUTTON_PIN) ? 0 : 1; } -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; +int board_uart_read(uint8_t *buf, int len) { + (void) buf; + (void) len; return 0; } -int board_uart_write(void const * buf, int len) -{ - (void) buf; (void) len; +int board_uart_write(void const *buf, int len) { + (void) buf; + (void) len; return 0; } -#if CFG_TUSB_OS == OPT_OS_NONE +#if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; -void SysTick_Handler (void) -{ +void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) -{ +uint32_t board_millis(void) { return system_ticks; } + +//--------------------------------------------------------------------+ +// API: SPI transfer with MAX3421E, must be implemented by application +//--------------------------------------------------------------------+ +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + +void EIC_4_Handler(void) +{ + // Clear the interrupt flag + EIC->INTFLAG.reg = EIC_INTFLAG_EXTINT(1 << 4); + + // Call the TinyUSB interrupt handler + tuh_int_handler(1); +} + +void tuh_max3421e_int_api(uint8_t rhport, bool enabled) { + (void) rhport; + + if (enabled) { + NVIC_EnableIRQ(EIC_4_IRQn); + } else { + NVIC_DisableIRQ(EIC_4_IRQn); + } +} + +void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { + (void) rhport; + gpio_set_pin_level(MAX3421E_CS_PIN, active ? 0 : 1); +} + +bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { + (void) rhport; + + size_t count = 0; + while (count < tx_len || count < rx_len) { + // Wait for the transmit buffer to be empty +// while (!SERCOM2->SPI.INTFLAG.bit.DRE); + + // Write data to be transmitted + uint8_t data = 0x00; + if (count < tx_len) { + data = tx_buf[count]; + } + + SERCOM2->SPI.DATA.bit.DATA = data; + + // Wait for the receive buffer to be filled + while (!SERCOM2->SPI.INTFLAG.bit.RXC); + + // Read received data + if (rx_buf) { + rx_buf[count] = SERCOM2->SPI.DATA.bit.DATA; + } + + count++; + } + + return true; +} +#endif + #endif diff --git a/hw/bsp/samd51/family.cmake b/hw/bsp/samd51/family.cmake index fa9586066..1dce483fd 100644 --- a/hw/bsp/samd51/family.cmake +++ b/hw/bsp/samd51/family.cmake @@ -93,6 +93,7 @@ function(family_configure_example TARGET RTOS) family_add_tinyusb(${TARGET} OPT_MCU_SAMD51 ${RTOS}) target_sources(${TARGET}-tinyusb PUBLIC ${TOP}/src/portable/microchip/samd/dcd_samd.c + ${TOP}/src/portable/analog/max3421/hcd_max3421.c ) target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) From 1d68f2a3280cdc76912ec7e89238640e950e542c Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 8 Sep 2023 18:39:09 +0700 Subject: [PATCH 34/71] metro m4 working with max3421e --- hw/bsp/samd51/family.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/hw/bsp/samd51/family.c b/hw/bsp/samd51/family.c index 45a9aa5e0..51cfd19ba 100644 --- a/hw/bsp/samd51/family.c +++ b/hw/bsp/samd51/family.c @@ -294,7 +294,7 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_l size_t count = 0; while (count < tx_len || count < rx_len) { // Wait for the transmit buffer to be empty -// while (!SERCOM2->SPI.INTFLAG.bit.DRE); + while (!SERCOM2->SPI.INTFLAG.bit.DRE); // Write data to be transmitted uint8_t data = 0x00; @@ -302,19 +302,24 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_l data = tx_buf[count]; } - SERCOM2->SPI.DATA.bit.DATA = data; + SERCOM2->SPI.DATA.reg = (uint32_t) data; // Wait for the receive buffer to be filled while (!SERCOM2->SPI.INTFLAG.bit.RXC); // Read received data - if (rx_buf) { - rx_buf[count] = SERCOM2->SPI.DATA.bit.DATA; + data = (uint8_t) SERCOM2->SPI.DATA.reg; + if (count < rx_len) { + rx_buf[count] = data; } count++; } + // wait for bus idle and clear flags + while (!(SERCOM2->SPI.INTFLAG.reg & (SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE))); + SERCOM2->SPI.INTFLAG.reg = SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE; + return true; } #endif From 228acbeac2642534753beffd866db2a7eab45e31 Mon Sep 17 00:00:00 2001 From: maidnl Date: Fri, 8 Sep 2023 15:48:05 +0200 Subject: [PATCH 35/71] wait_pipe_fifo_empty() now returns bool (as expected using TU_ASSERT macro) --- src/portable/renesas/rusb2/dcd_rusb2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/portable/renesas/rusb2/dcd_rusb2.c b/src/portable/renesas/rusb2/dcd_rusb2.c index 68ef5890f..24edc30e7 100644 --- a/src/portable/renesas/rusb2/dcd_rusb2.c +++ b/src/portable/renesas/rusb2/dcd_rusb2.c @@ -267,9 +267,10 @@ static void pipe_read_packet_ff(rusb2_reg_t * rusb, tu_fifo_t *f, volatile void } -static void wait_pipe_fifo_empty(rusb2_reg_t* rusb, uint8_t num) { +static bool wait_pipe_fifo_empty(rusb2_reg_t* rusb, uint8_t num) { TU_ASSERT(num); while( (rusb->PIPE_CTR[num-1] & RUSB2_PIPE_CTR_INBUFM_Msk) > 0 ) {} + return true; } From c074488f75522c7c29dc7853aa2d8597b4858f89 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 9 Sep 2023 12:20:16 +0700 Subject: [PATCH 36/71] minor rename --- .../boards/feather_nrf52840_express/board.h | 10 +- hw/bsp/nrf/boards/pca10056/board.h | 10 +- hw/bsp/nrf/boards/pca10095/board.h | 10 +- hw/bsp/nrf/family.c | 22 +-- hw/bsp/samd51/boards/metro_m4_express/board.h | 12 +- hw/bsp/samd51/family.c | 183 +++++++++--------- src/portable/analog/max3421/hcd_max3421.c | 14 +- 7 files changed, 131 insertions(+), 130 deletions(-) diff --git a/hw/bsp/nrf/boards/feather_nrf52840_express/board.h b/hw/bsp/nrf/boards/feather_nrf52840_express/board.h index e6e7590ac..76100a14a 100644 --- a/hw/bsp/nrf/boards/feather_nrf52840_express/board.h +++ b/hw/bsp/nrf/boards/feather_nrf52840_express/board.h @@ -46,11 +46,11 @@ #define UART_TX_PIN 25 // SPI for USB host shield -#define MAX3421E_SCK_PIN 14 -#define MAX3421E_MOSI_PIN 13 -#define MAX3421E_MISO_PIN 15 -#define MAX3421E_CS_PIN 27 -#define MAX3241E_INTR_PIN 26 +#define MAX3421_SCK_PIN 14 +#define MAX3421_MOSI_PIN 13 +#define MAX3421_MISO_PIN 15 +#define MAX3421_CS_PIN 27 +#define MAX3421_INTR_PIN 26 #ifdef __cplusplus } diff --git a/hw/bsp/nrf/boards/pca10056/board.h b/hw/bsp/nrf/boards/pca10056/board.h index 16d31addb..9459e7911 100644 --- a/hw/bsp/nrf/boards/pca10056/board.h +++ b/hw/bsp/nrf/boards/pca10056/board.h @@ -46,11 +46,11 @@ #define UART_TX_PIN 6 // SPI for USB host shield -#define MAX3421E_SCK_PIN _PINNUM(1, 15) -#define MAX3421E_MOSI_PIN _PINNUM(1, 13) -#define MAX3421E_MISO_PIN _PINNUM(1, 14) -#define MAX3421E_CS_PIN _PINNUM(1, 12) -#define MAX3241E_INTR_PIN _PINNUM(1, 11) +#define MAX3421_SCK_PIN _PINNUM(1, 15) +#define MAX3421_MOSI_PIN _PINNUM(1, 13) +#define MAX3421_MISO_PIN _PINNUM(1, 14) +#define MAX3421_CS_PIN _PINNUM(1, 12) +#define MAX3421_INTR_PIN _PINNUM(1, 11) #ifdef __cplusplus } diff --git a/hw/bsp/nrf/boards/pca10095/board.h b/hw/bsp/nrf/boards/pca10095/board.h index b9d3a19dc..ad3379bf6 100644 --- a/hw/bsp/nrf/boards/pca10095/board.h +++ b/hw/bsp/nrf/boards/pca10095/board.h @@ -46,11 +46,11 @@ #define UART_TX_PIN 33 // SPI for USB host shield -#define MAX3421E_SCK_PIN _PINNUM(1, 15) -#define MAX3421E_MOSI_PIN _PINNUM(1, 13) -#define MAX3421E_MISO_PIN _PINNUM(1, 14) -#define MAX3421E_CS_PIN _PINNUM(1, 12) -#define MAX3241E_INTR_PIN _PINNUM(1, 11) +#define MAX3421_SCK_PIN _PINNUM(1, 15) +#define MAX3421_MOSI_PIN _PINNUM(1, 13) +#define MAX3421_MISO_PIN _PINNUM(1, 14) +#define MAX3421_CS_PIN _PINNUM(1, 12) +#define MAX3421_INTR_PIN _PINNUM(1, 11) #ifdef __cplusplus } diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 47c765a96..6fcfd9476 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -97,8 +97,8 @@ TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) { #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(1); -void max3421e_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { - if (!(pin == MAX3241E_INTR_PIN && action == NRF_GPIOTE_POLARITY_HITOLO)) return; +void max3421_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { + if (!(pin == MAX3421_INTR_PIN && action == NRF_GPIOTE_POLARITY_HITOLO)) return; tuh_int_handler(1); } @@ -207,14 +207,14 @@ void board_init(void) { #endif // manually manage CS - nrf_gpio_cfg_output(MAX3421E_CS_PIN); - nrf_gpio_pin_write(MAX3421E_CS_PIN, 1); + nrf_gpio_cfg_output(MAX3421_CS_PIN); + nrf_gpio_pin_write(MAX3421_CS_PIN, 1); // USB host using max3421e usb controller via SPI nrfx_spim_config_t cfg = { - .sck_pin = MAX3421E_SCK_PIN, - .mosi_pin = MAX3421E_MOSI_PIN, - .miso_pin = MAX3421E_MISO_PIN, + .sck_pin = MAX3421_SCK_PIN, + .mosi_pin = MAX3421_MOSI_PIN, + .miso_pin = MAX3421_MISO_PIN, .ss_pin = NRFX_SPIM_PIN_NOT_USED, .ss_active_high = false, .irq_priority = 3, @@ -233,8 +233,8 @@ void board_init(void) { nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true); in_config.pull = NRF_GPIO_PIN_PULLUP; - nrfx_gpiote_in_init(MAX3241E_INTR_PIN, &in_config, max3421e_int_handler); - nrfx_gpiote_trigger_enable(MAX3241E_INTR_PIN, true); + nrfx_gpiote_in_init(MAX3421_INTR_PIN, &in_config, max3421_int_handler); + nrfx_gpiote_trigger_enable(MAX3421_INTR_PIN, true); #endif } @@ -317,7 +317,7 @@ void nrf_error_cb(uint32_t id, uint32_t pc, uint32_t info) { //--------------------------------------------------------------------+ #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 -void tuh_max3421e_int_api(uint8_t rhport, bool enabled) { +void tuh_max3421_int_api(uint8_t rhport, bool enabled) { (void) rhport; // use NVIC_Enable/Disable instead since nrfx_gpiote_trigger_enable/disable clear pending and can miss interrupt @@ -331,7 +331,7 @@ void tuh_max3421e_int_api(uint8_t rhport, bool enabled) { void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { (void) rhport; - nrf_gpio_pin_write(MAX3421E_CS_PIN, active ? 0 : 1); + nrf_gpio_pin_write(MAX3421_CS_PIN, active ? 0 : 1); } bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { diff --git a/hw/bsp/samd51/boards/metro_m4_express/board.h b/hw/bsp/samd51/boards/metro_m4_express/board.h index 3441d03e9..fe2a867a4 100644 --- a/hw/bsp/samd51/boards/metro_m4_express/board.h +++ b/hw/bsp/samd51/boards/metro_m4_express/board.h @@ -44,12 +44,12 @@ #define UART_RX_PIN 22 // SPI for USB host shield -#define MAX3421E_SERCOM SERCOM2 -#define MAX3421E_SCK_PIN 13 -#define MAX3421E_MOSI_PIN 12 -#define MAX3421E_MISO_PIN 14 -#define MAX3421E_CS_PIN 18 // D10 -#define MAX3241E_INTR_PIN 20 // D9 +#define MAX3421_SERCOM 2 // SERCOM2 +#define MAX3421_SCK_PIN 13 +#define MAX3421_MOSI_PIN 12 +#define MAX3421_MISO_PIN 14 +#define MAX3421_CS_PIN 18 // D10 +#define MAX3421_INTR_PIN 20 // D9 #ifdef __cplusplus diff --git a/hw/bsp/samd51/family.c b/hw/bsp/samd51/family.c index 51cfd19ba..34dd93cef 100644 --- a/hw/bsp/samd51/family.c +++ b/hw/bsp/samd51/family.c @@ -73,58 +73,14 @@ void USB_3_Handler(void) { } //--------------------------------------------------------------------+ -// +// Implementation //--------------------------------------------------------------------+ #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 -void max3421_init(void) -{ - //------------- SPI Init -------------// +static void max3421_init(void); - // Enable the APB clock for SERCOM2 - MCLK->APBBMASK.reg |= MCLK_APBBMASK_SERCOM2; +//#define - // Configure GCLK for SERCOM2, initClockNVIC() - GCLK->PCHCTRL[SERCOM2_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); - GCLK->PCHCTRL[SERCOM2_GCLK_ID_SLOW].reg = GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); - - // Disable the SPI module - SERCOM2->SPI.CTRLA.bit.ENABLE = 0; - - // Reset the SPI module - SERCOM2->SPI.CTRLA.bit.SWRST = 1; - while (SERCOM2->SPI.SYNCBUSY.bit.SWRST); - - // Set up SPI in master mode, MSB first, SPI mode 0 - uint8_t const mosi_pad = 0; - uint8_t const miso_pad = 2; - SERCOM2->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE(3) | SERCOM_SPI_CTRLA_DOPO(mosi_pad) | SERCOM_SPI_CTRLA_DIPO(miso_pad); - - SERCOM2->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN; - while( SERCOM2->SPI.SYNCBUSY.bit.CTRLB == 1 ); - - // Set the baud rate - uint32_t baudrate = 4000000u; - SERCOM2->SPI.BAUD.reg = (uint8_t)(SystemCoreClock / (2 * baudrate) - 1); // Replace 1000000 with your desired baud rate - - // Configure PA12 as MOSI (PAD0), PA13 as SCK (PAD1), PA14 as MISO (PAD2) - // 2 function C: PIO_SERCOM - gpio_set_pin_direction(MAX3421E_SCK_PIN, GPIO_DIRECTION_OUT); - gpio_set_pin_pull_mode(MAX3421E_SCK_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(MAX3421E_SCK_PIN, 2); - - gpio_set_pin_direction(MAX3421E_MOSI_PIN, GPIO_DIRECTION_OUT); - gpio_set_pin_pull_mode(MAX3421E_MOSI_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(MAX3421E_MOSI_PIN, 2); - - gpio_set_pin_direction(MAX3421E_MISO_PIN, GPIO_DIRECTION_IN); - gpio_set_pin_pull_mode(MAX3421E_MISO_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(MAX3421E_MISO_PIN, 2); - - // Enable the SPI module - SERCOM2->SPI.CTRLA.bit.ENABLE = 1; - while (SERCOM2->SPI.SYNCBUSY.bit.ENABLE); -} #endif void board_init(void) { @@ -180,46 +136,7 @@ void board_init(void) { gpio_set_pin_function(PIN_PA25, PINMUX_PA25H_USB_DP); #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 - // CS pin - gpio_set_pin_direction(MAX3421E_CS_PIN, GPIO_DIRECTION_OUT); - gpio_set_pin_level(MAX3421E_CS_PIN, 1); - - // SPI max3421_init(); - - // INT pin with external interrupt - gpio_set_pin_direction(MAX3241E_INTR_PIN, GPIO_DIRECTION_IN); - gpio_set_pin_pull_mode(MAX3241E_INTR_PIN, GPIO_PULL_UP); - - // Enable the APB clock for EIC (External Interrupt Controller) - MCLK->APBAMASK.reg |= MCLK_APBAMASK_EIC; - - // Configure GCLK for EIC - GCLK->PCHCTRL[EIC_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); - - // Configure PA20 as an input - PORT->Group[0].DIRCLR.reg = PORT_PA20; - PORT->Group[0].PINCFG[20].reg = PORT_PINCFG_INEN | PORT_PINCFG_PULLEN; - PORT->Group[0].OUTSET.reg = PORT_PA20; // Enable pull-up - - // Configure PA20 to use EIC - PORT->Group[0].PMUX[10].bit.PMUXE = MUX_PA20A_EIC_EXTINT4; - PORT->Group[0].PINCFG[20].bit.PMUXEN = 1; - - // Disable EIC - EIC->CTRLA.bit.ENABLE = 0; - while (EIC->SYNCBUSY.bit.ENABLE); - - // Configure EXTINT4 (PA20) to trigger on falling edge - EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE4_FALL; - - // Enable EXTINT4 - EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << 4); - - // Enable EIC - EIC->CTRLA.bit.ENABLE = 1; - while (EIC->SYNCBUSY.bit.ENABLE); - #endif } @@ -264,8 +181,91 @@ uint32_t board_millis(void) { //--------------------------------------------------------------------+ #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 -void EIC_4_Handler(void) -{ +static void max3421_init(void) { + // CS pin + gpio_set_pin_direction(MAX3421_CS_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_level(MAX3421_CS_PIN, 1); + + //------------- SPI Init -------------// + + // Enable the APB clock for SERCOM2 + MCLK->APBBMASK.reg |= MCLK_APBBMASK_SERCOM2; + + // Configure GCLK for SERCOM2, initClockNVIC() + GCLK->PCHCTRL[SERCOM2_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); + GCLK->PCHCTRL[SERCOM2_GCLK_ID_SLOW].reg = GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); + + // Disable the SPI module + SERCOM2->SPI.CTRLA.bit.ENABLE = 0; + + // Reset the SPI module + SERCOM2->SPI.CTRLA.bit.SWRST = 1; + while (SERCOM2->SPI.SYNCBUSY.bit.SWRST); + + // Set up SPI in master mode, MSB first, SPI mode 0 + uint8_t const mosi_pad = 0; + uint8_t const miso_pad = 2; + SERCOM2->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE(3) | SERCOM_SPI_CTRLA_DOPO(mosi_pad) | SERCOM_SPI_CTRLA_DIPO(miso_pad); + + SERCOM2->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN; + while (SERCOM2->SPI.SYNCBUSY.bit.CTRLB == 1); + + // Set the baud rate + uint32_t baudrate = 4000000u; + SERCOM2->SPI.BAUD.reg = (uint8_t) (SystemCoreClock / (2 * baudrate) - + 1); // Replace 1000000 with your desired baud rate + + // Configure PA12 as MOSI (PAD0), PA13 as SCK (PAD1), PA14 as MISO (PAD2) + // 2 function C: PIO_SERCOM + gpio_set_pin_direction(MAX3421_SCK_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_pull_mode(MAX3421_SCK_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421_SCK_PIN, 2); + + gpio_set_pin_direction(MAX3421_MOSI_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_pull_mode(MAX3421_MOSI_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421_MOSI_PIN, 2); + + gpio_set_pin_direction(MAX3421_MISO_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(MAX3421_MISO_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421_MISO_PIN, 2); + + // Enable the SPI module + SERCOM2->SPI.CTRLA.bit.ENABLE = 1; + while (SERCOM2->SPI.SYNCBUSY.bit.ENABLE); + + //------------- External Interrupt -------------// + + // INT pin with external interrupt + gpio_set_pin_direction(MAX3421_INTR_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(MAX3421_INTR_PIN, GPIO_PULL_UP); + + // Enable the APB clock for EIC (External Interrupt Controller) + MCLK->APBAMASK.reg |= MCLK_APBAMASK_EIC; + + // Configure GCLK for EIC + GCLK->PCHCTRL[EIC_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); + + // Configure PA20 as an input with function A (external interrupt) + gpio_set_pin_direction(MAX3421_INTR_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(MAX3421_INTR_PIN, GPIO_PULL_UP); + gpio_set_pin_function(MAX3421_INTR_PIN, 0); + + // Disable EIC + EIC->CTRLA.bit.ENABLE = 0; + while (EIC->SYNCBUSY.bit.ENABLE); + + // Configure EXTINT4 (PA20) to trigger on falling edge + EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE4_FALL; + + // Enable EXTINT4 + EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << 4); + + // Enable EIC + EIC->CTRLA.bit.ENABLE = 1; + while (EIC->SYNCBUSY.bit.ENABLE); +} + +void EIC_4_Handler(void) { // Clear the interrupt flag EIC->INTFLAG.reg = EIC_INTFLAG_EXTINT(1 << 4); @@ -273,7 +273,7 @@ void EIC_4_Handler(void) tuh_int_handler(1); } -void tuh_max3421e_int_api(uint8_t rhport, bool enabled) { +void tuh_max3421_int_api(uint8_t rhport, bool enabled) { (void) rhport; if (enabled) { @@ -285,7 +285,7 @@ void tuh_max3421e_int_api(uint8_t rhport, bool enabled) { void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { (void) rhport; - gpio_set_pin_level(MAX3421E_CS_PIN, active ? 0 : 1); + gpio_set_pin_level(MAX3421_CS_PIN, active ? 0 : 1); } bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { @@ -299,7 +299,7 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_l // Write data to be transmitted uint8_t data = 0x00; if (count < tx_len) { - data = tx_buf[count]; + data = tx_buf[count]; } SERCOM2->SPI.DATA.reg = (uint32_t) data; @@ -322,6 +322,7 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_l return true; } + #endif #endif diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 95cf5516e..238b518a0 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -212,7 +212,7 @@ static max3421_data_t _hcd_data; void tuh_max3421_spi_cs_api(uint8_t rhport, bool active); bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len); -void tuh_max3421e_int_api(uint8_t rhport, bool enabled); +void tuh_max3421_int_api(uint8_t rhport, bool enabled); static void handle_connect_irq(uint8_t rhport, bool in_isr); static inline void hirq_write(uint8_t rhport, uint8_t data, bool in_isr); @@ -225,7 +225,7 @@ static void max3421_spi_lock(uint8_t rhport, bool in_isr) { // disable interrupt and mutex lock (for pre-emptive RTOS) if not in_isr if (!in_isr) { (void) osal_mutex_lock(_hcd_data.spi_mutex, OSAL_TIMEOUT_WAIT_FOREVER); - tuh_max3421e_int_api(rhport, false); + tuh_max3421_int_api(rhport, false); } // assert CS @@ -238,7 +238,7 @@ static void max3421_spi_unlock(uint8_t rhport, bool in_isr) { // mutex unlock and re-enable interrupt if (!in_isr) { - tuh_max3421e_int_api(rhport, true); + tuh_max3421_int_api(rhport, true); (void) osal_mutex_unlock(_hcd_data.spi_mutex); } } @@ -411,7 +411,7 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { bool hcd_init(uint8_t rhport) { (void) rhport; - tuh_max3421e_int_api(rhport, false); + tuh_max3421_int_api(rhport, false); tuh_max3421_spi_cs_api(rhport, false); TU_LOG2_INT(sizeof(max3421_ep_t)); @@ -450,7 +450,7 @@ bool hcd_init(uint8_t rhport) { // Enable IRQ hien_write(rhport, DEFAULT_HIEN, false); - tuh_max3421e_int_api(rhport, true); + tuh_max3421_int_api(rhport, true); // Enable Interrupt pin reg_write(rhport, CPUCTL_ADDR, CPUCTL_IE, false); @@ -461,13 +461,13 @@ bool hcd_init(uint8_t rhport) { // Enable USB interrupt // Not actually enable GPIO interrupt, just set variable to prevent handler to process void hcd_int_enable (uint8_t rhport) { - tuh_max3421e_int_api(rhport, true); + tuh_max3421_int_api(rhport, true); } // Disable USB interrupt // Not actually disable GPIO interrupt, just set variable to prevent handler to process void hcd_int_disable(uint8_t rhport) { - tuh_max3421e_int_api(rhport, false); + tuh_max3421_int_api(rhport, false); } // Get frame number (1ms) From 605ad73ec02033aa6b66e6899e232537ca2354bb Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 9 Sep 2023 13:04:36 +0700 Subject: [PATCH 37/71] refactor max3421_init() for samd51 to be generic for sercom and eic --- hw/bsp/samd51/boards/metro_m4_express/board.h | 15 ++- hw/bsp/samd51/family.c | 108 +++++++++++------- 2 files changed, 77 insertions(+), 46 deletions(-) diff --git a/hw/bsp/samd51/boards/metro_m4_express/board.h b/hw/bsp/samd51/boards/metro_m4_express/board.h index fe2a867a4..aa6bdd0c8 100644 --- a/hw/bsp/samd51/boards/metro_m4_express/board.h +++ b/hw/bsp/samd51/boards/metro_m4_express/board.h @@ -44,13 +44,16 @@ #define UART_RX_PIN 22 // SPI for USB host shield -#define MAX3421_SERCOM 2 // SERCOM2 -#define MAX3421_SCK_PIN 13 -#define MAX3421_MOSI_PIN 12 -#define MAX3421_MISO_PIN 14 -#define MAX3421_CS_PIN 18 // D10 -#define MAX3421_INTR_PIN 20 // D9 +#define MAX3421_SERCOM_ID 2 // SERCOM2 +#define MAX3421_SCK_PIN 13 +#define MAX3421_MOSI_PIN 12 +#define MAX3421_MOSI_PAD 0 +#define MAX3421_MISO_PIN 14 +#define MAX3421_MISO_PAD 2 +#define MAX3421_CS_PIN 18 // D10 +#define MAX3421_INTR_PIN 20 // D9 +#define MAX3421_INTR_EIC_ID 4 // EIC4 #ifdef __cplusplus } diff --git a/hw/bsp/samd51/family.c b/hw/bsp/samd51/family.c index 34dd93cef..f9e1718d0 100644 --- a/hw/bsp/samd51/family.c +++ b/hw/bsp/samd51/family.c @@ -79,7 +79,8 @@ void USB_3_Handler(void) { #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 static void max3421_init(void); -//#define +#define MAX3421_SERCOM TU_XSTRCAT(SERCOM, MAX3421_SERCOM_ID) +#define MAX3421_EIC_Handler TU_XSTRCAT3(EIC_, MAX3421_INTR_EIC_ID, _Handler) #endif @@ -182,41 +183,55 @@ uint32_t board_millis(void) { #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 static void max3421_init(void) { - // CS pin - gpio_set_pin_direction(MAX3421_CS_PIN, GPIO_DIRECTION_OUT); - gpio_set_pin_level(MAX3421_CS_PIN, 1); - //------------- SPI Init -------------// + uint32_t const baudrate = 4000000u; - // Enable the APB clock for SERCOM2 - MCLK->APBBMASK.reg |= MCLK_APBBMASK_SERCOM2; + struct { + volatile uint32_t *mck_apb; + uint32_t mask; + uint8_t gclk_id_core; + uint8_t gclk_id_slow; + } const sercom_clock[] = { + { &MCLK->APBAMASK.reg, MCLK_APBAMASK_SERCOM0, SERCOM0_GCLK_ID_CORE, SERCOM0_GCLK_ID_SLOW }, + { &MCLK->APBAMASK.reg, MCLK_APBAMASK_SERCOM1, SERCOM1_GCLK_ID_CORE, SERCOM1_GCLK_ID_SLOW }, + { &MCLK->APBBMASK.reg, MCLK_APBBMASK_SERCOM2, SERCOM2_GCLK_ID_CORE, SERCOM2_GCLK_ID_SLOW }, + { &MCLK->APBBMASK.reg, MCLK_APBBMASK_SERCOM3, SERCOM3_GCLK_ID_CORE, SERCOM3_GCLK_ID_SLOW }, + { &MCLK->APBDMASK.reg, MCLK_APBDMASK_SERCOM4, SERCOM4_GCLK_ID_CORE, SERCOM4_GCLK_ID_SLOW }, + { &MCLK->APBDMASK.reg, MCLK_APBDMASK_SERCOM5, SERCOM5_GCLK_ID_CORE, SERCOM5_GCLK_ID_SLOW }, + #ifdef SERCOM6_GCLK_ID_CORE + { &MCLK->APBDMASK.reg, MCLK_APBDMASK_SERCOM6, SERCOM6_GCLK_ID_CORE, SERCOM6_GCLK_ID_SLOW }, + #endif + #ifdef SERCOM7_GCLK_ID_CORE + { &MCLK->APBDMASK.reg, MCLK_APBDMASK_SERCOM7, SERCOM7_GCLK_ID_CORE, SERCOM7_GCLK_ID_SLOW }, + #endif + }; - // Configure GCLK for SERCOM2, initClockNVIC() - GCLK->PCHCTRL[SERCOM2_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); - GCLK->PCHCTRL[SERCOM2_GCLK_ID_SLOW].reg = GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); + Sercom* sercom = MAX3421_SERCOM; + + // Enable the APB clock for SERCOM + *sercom_clock[MAX3421_SERCOM_ID].mck_apb |= sercom_clock[MAX3421_SERCOM_ID].mask; + + // Configure GCLK for SERCOM + GCLK->PCHCTRL[sercom_clock[MAX3421_SERCOM_ID].gclk_id_core].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); + GCLK->PCHCTRL[sercom_clock[MAX3421_SERCOM_ID].gclk_id_slow].reg = GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); // Disable the SPI module - SERCOM2->SPI.CTRLA.bit.ENABLE = 0; + sercom->SPI.CTRLA.bit.ENABLE = 0; // Reset the SPI module - SERCOM2->SPI.CTRLA.bit.SWRST = 1; - while (SERCOM2->SPI.SYNCBUSY.bit.SWRST); + sercom->SPI.CTRLA.bit.SWRST = 1; + while (sercom->SPI.SYNCBUSY.bit.SWRST); // Set up SPI in master mode, MSB first, SPI mode 0 - uint8_t const mosi_pad = 0; - uint8_t const miso_pad = 2; - SERCOM2->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE(3) | SERCOM_SPI_CTRLA_DOPO(mosi_pad) | SERCOM_SPI_CTRLA_DIPO(miso_pad); + sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE(3) | SERCOM_SPI_CTRLA_DOPO(MAX3421_MOSI_PAD) | SERCOM_SPI_CTRLA_DIPO(MAX3421_MISO_PAD); - SERCOM2->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN; - while (SERCOM2->SPI.SYNCBUSY.bit.CTRLB == 1); + sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN; + while (sercom->SPI.SYNCBUSY.bit.CTRLB == 1); // Set the baud rate - uint32_t baudrate = 4000000u; - SERCOM2->SPI.BAUD.reg = (uint8_t) (SystemCoreClock / (2 * baudrate) - - 1); // Replace 1000000 with your desired baud rate + sercom->SPI.BAUD.reg = (uint8_t) (SystemCoreClock / (2 * baudrate) - 1); - // Configure PA12 as MOSI (PAD0), PA13 as SCK (PAD1), PA14 as MISO (PAD2) - // 2 function C: PIO_SERCOM + // Configure PA12 as MOSI (PAD0), PA13 as SCK (PAD1), PA14 as MISO (PAD2), function C (sercom) gpio_set_pin_direction(MAX3421_SCK_PIN, GPIO_DIRECTION_OUT); gpio_set_pin_pull_mode(MAX3421_SCK_PIN, GPIO_PULL_OFF); gpio_set_pin_function(MAX3421_SCK_PIN, 2); @@ -229,16 +244,16 @@ static void max3421_init(void) { gpio_set_pin_pull_mode(MAX3421_MISO_PIN, GPIO_PULL_OFF); gpio_set_pin_function(MAX3421_MISO_PIN, 2); + // CS pin + gpio_set_pin_direction(MAX3421_CS_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_level(MAX3421_CS_PIN, 1); + // Enable the SPI module - SERCOM2->SPI.CTRLA.bit.ENABLE = 1; - while (SERCOM2->SPI.SYNCBUSY.bit.ENABLE); + sercom->SPI.CTRLA.bit.ENABLE = 1; + while (sercom->SPI.SYNCBUSY.bit.ENABLE); //------------- External Interrupt -------------// - // INT pin with external interrupt - gpio_set_pin_direction(MAX3421_INTR_PIN, GPIO_DIRECTION_IN); - gpio_set_pin_pull_mode(MAX3421_INTR_PIN, GPIO_PULL_UP); - // Enable the APB clock for EIC (External Interrupt Controller) MCLK->APBAMASK.reg |= MCLK_APBAMASK_EIC; @@ -255,19 +270,30 @@ static void max3421_init(void) { while (EIC->SYNCBUSY.bit.ENABLE); // Configure EXTINT4 (PA20) to trigger on falling edge - EIC->CONFIG[0].reg |= EIC_CONFIG_SENSE4_FALL; + volatile uint32_t * eic_config; + uint8_t sense_shift; + if ( MAX3421_INTR_EIC_ID < 8 ) { + eic_config = &EIC->CONFIG[0].reg; + sense_shift = MAX3421_INTR_EIC_ID * 4; + } else { + eic_config = &EIC->CONFIG[1].reg; + sense_shift = (MAX3421_INTR_EIC_ID - 8) * 4; + } - // Enable EXTINT4 - EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << 4); + *eic_config &= ~(7 << sense_shift); + *eic_config |= 2 << sense_shift; + + // Enable External Interrupt + EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << MAX3421_INTR_EIC_ID); // Enable EIC EIC->CTRLA.bit.ENABLE = 1; while (EIC->SYNCBUSY.bit.ENABLE); } -void EIC_4_Handler(void) { +void MAX3421_EIC_Handler(void) { // Clear the interrupt flag - EIC->INTFLAG.reg = EIC_INTFLAG_EXTINT(1 << 4); + EIC->INTFLAG.reg = EIC_INTFLAG_EXTINT(1 << MAX3421_INTR_EIC_ID); // Call the TinyUSB interrupt handler tuh_int_handler(1); @@ -291,10 +317,12 @@ void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { (void) rhport; + Sercom* sercom = MAX3421_SERCOM; + size_t count = 0; while (count < tx_len || count < rx_len) { // Wait for the transmit buffer to be empty - while (!SERCOM2->SPI.INTFLAG.bit.DRE); + while (!sercom->SPI.INTFLAG.bit.DRE); // Write data to be transmitted uint8_t data = 0x00; @@ -302,13 +330,13 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_l data = tx_buf[count]; } - SERCOM2->SPI.DATA.reg = (uint32_t) data; + sercom->SPI.DATA.reg = (uint32_t) data; // Wait for the receive buffer to be filled - while (!SERCOM2->SPI.INTFLAG.bit.RXC); + while (!sercom->SPI.INTFLAG.bit.RXC); // Read received data - data = (uint8_t) SERCOM2->SPI.DATA.reg; + data = (uint8_t) sercom->SPI.DATA.reg; if (count < rx_len) { rx_buf[count] = data; } @@ -317,8 +345,8 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_l } // wait for bus idle and clear flags - while (!(SERCOM2->SPI.INTFLAG.reg & (SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE))); - SERCOM2->SPI.INTFLAG.reg = SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE; + while (!(sercom->SPI.INTFLAG.reg & (SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE))); + sercom->SPI.INTFLAG.reg = SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE; return true; } From e32c1e08bd701b5dda7d081b10ba3262e2061326 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 9 Sep 2023 16:50:16 +0700 Subject: [PATCH 38/71] both samd21/d51 works perfectly with max3421e --- hw/bsp/samd21/boards/metro_m0_express/board.h | 16 ++ hw/bsp/samd21/family.c | 230 +++++++++++++++--- hw/bsp/samd21/family.cmake | 1 + hw/bsp/samd51/boards/metro_m4_express/board.h | 22 +- hw/bsp/samd51/family.c | 19 +- 5 files changed, 234 insertions(+), 54 deletions(-) diff --git a/hw/bsp/samd21/boards/metro_m0_express/board.h b/hw/bsp/samd21/boards/metro_m0_express/board.h index d26aae53c..6dd53e901 100644 --- a/hw/bsp/samd21/boards/metro_m0_express/board.h +++ b/hw/bsp/samd21/boards/metro_m0_express/board.h @@ -43,6 +43,22 @@ #define UART_RX_PIN 4 #define UART_TX_PIN 5 +// SPI for USB host shield +#define MAX3421_SERCOM_ID 4 // SERCOM4 +#define MAX3421_SERCOM_FUNCTION 3 // function D (Sercom Alt) + +#define MAX3421_SCK_PIN (32+11) +#define MAX3421_MOSI_PIN (32+10) +#define MAX3421_MISO_PIN 12 +#define MAX3421_TX_PAD 1 // MOSI = PAD_2, SCK = PAD_3 +#define MAX3421_RX_PAD 0 // MISO = PAD_2 + +#define MAX3421_CS_PIN 18 // D10 + +#define MAX3421_INTR_PIN 7 // D9 +#define MAX3421_INTR_EIC_ID 7 // EIC7 + + #ifdef __cplusplus } #endif diff --git a/hw/bsp/samd21/family.c b/hw/bsp/samd21/family.c index 2121e028a..cfe66b8dc 100644 --- a/hw/bsp/samd21/family.c +++ b/hw/bsp/samd21/family.c @@ -46,19 +46,6 @@ #pragma GCC diagnostic pop #endif -//--------------------------------------------------------------------+ -// Forward USB interrupt events to TinyUSB IRQ Handler -//--------------------------------------------------------------------+ -void USB_Handler(void) -{ - tud_int_handler(0); -} - -//--------------------------------------------------------------------+ -// UART support -//--------------------------------------------------------------------+ -static void uart_init(void); - //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ @@ -69,8 +56,25 @@ static void uart_init(void); /* Not referenced GCLKs, initialized last */ #define _GCLK_INIT_LAST (~_GCLK_INIT_1ST) -void board_init(void) -{ +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_Handler(void) { + tud_int_handler(0); +} + +//--------------------------------------------------------------------+ +// Implementation +//--------------------------------------------------------------------+ +static void uart_init(void); + +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 +#define MAX3421_SERCOM TU_XSTRCAT(SERCOM, MAX3421_SERCOM_ID) + +static void max3421_init(void); +#endif + +void board_init(void) { // Clock init ( follow hpl_init.c ) hri_nvmctrl_set_CTRLB_RWS_bf(NVMCTRL, 2); @@ -85,7 +89,7 @@ void board_init(void) // Update SystemCoreClock since it is hard coded with asf4 and not correct // Init 1ms tick timer (samd SystemCoreClock may not correct) SystemCoreClock = CONF_CPU_FREQUENCY; -#if CFG_TUSB_OS == OPT_OS_NONE +#if CFG_TUSB_OS == OPT_OS_NONE SysTick_Config(CONF_CPU_FREQUENCY / 1000); #endif @@ -103,7 +107,7 @@ void board_init(void) uart_init(); -#if CFG_TUSB_OS == OPT_OS_FREERTOS +#if CFG_TUSB_OS == OPT_OS_FREERTOS // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) NVIC_SetPriority(USB_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); #endif @@ -134,22 +138,24 @@ void board_init(void) gpio_set_pin_function(PIN_PA19, PINMUX_PA19F_TCC0_WO3); _gclk_enable_channel(TCC0_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); + +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + max3421_init(); +#endif } //--------------------------------------------------------------------+ // Board porting API //--------------------------------------------------------------------+ -void board_led_write(bool state) -{ - (void)state; +void board_led_write(bool state) { + (void) state; #ifdef LED_PIN - gpio_set_pin_level(LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); + gpio_set_pin_level(LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); #endif } -uint32_t board_button_read(void) -{ +uint32_t board_button_read(void) { #ifdef BUTTON_PIN return BUTTON_STATE_ACTIVE == gpio_get_pin_level(BUTTON_PIN); #else @@ -227,33 +233,185 @@ int board_uart_write(void const * buf, int len) } #else // ! defined(UART_SERCOM) -static void uart_init(void) -{ +static void uart_init(void) { } -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; +int board_uart_read(uint8_t *buf, int len) { + (void) buf; + (void) len; return 0; } -int board_uart_write(void const * buf, int len) -{ - (void) buf; (void) len; +int board_uart_write(void const *buf, int len) { + (void) buf; + (void) len; return 0; } + #endif -#if CFG_TUSB_OS == OPT_OS_NONE +#if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; -void SysTick_Handler (void) -{ + +void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) -{ +uint32_t board_millis(void) { return system_ticks; } + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + +static void max3421_init(void) { + //------------- SPI Init -------------// + uint32_t const baudrate = 4000000u; + + // Enable the APB clock for SERCOM + PM->APBCMASK.reg |= 1u << (PM_APBCMASK_SERCOM0_Pos + MAX3421_SERCOM_ID); + + // Configure GCLK for SERCOM +// GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_SERCOM4_CORE | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_SERCOM0_CORE_Val+MAX3421_SERCOM_ID) | + GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; + while (GCLK->STATUS.bit.SYNCBUSY); + + Sercom* sercom = MAX3421_SERCOM; + + // Disable the SPI module + sercom->SPI.CTRLA.bit.ENABLE = 0; + + // Reset the SPI module + sercom->SPI.CTRLA.bit.SWRST = 1; + while (sercom->SPI.SYNCBUSY.bit.SWRST); + + // Set up SPI in master mode, MSB first, SPI mode 0 + sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_DOPO(MAX3421_TX_PAD) | SERCOM_SPI_CTRLA_DIPO(MAX3421_RX_PAD) | + SERCOM_SPI_CTRLA_MODE(3); + + sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN; + while (sercom->SPI.SYNCBUSY.bit.CTRLB == 1); + + // Set the baud rate + sercom->SPI.BAUD.reg = (uint8_t) (SystemCoreClock / (2 * baudrate) - 1); + + // Configure PA12 as MOSI (PAD0), PA13 as SCK (PAD1), PA14 as MISO (PAD2), function C (sercom) + gpio_set_pin_direction(MAX3421_SCK_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_pull_mode(MAX3421_SCK_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421_SCK_PIN, MAX3421_SERCOM_FUNCTION); + + gpio_set_pin_direction(MAX3421_MOSI_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_pull_mode(MAX3421_MOSI_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421_MOSI_PIN, MAX3421_SERCOM_FUNCTION); + + gpio_set_pin_direction(MAX3421_MISO_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(MAX3421_MISO_PIN, GPIO_PULL_OFF); + gpio_set_pin_function(MAX3421_MISO_PIN, MAX3421_SERCOM_FUNCTION); + + // CS pin + gpio_set_pin_direction(MAX3421_CS_PIN, GPIO_DIRECTION_OUT); + gpio_set_pin_level(MAX3421_CS_PIN, 1); + + // Enable the SPI module + sercom->SPI.CTRLA.bit.ENABLE = 1; + while (sercom->SPI.SYNCBUSY.bit.ENABLE); + + //------------- External Interrupt -------------// + + // Enable the APB clock for EIC (External Interrupt Controller) + PM->APBAMASK.reg |= PM_APBAMASK_EIC; + + // Configure GCLK for EIC + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_EIC | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; + while (GCLK->STATUS.bit.SYNCBUSY); + + // Configure PA20 as an input with function A (external interrupt) + gpio_set_pin_direction(MAX3421_INTR_PIN, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(MAX3421_INTR_PIN, GPIO_PULL_UP); + gpio_set_pin_function(MAX3421_INTR_PIN, 0); + + // Disable EIC + EIC->CTRL.bit.ENABLE = 0; + while (EIC->STATUS.bit.SYNCBUSY); + + // Configure EIC to trigger on falling edge + uint8_t const sense_shift = MAX3421_INTR_EIC_ID * 4; + EIC->CONFIG[0].reg &= ~(7 << sense_shift); + EIC->CONFIG[0].reg |= 2 << sense_shift; + + // Enable External Interrupt + EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << MAX3421_INTR_EIC_ID); + + // Enable EIC + EIC->CTRL.bit.ENABLE = 1; + while (EIC->STATUS.bit.SYNCBUSY); +} + +void EIC_Handler(void) { + // Clear the interrupt flag + EIC->INTFLAG.reg = EIC_INTFLAG_EXTINT(1 << MAX3421_INTR_EIC_ID); + + // Call the TinyUSB interrupt handler + tuh_int_handler(1); +} + +void tuh_max3421_int_api(uint8_t rhport, bool enabled) { + (void) rhport; + + if (enabled) { + NVIC_EnableIRQ(EIC_IRQn); + } else { + NVIC_DisableIRQ(EIC_IRQn); + } +} + +void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { + (void) rhport; + gpio_set_pin_level(MAX3421_CS_PIN, active ? 0 : 1); +} + +bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { + (void) rhport; + + Sercom* sercom = MAX3421_SERCOM; + + size_t count = 0; + while (count < tx_len || count < rx_len) { + // Wait for the transmit buffer to be empty + while (!sercom->SPI.INTFLAG.bit.DRE); + + // Write data to be transmitted + uint8_t data = 0x00; + if (count < tx_len) { + data = tx_buf[count]; + } + + sercom->SPI.DATA.reg = (uint32_t) data; + + // Wait for the receive buffer to be filled + while (!sercom->SPI.INTFLAG.bit.RXC); + + // Read received data + data = (uint8_t) sercom->SPI.DATA.reg; + if (count < rx_len) { + rx_buf[count] = data; + } + + count++; + } + + // wait for bus idle and clear flags + while (!(sercom->SPI.INTFLAG.reg & (SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE))); + sercom->SPI.INTFLAG.reg = SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE; + + return true; +} + +#endif + + #endif diff --git a/hw/bsp/samd21/family.cmake b/hw/bsp/samd21/family.cmake index 07186934a..ffbf687a1 100644 --- a/hw/bsp/samd21/family.cmake +++ b/hw/bsp/samd21/family.cmake @@ -94,6 +94,7 @@ function(family_configure_example TARGET RTOS) family_add_tinyusb(${TARGET} OPT_MCU_SAMD21 ${RTOS}) target_sources(${TARGET}-tinyusb PUBLIC ${TOP}/src/portable/microchip/samd/dcd_samd.c + ${TOP}/src/portable/analog/max3421/hcd_max3421.c ) target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) diff --git a/hw/bsp/samd51/boards/metro_m4_express/board.h b/hw/bsp/samd51/boards/metro_m4_express/board.h index aa6bdd0c8..b3b80db89 100644 --- a/hw/bsp/samd51/boards/metro_m4_express/board.h +++ b/hw/bsp/samd51/boards/metro_m4_express/board.h @@ -44,16 +44,20 @@ #define UART_RX_PIN 22 // SPI for USB host shield -#define MAX3421_SERCOM_ID 2 // SERCOM2 -#define MAX3421_SCK_PIN 13 -#define MAX3421_MOSI_PIN 12 -#define MAX3421_MOSI_PAD 0 -#define MAX3421_MISO_PIN 14 -#define MAX3421_MISO_PAD 2 -#define MAX3421_CS_PIN 18 // D10 +#define MAX3421_SERCOM_ID 2 // SERCOM2 +#define MAX3421_SERCOM_FUNCTION 2 // function C + +#define MAX3421_SCK_PIN 13 +#define MAX3421_MOSI_PIN 12 +#define MAX3421_MISO_PIN 14 +#define MAX3421_TX_PAD 0 // MOSI = PAD_0, SCK = PAD_1 +#define MAX3421_RX_PAD 2 // MISO = PAD_2 + +#define MAX3421_CS_PIN 18 // D10 + +#define MAX3421_INTR_PIN 20 // D9 +#define MAX3421_INTR_EIC_ID 4 // EIC4 -#define MAX3421_INTR_PIN 20 // D9 -#define MAX3421_INTR_EIC_ID 4 // EIC4 #ifdef __cplusplus } diff --git a/hw/bsp/samd51/family.c b/hw/bsp/samd51/family.c index f9e1718d0..2cf00c7af 100644 --- a/hw/bsp/samd51/family.c +++ b/hw/bsp/samd51/family.c @@ -77,11 +77,10 @@ void USB_3_Handler(void) { //--------------------------------------------------------------------+ #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 -static void max3421_init(void); - #define MAX3421_SERCOM TU_XSTRCAT(SERCOM, MAX3421_SERCOM_ID) #define MAX3421_EIC_Handler TU_XSTRCAT3(EIC_, MAX3421_INTR_EIC_ID, _Handler) +static void max3421_init(void); #endif void board_init(void) { @@ -223,7 +222,8 @@ static void max3421_init(void) { while (sercom->SPI.SYNCBUSY.bit.SWRST); // Set up SPI in master mode, MSB first, SPI mode 0 - sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE(3) | SERCOM_SPI_CTRLA_DOPO(MAX3421_MOSI_PAD) | SERCOM_SPI_CTRLA_DIPO(MAX3421_MISO_PAD); + sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_DOPO(MAX3421_TX_PAD) | SERCOM_SPI_CTRLA_DIPO(MAX3421_RX_PAD) | + SERCOM_SPI_CTRLA_MODE(3); sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN; while (sercom->SPI.SYNCBUSY.bit.CTRLB == 1); @@ -234,15 +234,15 @@ static void max3421_init(void) { // Configure PA12 as MOSI (PAD0), PA13 as SCK (PAD1), PA14 as MISO (PAD2), function C (sercom) gpio_set_pin_direction(MAX3421_SCK_PIN, GPIO_DIRECTION_OUT); gpio_set_pin_pull_mode(MAX3421_SCK_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(MAX3421_SCK_PIN, 2); + gpio_set_pin_function(MAX3421_SCK_PIN, MAX3421_SERCOM_FUNCTION); gpio_set_pin_direction(MAX3421_MOSI_PIN, GPIO_DIRECTION_OUT); gpio_set_pin_pull_mode(MAX3421_MOSI_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(MAX3421_MOSI_PIN, 2); + gpio_set_pin_function(MAX3421_MOSI_PIN, MAX3421_SERCOM_FUNCTION); gpio_set_pin_direction(MAX3421_MISO_PIN, GPIO_DIRECTION_IN); gpio_set_pin_pull_mode(MAX3421_MISO_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(MAX3421_MISO_PIN, 2); + gpio_set_pin_function(MAX3421_MISO_PIN, MAX3421_SERCOM_FUNCTION); // CS pin gpio_set_pin_direction(MAX3421_CS_PIN, GPIO_DIRECTION_OUT); @@ -269,7 +269,7 @@ static void max3421_init(void) { EIC->CTRLA.bit.ENABLE = 0; while (EIC->SYNCBUSY.bit.ENABLE); - // Configure EXTINT4 (PA20) to trigger on falling edge + // Configure EIC to trigger on falling edge volatile uint32_t * eic_config; uint8_t sense_shift; if ( MAX3421_INTR_EIC_ID < 8 ) { @@ -302,10 +302,11 @@ void MAX3421_EIC_Handler(void) { void tuh_max3421_int_api(uint8_t rhport, bool enabled) { (void) rhport; + const IRQn_Type irq = EIC_0_IRQn + MAX3421_INTR_EIC_ID; if (enabled) { - NVIC_EnableIRQ(EIC_4_IRQn); + NVIC_EnableIRQ(irq); } else { - NVIC_DisableIRQ(EIC_4_IRQn); + NVIC_DisableIRQ(irq); } } From ab9585401b9964407cbf2bc7bffdf762353817f9 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 11 Sep 2023 11:35:51 +0700 Subject: [PATCH 39/71] wrap up build cmake & make support for max3421, to enable the Host driver, 'MAX3421_HOST=1' must be added as part of make/cmake command --- .idea/cmake.xml | 6 ++-- .idea/runConfigurations/kl25.xml | 2 +- .idea/runConfigurations/lpc1857.xml | 2 +- .idea/runConfigurations/lpc4088.xml | 2 +- .idea/runConfigurations/lpc54628.xml | 10 ++++++ .idea/runConfigurations/lpc55s69.xml | 10 ++++++ .idea/runConfigurations/mcx947.xml | 2 +- .idea/runConfigurations/nrf52840.xml | 2 +- .idea/runConfigurations/nrf5340.xml | 2 +- .idea/runConfigurations/ra4m1.xml | 2 +- .idea/runConfigurations/ra6m1.xml | 2 +- .idea/runConfigurations/ra6m5.xml | 2 +- .idea/runConfigurations/rt1010.xml | 2 +- .idea/runConfigurations/rt1060.xml | 2 +- .idea/runConfigurations/samd21g18.xml | 10 ++++++ .idea/runConfigurations/samd51j19.xml | 10 ++++++ .idea/runConfigurations/stlink.xml | 2 +- .idea/runConfigurations/stm32g474.xml | 2 +- .idea/runConfigurations/stm32h743.xml | 2 +- .idea/runConfigurations/uno_r4.xml | 2 +- examples/dual/host_hid_to_device_cdc/only.txt | 1 + examples/host/bare_api/only.txt | 1 + examples/host/cdc_msc_hid/only.txt | 1 + examples/host/cdc_msc_hid/src/tusb_config.h | 3 -- examples/host/hid_controller/only.txt | 1 + examples/host/msc_file_explorer/only.txt | 1 + .../host/msc_file_explorer/src/tusb_config.h | 3 -- examples/make.mk | 13 ++++---- examples/rules.mk | 2 +- hw/bsp/family_support.cmake | 14 ++++++++ hw/bsp/nrf/family.cmake | 1 - hw/bsp/samd21/family.cmake | 1 - hw/bsp/samd21/family.mk | 32 +++++++++---------- hw/bsp/samd51/family.cmake | 1 - 34 files changed, 101 insertions(+), 50 deletions(-) create mode 100644 .idea/runConfigurations/lpc54628.xml create mode 100644 .idea/runConfigurations/lpc55s69.xml create mode 100644 .idea/runConfigurations/samd21g18.xml create mode 100644 .idea/runConfigurations/samd51j19.xml diff --git a/.idea/cmake.xml b/.idea/cmake.xml index 8d19b7624..89ec1066c 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -33,7 +33,7 @@ - + @@ -53,8 +53,8 @@ - - + + \ No newline at end of file diff --git a/.idea/runConfigurations/kl25.xml b/.idea/runConfigurations/kl25.xml index a08c20d44..66f8ea684 100644 --- a/.idea/runConfigurations/kl25.xml +++ b/.idea/runConfigurations/kl25.xml @@ -1,5 +1,5 @@ - + diff --git a/.idea/runConfigurations/lpc1857.xml b/.idea/runConfigurations/lpc1857.xml index 7525f51f7..f7d4ba402 100644 --- a/.idea/runConfigurations/lpc1857.xml +++ b/.idea/runConfigurations/lpc1857.xml @@ -1,5 +1,5 @@ - + diff --git a/.idea/runConfigurations/lpc4088.xml b/.idea/runConfigurations/lpc4088.xml index 7b32b2b85..911876903 100644 --- a/.idea/runConfigurations/lpc4088.xml +++ b/.idea/runConfigurations/lpc4088.xml @@ -1,5 +1,5 @@ - + diff --git a/.idea/runConfigurations/lpc54628.xml b/.idea/runConfigurations/lpc54628.xml new file mode 100644 index 000000000..e0047f187 --- /dev/null +++ b/.idea/runConfigurations/lpc54628.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/lpc55s69.xml b/.idea/runConfigurations/lpc55s69.xml new file mode 100644 index 000000000..d5e9b117a --- /dev/null +++ b/.idea/runConfigurations/lpc55s69.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/mcx947.xml b/.idea/runConfigurations/mcx947.xml index 77dec59f8..31e5c27dd 100644 --- a/.idea/runConfigurations/mcx947.xml +++ b/.idea/runConfigurations/mcx947.xml @@ -1,5 +1,5 @@ - + diff --git a/.idea/runConfigurations/nrf52840.xml b/.idea/runConfigurations/nrf52840.xml index 2f3f1876a..3ffa16385 100644 --- a/.idea/runConfigurations/nrf52840.xml +++ b/.idea/runConfigurations/nrf52840.xml @@ -1,5 +1,5 @@ - + diff --git a/.idea/runConfigurations/nrf5340.xml b/.idea/runConfigurations/nrf5340.xml index 98fe39d80..2f8009444 100644 --- a/.idea/runConfigurations/nrf5340.xml +++ b/.idea/runConfigurations/nrf5340.xml @@ -1,5 +1,5 @@ - + diff --git a/.idea/runConfigurations/ra4m1.xml b/.idea/runConfigurations/ra4m1.xml index 561b509a2..6135e5cf3 100644 --- a/.idea/runConfigurations/ra4m1.xml +++ b/.idea/runConfigurations/ra4m1.xml @@ -1,5 +1,5 @@ - + diff --git a/.idea/runConfigurations/ra6m1.xml b/.idea/runConfigurations/ra6m1.xml index 099510c60..0833d43b3 100644 --- a/.idea/runConfigurations/ra6m1.xml +++ b/.idea/runConfigurations/ra6m1.xml @@ -1,5 +1,5 @@ - + diff --git a/.idea/runConfigurations/ra6m5.xml b/.idea/runConfigurations/ra6m5.xml index 0cffac135..606e04e52 100644 --- a/.idea/runConfigurations/ra6m5.xml +++ b/.idea/runConfigurations/ra6m5.xml @@ -1,5 +1,5 @@ - + diff --git a/.idea/runConfigurations/rt1010.xml b/.idea/runConfigurations/rt1010.xml index 63df076b1..f4f48181c 100644 --- a/.idea/runConfigurations/rt1010.xml +++ b/.idea/runConfigurations/rt1010.xml @@ -1,5 +1,5 @@ - + diff --git a/.idea/runConfigurations/rt1060.xml b/.idea/runConfigurations/rt1060.xml index 147f197a2..3d740edeb 100644 --- a/.idea/runConfigurations/rt1060.xml +++ b/.idea/runConfigurations/rt1060.xml @@ -1,5 +1,5 @@ - + diff --git a/.idea/runConfigurations/samd21g18.xml b/.idea/runConfigurations/samd21g18.xml new file mode 100644 index 000000000..9a1e65563 --- /dev/null +++ b/.idea/runConfigurations/samd21g18.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/samd51j19.xml b/.idea/runConfigurations/samd51j19.xml new file mode 100644 index 000000000..74d0e3649 --- /dev/null +++ b/.idea/runConfigurations/samd51j19.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/stlink.xml b/.idea/runConfigurations/stlink.xml index 7e9166d90..b29b63f1a 100644 --- a/.idea/runConfigurations/stlink.xml +++ b/.idea/runConfigurations/stlink.xml @@ -1,5 +1,5 @@ - + diff --git a/.idea/runConfigurations/stm32g474.xml b/.idea/runConfigurations/stm32g474.xml index 2e4c4b82a..a7267fe90 100644 --- a/.idea/runConfigurations/stm32g474.xml +++ b/.idea/runConfigurations/stm32g474.xml @@ -1,5 +1,5 @@ - + diff --git a/.idea/runConfigurations/stm32h743.xml b/.idea/runConfigurations/stm32h743.xml index f0ab6e9e7..9cd142de0 100644 --- a/.idea/runConfigurations/stm32h743.xml +++ b/.idea/runConfigurations/stm32h743.xml @@ -1,5 +1,5 @@ - + diff --git a/.idea/runConfigurations/uno_r4.xml b/.idea/runConfigurations/uno_r4.xml index e9e1ebb8d..75eb3df4d 100644 --- a/.idea/runConfigurations/uno_r4.xml +++ b/.idea/runConfigurations/uno_r4.xml @@ -1,5 +1,5 @@ - + diff --git a/examples/dual/host_hid_to_device_cdc/only.txt b/examples/dual/host_hid_to_device_cdc/only.txt index a3b567f9a..cfc87eb4e 100644 --- a/examples/dual/host_hid_to_device_cdc/only.txt +++ b/examples/dual/host_hid_to_device_cdc/only.txt @@ -3,3 +3,4 @@ board:mimxrt1064_evk board:mcb1800 mcu:RP2040 mcu:ra6m5 +mcu:MAX3421 diff --git a/examples/host/bare_api/only.txt b/examples/host/bare_api/only.txt index f8aa2186f..3837ac8a2 100644 --- a/examples/host/bare_api/only.txt +++ b/examples/host/bare_api/only.txt @@ -10,3 +10,4 @@ mcu:RP2040 mcu:MSP432E4 mcu:RX65X mcu:RAXXX +mcu:MAX3421 diff --git a/examples/host/cdc_msc_hid/only.txt b/examples/host/cdc_msc_hid/only.txt index f8aa2186f..3837ac8a2 100644 --- a/examples/host/cdc_msc_hid/only.txt +++ b/examples/host/cdc_msc_hid/only.txt @@ -10,3 +10,4 @@ mcu:RP2040 mcu:MSP432E4 mcu:RX65X mcu:RAXXX +mcu:MAX3421 diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 8d3ef8891..c8e9138e3 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -38,9 +38,6 @@ // change to 1 if using pico-pio-usb as host controller for raspberry rp2040 #define CFG_TUH_RPI_PIO_USB 0 #define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB -//#elif CFG_TUSB_MCU == OPT_MCU_NRF5X -// // Use external USB controller (via SPI) MAX3421E (aka usb host shield) -// #define CFG_TUH_MAX3421 1 #endif // RHPort number used for host can be defined by board.mk, default to port 0 diff --git a/examples/host/hid_controller/only.txt b/examples/host/hid_controller/only.txt index f8aa2186f..3837ac8a2 100644 --- a/examples/host/hid_controller/only.txt +++ b/examples/host/hid_controller/only.txt @@ -10,3 +10,4 @@ mcu:RP2040 mcu:MSP432E4 mcu:RX65X mcu:RAXXX +mcu:MAX3421 diff --git a/examples/host/msc_file_explorer/only.txt b/examples/host/msc_file_explorer/only.txt index f8aa2186f..3837ac8a2 100644 --- a/examples/host/msc_file_explorer/only.txt +++ b/examples/host/msc_file_explorer/only.txt @@ -10,3 +10,4 @@ mcu:RP2040 mcu:MSP432E4 mcu:RX65X mcu:RAXXX +mcu:MAX3421 diff --git a/examples/host/msc_file_explorer/src/tusb_config.h b/examples/host/msc_file_explorer/src/tusb_config.h index e6186ba46..b4ccd8223 100644 --- a/examples/host/msc_file_explorer/src/tusb_config.h +++ b/examples/host/msc_file_explorer/src/tusb_config.h @@ -38,9 +38,6 @@ // change to 1 if using pico-pio-usb as host controller for raspberry rp2040 #define CFG_TUH_RPI_PIO_USB 0 #define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB -//#elif CFG_TUSB_MCU == OPT_MCU_NRF5X -// // Use external USB controller (via SPI) MAX3421E (aka usb host shield) -// #define CFG_TUH_MAX3421 1 #endif diff --git a/examples/make.mk b/examples/make.mk index a590e34f7..8fe4a3486 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -73,7 +73,6 @@ ifeq ($(FAMILY),) else # Include Family and Board specific defs include $(TOP)/$(FAMILY_PATH)/family.mk - SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(FAMILY_PATH)/*.c)) endif @@ -84,9 +83,6 @@ CROSS_COMPILE ?= arm-none-eabi- ifeq ($(TOOLCHAIN),iar) CC := iccarm -endif - -ifeq ($(CC),iccarm) USE_IAR = 1 endif @@ -105,13 +101,12 @@ endif #-------------- Source files and compiler flags -------------- # tinyusb makefile include $(TOP)/src/tinyusb.mk +SRC_C += $(TINYUSB_SRC_C) # Include all source C in family & board folder SRC_C += hw/bsp/board.c SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(BOARD_PATH)/*.c)) -SRC_C += $(TINYUSB_SRC_C) - INC += \ $(TOP)/$(FAMILY_PATH) \ $(TOP)/src \ @@ -119,6 +114,12 @@ INC += \ BOARD_UPPER = $(subst a,A,$(subst b,B,$(subst c,C,$(subst d,D,$(subst e,E,$(subst f,F,$(subst g,G,$(subst h,H,$(subst i,I,$(subst j,J,$(subst k,K,$(subst l,L,$(subst m,M,$(subst n,N,$(subst o,O,$(subst p,P,$(subst q,Q,$(subst r,R,$(subst s,S,$(subst t,T,$(subst u,U,$(subst v,V,$(subst w,W,$(subst x,X,$(subst y,Y,$(subst z,Z,$(subst -,_,$(BOARD)))))))))))))))))))))))))))) CFLAGS += -DBOARD_$(BOARD_UPPER) +# use max3421 as host controller +ifeq (${MAX3421_HOST},1) + SRC_C += src/portable/analog/max3421/hcd_max3421.c + CFLAGS += -DCFG_TUH_MAX3421=1 +endif + # Log level is mapped to TUSB DEBUG option ifneq ($(LOG),) CMAKE_DEFSYM += -DLOG=$(LOG) diff --git a/examples/rules.mk b/examples/rules.mk index 44d6b84c8..227849a18 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -72,7 +72,7 @@ endif # get depenecies .PHONY: get-deps get-deps: - $(PYTHON) $(TOP)/tools/get_deps.py $(DEPS_SUBMODULES) + $(PYTHON) $(TOP)/tools/get_deps.py ${FAMILY} .PHONY: size size: $(BUILD)/$(PROJECT).elf diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 1cbcfb2a7..642282b0e 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -253,6 +253,15 @@ function(family_add_tinyusb TARGET OPT_MCU RTOS) # link tinyusb with freeRTOS kernel target_link_libraries(${TARGET}-tinyusb PUBLIC freertos_kernel) endif () + + # use max3421 as host controller + if (MAX3421_HOST STREQUAL "1") + target_compile_definitions(${TARGET}-tinyusb_config INTERFACE CFG_TUH_MAX3421=1) + target_sources(${TARGET}-tinyusb PUBLIC + ${TOP}/src/portable/analog/max3421/hcd_max3421.c + ) + endif () + endfunction() @@ -438,5 +447,10 @@ if (NOT FAMILY_MCUS) set(FAMILY_MCUS ${FAMILY}) endif() +# if use max3421 as host controller, expand FAMILY_MCUS to include max3421 +if (MAX3421_HOST STREQUAL "1") + set(FAMILY_MCUS ${FAMILY_MCUS} MAX3421) +endif () + # save it in case of re-inclusion set(FAMILY_MCUS ${FAMILY_MCUS} CACHE INTERNAL "") diff --git a/hw/bsp/nrf/family.cmake b/hw/bsp/nrf/family.cmake index ff6b882ce..99d9ac6dd 100644 --- a/hw/bsp/nrf/family.cmake +++ b/hw/bsp/nrf/family.cmake @@ -124,7 +124,6 @@ function(family_configure_example TARGET RTOS) family_add_tinyusb(${TARGET} OPT_MCU_NRF5X ${RTOS}) target_sources(${TARGET}-tinyusb PUBLIC ${TOP}/src/portable/nordic/nrf5x/dcd_nrf5x.c - ${TOP}/src/portable/analog/max3421/hcd_max3421.c ) target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) diff --git a/hw/bsp/samd21/family.cmake b/hw/bsp/samd21/family.cmake index ffbf687a1..07186934a 100644 --- a/hw/bsp/samd21/family.cmake +++ b/hw/bsp/samd21/family.cmake @@ -94,7 +94,6 @@ function(family_configure_example TARGET RTOS) family_add_tinyusb(${TARGET} OPT_MCU_SAMD21 ${RTOS}) target_sources(${TARGET}-tinyusb PUBLIC ${TOP}/src/portable/microchip/samd/dcd_samd.c - ${TOP}/src/portable/analog/max3421/hcd_max3421.c ) target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) diff --git a/hw/bsp/samd21/family.mk b/hw/bsp/samd21/family.mk index 49a1a781a..79c63812d 100644 --- a/hw/bsp/samd21/family.mk +++ b/hw/bsp/samd21/family.mk @@ -1,5 +1,5 @@ UF2_FAMILY_ID = 0x68ed2b88 -DEPS_SUBMODULES += hw/mcu/microchip +SDK_DIR = hw/mcu/microchip/samd21 include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m0plus @@ -18,24 +18,24 @@ CFLAGS_SKIP += -Wcast-qual SRC_C += \ src/portable/microchip/samd/dcd_samd.c \ - hw/mcu/microchip/samd21/gcc/gcc/startup_samd21.c \ - hw/mcu/microchip/samd21/gcc/system_samd21.c \ - hw/mcu/microchip/samd21/hpl/gclk/hpl_gclk.c \ - hw/mcu/microchip/samd21/hpl/pm/hpl_pm.c \ - hw/mcu/microchip/samd21/hpl/sysctrl/hpl_sysctrl.c \ - hw/mcu/microchip/samd21/hal/src/hal_atomic.c + ${SDK_DIR}/gcc/gcc/startup_samd21.c \ + ${SDK_DIR}/gcc/system_samd21.c \ + ${SDK_DIR}/hpl/gclk/hpl_gclk.c \ + ${SDK_DIR}/hpl/pm/hpl_pm.c \ + ${SDK_DIR}/hpl/sysctrl/hpl_sysctrl.c \ + ${SDK_DIR}/hal/src/hal_atomic.c INC += \ $(TOP)/$(BOARD_PATH) \ - $(TOP)/hw/mcu/microchip/samd21/ \ - $(TOP)/hw/mcu/microchip/samd21/config \ - $(TOP)/hw/mcu/microchip/samd21/include \ - $(TOP)/hw/mcu/microchip/samd21/hal/include \ - $(TOP)/hw/mcu/microchip/samd21/hal/utils/include \ - $(TOP)/hw/mcu/microchip/samd21/hpl/pm/ \ - $(TOP)/hw/mcu/microchip/samd21/hpl/port \ - $(TOP)/hw/mcu/microchip/samd21/hri \ - $(TOP)/hw/mcu/microchip/samd21/CMSIS/Include + $(TOP)/${SDK_DIR}/ \ + $(TOP)/${SDK_DIR}/config \ + $(TOP)/${SDK_DIR}/include \ + $(TOP)/${SDK_DIR}/hal/include \ + $(TOP)/${SDK_DIR}/hal/utils/include \ + $(TOP)/${SDK_DIR}/hpl/pm/ \ + $(TOP)/${SDK_DIR}/hpl/port \ + $(TOP)/${SDK_DIR}/hri \ + $(TOP)/${SDK_DIR}/CMSIS/Include # flash using bossac at least version 1.8 # can be found in arduino15/packages/arduino/tools/bossac/ diff --git a/hw/bsp/samd51/family.cmake b/hw/bsp/samd51/family.cmake index 1dce483fd..fa9586066 100644 --- a/hw/bsp/samd51/family.cmake +++ b/hw/bsp/samd51/family.cmake @@ -93,7 +93,6 @@ function(family_configure_example TARGET RTOS) family_add_tinyusb(${TARGET} OPT_MCU_SAMD51 ${RTOS}) target_sources(${TARGET}-tinyusb PUBLIC ${TOP}/src/portable/microchip/samd/dcd_samd.c - ${TOP}/src/portable/analog/max3421/hcd_max3421.c ) target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) From 1eb0cb0c65077607944665013d4c60f8c8512ec5 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 11 Sep 2023 15:45:26 +0700 Subject: [PATCH 40/71] update readme to include max3421 support --- .github/workflows/build_arm.yml | 1 - .github/workflows/cmake_arm.yml | 1 + README.rst | 8 ++++++-- hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake | 3 +++ hw/bsp/nrf/boards/feather_nrf52840_express/board.mk | 3 +++ 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_arm.yml b/.github/workflows/build_arm.yml index 70385bc1b..975f351a0 100644 --- a/.github/workflows/build_arm.yml +++ b/.github/workflows/build_arm.yml @@ -38,7 +38,6 @@ jobs: - 'lpc11 lpc13 lpc15 lpc17' - 'lpc51 lpc54' - 'mm32 msp432e4' - - 'nrf' - 'samd11 same5x saml2x' - 'stm32f2 stm32f3' - 'stm32l0 stm32u5 stm32wb' diff --git a/.github/workflows/cmake_arm.yml b/.github/workflows/cmake_arm.yml index e3a00f9c5..4b788a213 100644 --- a/.github/workflows/cmake_arm.yml +++ b/.github/workflows/cmake_arm.yml @@ -38,6 +38,7 @@ jobs: - 'lpc18 lpc40 lpc43' - 'lpc55' - 'mcx' + - 'nrf' - 'ra' - 'rp2040' - 'samd21' diff --git a/README.rst b/README.rst index d72cdb149..aef310b98 100644 --- a/README.rst +++ b/README.rst @@ -33,6 +33,7 @@ Supported MCUs The stack supports the following MCUs: - **Allwinner:** F1C100s/F1C200s +- **Analog:** MAX3421e (aka Arduino usb host shield) - **Broadcom:** BCM2837, BCM2711 - **Dialog:** DA1469x - **Espressif:** ESP32-S2, ESP32-S3 @@ -46,12 +47,13 @@ The stack supports the following MCUs: - iMX RT Series: RT10xx, RT11xx - Kinetis: KL25, K32L2 - LPC Series: 11u, 13, 15, 17, 18, 40, 43, 51u, 54, 55 + - MCX: N9x - **Raspberry Pi:** RP2040 - **Renesas:** - - RX Series: 63N, 65N, 72N - - RA Series: RA4M1, RA4M3 + - RX Series: 63n, 65n, 72n + - RA Series: 4m1, 4m3, 6m1, 6m5 - **Silabs:** EFM32GG - **Sony:** CXD56 @@ -87,6 +89,8 @@ Host Stack - Human Interface Device (HID): Keyboard, Mouse, Generic - Mass Storage Class (MSC) +- Communication Device Class: CDC-ACM +- Vendor serial over USB: FTDI, CP210x - Hub with multiple-level support Similar to the Device Stack, if you have a special requirement, `usbh_app_driver_get_cb()` can be used to write your own class driver without modifying the stack. diff --git a/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake b/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake index 78ed98225..ce6da8b43 100644 --- a/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake +++ b/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake @@ -2,5 +2,8 @@ set(MCU_VARIANT nrf52840) #set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld) set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52840_xxaa.ld) +# enable max3421 host driver for this board +set(MAX3421_HOST 1) + function(update_board TARGET) endfunction() diff --git a/hw/bsp/nrf/boards/feather_nrf52840_express/board.mk b/hw/bsp/nrf/boards/feather_nrf52840_express/board.mk index b80807963..1f3772caf 100644 --- a/hw/bsp/nrf/boards/feather_nrf52840_express/board.mk +++ b/hw/bsp/nrf/boards/feather_nrf52840_express/board.mk @@ -1,6 +1,9 @@ MCU_VARIANT = nrf52840 CFLAGS += -DNRF52840_XXAA +# enable max3421 host driver for this board +#MAX3421_HOST = 1 + # All source paths should be relative to the top level. LD_FILE = hw/bsp/nrf/linker/nrf52840_s140_v6.ld From f55052b61f548f0f28ec8c1b9b706f34424c58d1 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 11 Sep 2023 16:44:06 +0700 Subject: [PATCH 41/71] enable max3421 host for feather nrf52840 with makefile --- .../boards/feather_nrf52840_express/board.mk | 2 +- hw/bsp/nrf/family.mk | 26 +++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/hw/bsp/nrf/boards/feather_nrf52840_express/board.mk b/hw/bsp/nrf/boards/feather_nrf52840_express/board.mk index 1f3772caf..488f07b82 100644 --- a/hw/bsp/nrf/boards/feather_nrf52840_express/board.mk +++ b/hw/bsp/nrf/boards/feather_nrf52840_express/board.mk @@ -2,7 +2,7 @@ MCU_VARIANT = nrf52840 CFLAGS += -DNRF52840_XXAA # enable max3421 host driver for this board -#MAX3421_HOST = 1 +MAX3421_HOST = 1 # All source paths should be relative to the top level. LD_FILE = hw/bsp/nrf/linker/nrf52840_s140_v6.ld diff --git a/hw/bsp/nrf/family.mk b/hw/bsp/nrf/family.mk index cdcfe39bd..4b53b9a4f 100644 --- a/hw/bsp/nrf/family.mk +++ b/hw/bsp/nrf/family.mk @@ -1,5 +1,6 @@ UF2_FAMILY_ID = 0xADA52840 -DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/nordic/nrfx + +NRFX_DIR = hw/mcu/nordic/nrfx include $(TOP)/$(BOARD_PATH)/board.mk @@ -14,24 +15,27 @@ CFLAGS += \ # suppress warning caused by vendor mcu driver CFLAGS += -Wno-error=undef -Wno-error=unused-parameter -Wno-error=cast-align -Wno-error=cast-qual -Wno-error=redundant-decls -LDFLAGS += -L$(TOP)/hw/mcu/nordic/nrfx/mdk +LDFLAGS += -L$(TOP)/${NRFX_DIR}/mdk SRC_C += \ src/portable/nordic/nrf5x/dcd_nrf5x.c \ - hw/mcu/nordic/nrfx/drivers/src/nrfx_power.c \ - hw/mcu/nordic/nrfx/drivers/src/nrfx_uarte.c \ - hw/mcu/nordic/nrfx/mdk/system_$(MCU_VARIANT).c + ${NRFX_DIR}/helpers/nrfx_flag32_allocator.c \ + ${NRFX_DIR}/drivers/src/nrfx_gpiote.c \ + ${NRFX_DIR}/drivers/src/nrfx_power.c \ + ${NRFX_DIR}/drivers/src/nrfx_spim.c \ + ${NRFX_DIR}/drivers/src/nrfx_uarte.c \ + ${NRFX_DIR}/mdk/system_$(MCU_VARIANT).c INC += \ $(TOP)/$(BOARD_PATH) \ $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ - $(TOP)/hw/mcu/nordic/nrfx \ - $(TOP)/hw/mcu/nordic/nrfx/mdk \ - $(TOP)/hw/mcu/nordic/nrfx/hal \ - $(TOP)/hw/mcu/nordic/nrfx/drivers/include \ - $(TOP)/hw/mcu/nordic/nrfx/drivers/src \ + $(TOP)/${NRFX_DIR} \ + $(TOP)/${NRFX_DIR}/mdk \ + $(TOP)/${NRFX_DIR}/hal \ + $(TOP)/${NRFX_DIR}/drivers/include \ + $(TOP)/${NRFX_DIR}/drivers/src \ -SRC_S += hw/mcu/nordic/nrfx/mdk/gcc_startup_$(MCU_VARIANT).S +SRC_S += ${NRFX_DIR}/mdk/gcc_startup_$(MCU_VARIANT).S ASFLAGS += -D__HEAP_SIZE=0 From 81cd9951080181234f20d81c831ca0595d499577 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 18 Sep 2023 22:15:31 +0700 Subject: [PATCH 42/71] add default CFG_TUH_MAX3421 = 0, default spi speed for samd21/samd51 to 12Mhz --- hw/bsp/samd21/family.c | 3 ++- hw/bsp/samd51/family.c | 11 +++++++++-- src/portable/analog/max3421/hcd_max3421.c | 2 +- src/tusb_option.h | 22 +++++++++++++--------- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/hw/bsp/samd21/family.c b/hw/bsp/samd21/family.c index cfe66b8dc..395155548 100644 --- a/hw/bsp/samd21/family.c +++ b/hw/bsp/samd21/family.c @@ -269,7 +269,8 @@ uint32_t board_millis(void) { static void max3421_init(void) { //------------- SPI Init -------------// - uint32_t const baudrate = 4000000u; + // MAX3421E max SPI clock is 26MHz however SAMD can only work reliably at 12 Mhz + uint32_t const baudrate = 12000000u; // Enable the APB clock for SERCOM PM->APBCMASK.reg |= 1u << (PM_APBCMASK_SERCOM0_Pos + MAX3421_SERCOM_ID); diff --git a/hw/bsp/samd51/family.c b/hw/bsp/samd51/family.c index 2cf00c7af..c1b914a02 100644 --- a/hw/bsp/samd51/family.c +++ b/hw/bsp/samd51/family.c @@ -183,7 +183,9 @@ uint32_t board_millis(void) { static void max3421_init(void) { //------------- SPI Init -------------// - uint32_t const baudrate = 4000000u; + + // MAX3421E max SPI clock is 26MHz however SAMD can only work reliably at 12 Mhz + uint32_t const baudrate = 12000000u; struct { volatile uint32_t *mck_apb; @@ -229,7 +231,12 @@ static void max3421_init(void) { while (sercom->SPI.SYNCBUSY.bit.CTRLB == 1); // Set the baud rate - sercom->SPI.BAUD.reg = (uint8_t) (SystemCoreClock / (2 * baudrate) - 1); + uint8_t baud_reg = (uint8_t) (SystemCoreClock / (2 * baudrate)); + if (baud_reg) { + baud_reg--; + } + + sercom->SPI.BAUD.reg = baud_reg; // Configure PA12 as MOSI (PAD0), PA13 as SCK (PAD1), PA14 as MISO (PAD2), function C (sercom) gpio_set_pin_direction(MAX3421_SCK_PIN, GPIO_DIRECTION_OUT); diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 238b518a0..f3f76fd58 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -263,7 +263,7 @@ static void fifo_read(uint8_t rhport, uint8_t * buffer, uint16_t len, bool in_is max3421_spi_lock(rhport, in_isr); - tuh_max3421_spi_xfer_api(rhport, ®, 1, &hirq, 0); + tuh_max3421_spi_xfer_api(rhport, ®, 1, &hirq, 1); _hcd_data.hirq = hirq; tuh_max3421_spi_xfer_api(rhport, NULL, 0, buffer, len); diff --git a/src/tusb_option.h b/src/tusb_option.h index c72117850..a41f5a07e 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -424,11 +424,11 @@ //------------- CLASS -------------// #ifndef CFG_TUH_HUB -#define CFG_TUH_HUB 0 + #define CFG_TUH_HUB 0 #endif #ifndef CFG_TUH_CDC -#define CFG_TUH_CDC 0 + #define CFG_TUH_CDC 0 #endif #ifndef CFG_TUH_CDC_FTDI @@ -442,34 +442,38 @@ #endif #ifndef CFG_TUH_HID -#define CFG_TUH_HID 0 + #define CFG_TUH_HID 0 #endif #ifndef CFG_TUH_MIDI -#define CFG_TUH_MIDI 0 + #define CFG_TUH_MIDI 0 #endif #ifndef CFG_TUH_MSC -#define CFG_TUH_MSC 0 + #define CFG_TUH_MSC 0 #endif #ifndef CFG_TUH_VENDOR -#define CFG_TUH_VENDOR 0 + #define CFG_TUH_VENDOR 0 #endif #ifndef CFG_TUH_API_EDPT_XFER -#define CFG_TUH_API_EDPT_XFER 0 + #define CFG_TUH_API_EDPT_XFER 0 #endif // Enable PIO-USB software host controller #ifndef CFG_TUH_RPI_PIO_USB -#define CFG_TUH_RPI_PIO_USB 0 + #define CFG_TUH_RPI_PIO_USB 0 #endif #ifndef CFG_TUD_RPI_PIO_USB -#define CFG_TUD_RPI_PIO_USB 0 + #define CFG_TUD_RPI_PIO_USB 0 #endif +// MAX3421 Host controller option +#ifndef CFG_TUH_MAX3421 + #define CFG_TUH_MAX3421 0 +#endif //--------------------------------------------------------------------+ // TypeC Options (Default) From 71a2e8a36d7c98169359e6320e39bfdf3b84793f Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 19 Sep 2023 17:59:38 +0700 Subject: [PATCH 43/71] addding cmake support for u5 --- .idea/cmake.xml | 1 + hw/bsp/stm32g4/family.cmake | 10 +- .../stm32u5/boards/stm32u575eval/board.cmake | 10 + hw/bsp/stm32u5/boards/stm32u575eval/board.mk | 2 +- hw/bsp/stm32u5/family.c | 11 + hw/bsp/stm32u5/family.cmake | 216 ++++++++++++++++++ hw/bsp/stm32u5/family.mk | 6 +- 7 files changed, 244 insertions(+), 12 deletions(-) create mode 100644 hw/bsp/stm32u5/boards/stm32u575eval/board.cmake create mode 100644 hw/bsp/stm32u5/family.cmake diff --git a/.idea/cmake.xml b/.idea/cmake.xml index 89ec1066c..112449335 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -55,6 +55,7 @@ + \ No newline at end of file diff --git a/hw/bsp/stm32g4/family.cmake b/hw/bsp/stm32g4/family.cmake index 675a96c74..fa7badc02 100644 --- a/hw/bsp/stm32g4/family.cmake +++ b/hw/bsp/stm32g4/family.cmake @@ -36,10 +36,10 @@ function(add_board_target BOARD_TARGET) ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_cortex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr_ex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} @@ -50,11 +50,6 @@ function(add_board_target BOARD_TARGET) ${ST_CMSIS}/Include ${ST_HAL_DRIVER}/Inc ) - target_compile_options(${BOARD_TARGET} PUBLIC - ) - target_compile_definitions(${BOARD_TARGET} PUBLIC - ) - update_board(${BOARD_TARGET}) if (CMAKE_C_COMPILER_ID STREQUAL "GNU") @@ -62,8 +57,7 @@ function(add_board_target BOARD_TARGET) "LINKER:--script=${LD_FILE_GNU}" -nostartfiles # nanolib - --specs=nosys.specs - --specs=nano.specs + --specs=nosys.specs --specs=nano.specs ) elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") target_link_options(${BOARD_TARGET} PUBLIC diff --git a/hw/bsp/stm32u5/boards/stm32u575eval/board.cmake b/hw/bsp/stm32u5/boards/stm32u575eval/board.cmake new file mode 100644 index 000000000..57ba85c71 --- /dev/null +++ b/hw/bsp/stm32u5/boards/stm32u575eval/board.cmake @@ -0,0 +1,10 @@ +set(MCU_VARIANT stm32u575xx) +set(JLINK_DEVICE stm32u575ai) + +set(LD_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/linker/STM32U575xx_FLASH.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + STM32U575xx + ) +endfunction() diff --git a/hw/bsp/stm32u5/boards/stm32u575eval/board.mk b/hw/bsp/stm32u5/boards/stm32u575eval/board.mk index 19cd2a5b0..a75b2af78 100644 --- a/hw/bsp/stm32u5/boards/stm32u575eval/board.mk +++ b/hw/bsp/stm32u5/boards/stm32u575eval/board.mk @@ -7,4 +7,4 @@ LD_FILE = $(BOARD_PATH)/STM32U575AIIXQ_FLASH.ld SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u575xx.s # For flash-jlink target -JLINK_DEVICE = stm32u575 +JLINK_DEVICE = stm32u575ai diff --git a/hw/bsp/stm32u5/family.c b/hw/bsp/stm32u5/family.c index a30d886aa..1e1b9011e 100644 --- a/hw/bsp/stm32u5/family.c +++ b/hw/bsp/stm32u5/family.c @@ -25,7 +25,18 @@ * This file is part of the TinyUSB stack. */ +// Suppress warning caused by mcu driver +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wundef" +#endif + #include "stm32u5xx_hal.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + #include "bsp/board_api.h" #include "board.h" diff --git a/hw/bsp/stm32u5/family.cmake b/hw/bsp/stm32u5/family.cmake new file mode 100644 index 000000000..2aa7d392b --- /dev/null +++ b/hw/bsp/stm32u5/family.cmake @@ -0,0 +1,216 @@ +include_guard() + +if (NOT BOARD) + message(FATAL_ERROR "BOARD not specified") +endif () + +set(ST_FAMILY u5) +set(ST_PREFIX stm32${ST_FAMILY}xx) + +set(ST_HAL_DRIVER ${TOP}/hw/mcu/st/stm32${ST_FAMILY}xx_hal_driver) +set(ST_CMSIS ${TOP}/hw/mcu/st/cmsis_device_${ST_FAMILY}) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_PROCESSOR cortex-m33 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/tools/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS STM32U5 CACHE INTERNAL "") + + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (NOT TARGET ${BOARD_TARGET}) + # Startup & Linker script + set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) + set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) + set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) + + add_library(${BOARD_TARGET} STATIC + ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_cortex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMSIS_5}/CMSIS/Core/Include + ${ST_CMSIS}/Include + ${ST_HAL_DRIVER}/Inc + ) + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + # nanolib + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_STM32G4 ${RTOS}) + target_sources(${TARGET}-tinyusb PUBLIC + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + #${TOP}/src/portable/st/typec/typec_stm32.c + ) + target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) + + # Link dependencies + target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb) + + # Flashing + family_flash_stlink(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() +include_guard() + +if (NOT BOARD) + message(FATAL_ERROR "BOARD not specified") +endif () + +set(ST_FAMILY u5) +set(ST_PREFIX stm32${ST_FAMILY}xx) + +set(ST_HAL_DRIVER ${TOP}/hw/mcu/st/stm32${ST_FAMILY}xx_hal_driver) +set(ST_CMSIS ${TOP}/hw/mcu/st/cmsis_device_${ST_FAMILY}) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_PROCESSOR cortex-m33 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/tools/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS STM32U5 CACHE INTERNAL "") + + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (NOT TARGET ${BOARD_TARGET}) + # Startup & Linker script + set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) + set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) + set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) + + add_library(${BOARD_TARGET} STATIC + ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_cortex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMSIS_5}/CMSIS/Core/Include + ${ST_CMSIS}/Include + ${ST_HAL_DRIVER}/Inc + ) + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + # nanolib + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_STM32G4 ${RTOS}) + target_sources(${TARGET}-tinyusb PUBLIC + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + #${TOP}/src/portable/st/typec/typec_stm32.c + ) + target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) + + # Link dependencies + target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb) + + # Flashing + family_flash_stlink(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/stm32u5/family.mk b/hw/bsp/stm32u5/family.mk index 9174fe96a..902290b90 100644 --- a/hw/bsp/stm32u5/family.mk +++ b/hw/bsp/stm32u5/family.mk @@ -20,11 +20,11 @@ SRC_C += \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c INC += \ From 8cdcd0fa9d1530c88637e01924a4218f8106fc3a Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 19 Sep 2023 18:33:59 +0700 Subject: [PATCH 44/71] fix build and add u5 to ci --- .github/workflows/build_arm.yml | 2 +- .github/workflows/cmake_arm.yml | 1 + .../stm32u5/FreeRTOSConfig/FreeRTOSConfig.h | 165 ++++++++++++++++++ hw/bsp/stm32u5/family.c | 46 ++--- hw/bsp/stm32u5/family.cmake | 110 +----------- 5 files changed, 187 insertions(+), 137 deletions(-) create mode 100644 hw/bsp/stm32u5/FreeRTOSConfig/FreeRTOSConfig.h diff --git a/.github/workflows/build_arm.yml b/.github/workflows/build_arm.yml index 975f351a0..997fb7da9 100644 --- a/.github/workflows/build_arm.yml +++ b/.github/workflows/build_arm.yml @@ -40,7 +40,7 @@ jobs: - 'mm32 msp432e4' - 'samd11 same5x saml2x' - 'stm32f2 stm32f3' - - 'stm32l0 stm32u5 stm32wb' + - 'stm32l0 stm32wb' - 'tm4c123 xmc4000' steps: - name: Setup Python diff --git a/.github/workflows/cmake_arm.yml b/.github/workflows/cmake_arm.yml index 4b788a213..192bf957a 100644 --- a/.github/workflows/cmake_arm.yml +++ b/.github/workflows/cmake_arm.yml @@ -51,6 +51,7 @@ jobs: - 'stm32g4' - 'stm32h7' - 'stm32l4' + - 'stm32u5' steps: - name: Setup Python uses: actions/setup-python@v4 diff --git a/hw/bsp/stm32u5/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/stm32u5/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..138fc6ba6 --- /dev/null +++ b/hw/bsp/stm32u5/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,165 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + #include "stm32u5xx.h" +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* Define to trap errors during development. */ +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 +#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) + #define configASSERT(_exp) \ + do {\ + if ( !(_exp) ) { \ + volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ + if ( (*ARM_CM_DHCSR) & 1UL ) { /* Only halt mcu if debugger is attached */ \ + taskDISABLE_INTERRUPTS(); \ + __asm("BKPT #0\n"); \ + }\ + }\ + } while(0) +#else + #define configASSERT( x ) +#endif + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +#define configPRIO_BITS 4 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< Date: Tue, 19 Sep 2023 18:38:47 +0700 Subject: [PATCH 45/71] minor indent --- hw/bsp/stm32u5/family.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/bsp/stm32u5/family.c b/hw/bsp/stm32u5/family.c index 5e4379f9c..d8e58d293 100644 --- a/hw/bsp/stm32u5/family.c +++ b/hw/bsp/stm32u5/family.c @@ -67,7 +67,7 @@ void board_init(void) { __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); - UART_CLK_EN(); + UART_CLK_EN(); #if CFG_TUSB_OS == OPT_OS_NONE // 1ms tick timer @@ -154,7 +154,7 @@ void board_init(void) { HAL_PWREx_EnableVddUSB(); /* USB_OTG_FS clock enable */ - __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); } //--------------------------------------------------------------------+ From 9d0251f7a6751a0d998da4fad81a35a043608275 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 19 Sep 2023 15:42:52 +0200 Subject: [PATCH 46/71] Fix UAC interleaved copy. --- src/class/audio/audio_device.c | 113 +++++++++++++++------------------ 1 file changed, 51 insertions(+), 62 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 1a7ce7870..0e4220f4f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -631,68 +631,59 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t // Decoding according to 2.3.1.5 Audio Streams // Helper function -static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, void * dst, uint8_t * dst_end, uint8_t * src, uint8_t const n_ff_used) +static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, uint8_t * dst, uint8_t * dst_end, uint8_t * src, uint8_t const n_ff_used) { - // This function is an optimized version of - // while((uint8_t *)dst < dst_end) - // { - // memcpy(dst, src, nBytesToCopy); - // dst = (uint8_t *)dst + nBytesToCopy; - // src += nBytesToCopy * n_ff_used; - // } - - // Optimize for fast half word copies - typedef struct{ - uint16_t val; - } __attribute((__packed__)) unaligned_uint16_t; - - // Optimize for fast word copies - typedef struct{ - uint32_t val; - } __attribute((__packed__)) unaligned_uint32_t; + // Due to one FIFO contains 2 channels, data always aligned to (nBytesToCopy * 2) switch (nBytesToCopy) { case 1: while((uint8_t *)dst < dst_end) { - *(uint8_t *)dst++ = *src; - src += n_ff_used; + *(uint16_t*)dst = *(uint16_t*)src; + src += 2; + dst += 2; + src += 2 * (n_ff_used - 1); } break; case 2: while((uint8_t *)dst < dst_end) { - *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; - dst += 2; - src += 2 * n_ff_used; + *(uint32_t*)dst = *(uint32_t*)src; + src += 4; + dst += 4; + src += 4 * (n_ff_used - 1); } break; case 3: while((uint8_t *)dst < dst_end) { - // memcpy(dst, src, 3); - // dst = (uint8_t *)dst + 3; - // src += 3 * n_ff_used; - - // TODO: Is there a faster way to copy 3 bytes? - *(uint8_t *)dst++ = *src++; - *(uint8_t *)dst++ = *src++; - *(uint8_t *)dst++ = *src++; - - src += 3 * (n_ff_used - 1); + *(uint16_t*)dst = *(uint16_t*)src; + src += 2; + dst += 2; + *(uint16_t*)dst = *(uint16_t*)src; + src += 2; + dst += 2; + *(uint16_t*)dst = *(uint16_t*)src; + src += 2; + dst += 2; + src += 6 * (n_ff_used - 1); } break; case 4: while((uint8_t *)dst < dst_end) { - *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; + *(uint32_t*)dst++ = *(uint32_t*)src++; + src += 4; dst += 4; - src += 4 * n_ff_used; + *(uint32_t*)dst++ = *(uint32_t*)src++; + src += 4; + dst += 4; + src += 8 * (n_ff_used - 1); } break; } @@ -946,57 +937,55 @@ range [-1, +1) // Helper function static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, uint8_t * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) { - // Optimize for fast half word copies - typedef struct{ - uint16_t val; - } __attribute((__packed__)) unaligned_uint16_t; - - // Optimize for fast word copies - typedef struct{ - uint32_t val; - } __attribute((__packed__)) unaligned_uint32_t; - + // Due to one FIFO contains 2 channels, data always aligned to (nBytesToCopy * 2) switch (nBytesToCopy) { case 1: while(src < src_end) { - *dst = *src++; - dst += n_ff_used; + *(uint16_t*)dst = *(uint16_t*)src; + src += 2; + dst += 2; + dst += 2 * (n_ff_used - 1); } break; case 2: while(src < src_end) { - *(unaligned_uint16_t*)dst = *(unaligned_uint16_t*)src; - src += 2; - dst += 2 * n_ff_used; + *(uint32_t*)dst = *(uint32_t*)src; + src += 4; + dst += 4; + dst += 4 * (n_ff_used - 1); } break; case 3: while(src < src_end) { - // memcpy(dst, src, 3); - // src = (uint8_t *)src + 3; - // dst += 3 * n_ff_used; - - // TODO: Is there a faster way to copy 3 bytes? - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - - dst += 3 * (n_ff_used - 1); + *(uint16_t*)dst = *(uint16_t*)src; + src += 2; + dst += 2; + *(uint16_t*)dst = *(uint16_t*)src; + src += 2; + dst += 2; + *(uint16_t*)dst = *(uint16_t*)src; + src += 2; + dst += 2; + dst += 6 * (n_ff_used - 1); } break; case 4: while(src < src_end) { - *(unaligned_uint32_t*)dst = *(unaligned_uint32_t*)src; + *(uint32_t*)dst++ = *(uint32_t*)src++; src += 4; - dst += 4 * n_ff_used; + dst += 4; + *(uint32_t*)dst++ = *(uint32_t*)src++; + src += 4; + dst += 4; + dst += 8 * (n_ff_used - 1); } break; } From 6be7f354c26e09a87d1b856b0e237ff82be5963f Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 19 Sep 2023 16:32:49 +0200 Subject: [PATCH 47/71] Fix cast-align. --- src/class/audio/audio_device.c | 194 +++++++++++++++------------------ 1 file changed, 89 insertions(+), 105 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 0e4220f4f..46fd6dfa9 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -631,64 +631,55 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t // Decoding according to 2.3.1.5 Audio Streams // Helper function -static inline uint8_t * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, uint8_t * dst, uint8_t * dst_end, uint8_t * src, uint8_t const n_ff_used) +static inline void * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, void * dst, const void * dst_end, void * src, uint8_t const n_ff_used) { - // Due to one FIFO contains 2 channels, data always aligned to (nBytesToCopy * 2) + uint16_t * dst16 = dst; + uint16_t * src16 = src; + const uint16_t * dst_end16 = dst_end; + uint32_t * dst32 = dst; + uint32_t * src32 = src; + const uint32_t * dst_end32 = dst_end; - switch (nBytesToCopy) + if (nBytesToCopy == 1) { - case 1: - while((uint8_t *)dst < dst_end) - { - *(uint16_t*)dst = *(uint16_t*)src; - src += 2; - dst += 2; - src += 2 * (n_ff_used - 1); - } - break; - - case 2: - while((uint8_t *)dst < dst_end) - { - *(uint32_t*)dst = *(uint32_t*)src; - src += 4; - dst += 4; - src += 4 * (n_ff_used - 1); - } - break; - - case 3: - while((uint8_t *)dst < dst_end) - { - *(uint16_t*)dst = *(uint16_t*)src; - src += 2; - dst += 2; - *(uint16_t*)dst = *(uint16_t*)src; - src += 2; - dst += 2; - *(uint16_t*)dst = *(uint16_t*)src; - src += 2; - dst += 2; - src += 6 * (n_ff_used - 1); - } - break; - - case 4: - while((uint8_t *)dst < dst_end) - { - *(uint32_t*)dst++ = *(uint32_t*)src++; - src += 4; - dst += 4; - *(uint32_t*)dst++ = *(uint32_t*)src++; - src += 4; - dst += 4; - src += 8 * (n_ff_used - 1); - } - break; + while(dst16 < dst_end16) + { + *dst16++ = *src16++; + src16 += n_ff_used - 1; + } + return src16; + } + else if (nBytesToCopy == 2) + { + while(dst32 < dst_end32) + { + *dst32++ = *src32++; + src32 += n_ff_used - 1; + } + return src32; + } + else if (nBytesToCopy == 3) + { + while(dst16 < dst_end16) + { + *dst16++ = *src16++; + *dst16++ = *src16++; + *dst16++ = *src16++; + src16 += 3 * (n_ff_used - 1); + } + return src16; + } + else // nBytesToCopy == 4 + { + while(dst32 < dst_end32) + { + *dst32++ = *src32++; + *dst32++ = *src32++; + src32 += 2 * (n_ff_used - 1); + } + return src32; } - - return src; } static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) @@ -935,62 +926,55 @@ range [-1, +1) * */ // Helper function -static inline uint8_t * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, uint8_t * src, uint8_t * src_end, uint8_t * dst, uint8_t const n_ff_used) +static inline void * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, void * src, const void * src_end, void * dst, uint8_t const n_ff_used) { // Due to one FIFO contains 2 channels, data always aligned to (nBytesToCopy * 2) - switch (nBytesToCopy) + uint16_t * dst16 = dst; + uint16_t * src16 = src; + const uint16_t * src_end16 = src_end; + uint32_t * dst32 = dst; + uint32_t * src32 = src; + const uint32_t * src_end32 = src_end; + + if (nBytesToCopy == 1) { - case 1: - while(src < src_end) - { - *(uint16_t*)dst = *(uint16_t*)src; - src += 2; - dst += 2; - dst += 2 * (n_ff_used - 1); - } - break; - - case 2: - while(src < src_end) - { - *(uint32_t*)dst = *(uint32_t*)src; - src += 4; - dst += 4; - dst += 4 * (n_ff_used - 1); - } - break; - - case 3: - while(src < src_end) - { - *(uint16_t*)dst = *(uint16_t*)src; - src += 2; - dst += 2; - *(uint16_t*)dst = *(uint16_t*)src; - src += 2; - dst += 2; - *(uint16_t*)dst = *(uint16_t*)src; - src += 2; - dst += 2; - dst += 6 * (n_ff_used - 1); - } - break; - - case 4: - while(src < src_end) - { - *(uint32_t*)dst++ = *(uint32_t*)src++; - src += 4; - dst += 4; - *(uint32_t*)dst++ = *(uint32_t*)src++; - src += 4; - dst += 4; - dst += 8 * (n_ff_used - 1); - } - break; + while(src16 < src_end16) + { + *dst16++ = *src16++; + dst16 += n_ff_used - 1; + } + return dst16; + } + else if (nBytesToCopy == 2) + { + while(src32 < src_end32) + { + *dst32++ = *src32++; + dst32 += n_ff_used - 1; + } + return dst32; + } + else if (nBytesToCopy == 3) + { + while(src16 < src_end16) + { + *dst16++ = *src16++; + *dst16++ = *src16++; + *dst16++ = *src16++; + dst16 += 3 * (n_ff_used - 1); + } + return dst16; + } + else // nBytesToCopy == 4 + { + while(src32 < src_end32) + { + *dst32++ = *src32++; + *dst32++ = *src32++; + dst32 += 2 * (n_ff_used - 1); + } + return dst32; } - - return dst; } static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audio) From a7c136c03f0c4a057f8b49c10ed9cddcecf52879 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 25 Sep 2023 16:53:11 +0700 Subject: [PATCH 48/71] adding host/cdc_msc_hid_freertos example --- .idea/cmake.xml | 19 +- examples/device/cdc_msc_freertos/Makefile | 2 +- examples/device/cdc_msc_freertos/src/main.c | 70 +++----- examples/host/bare_api/CMakeLists.txt | 5 + examples/host/cdc_msc_hid/CMakeLists.txt | 5 + .../host/cdc_msc_hid_freertos/CMakeLists.txt | 36 ++++ .../cdc_msc_hid_freertos/src/CMakeLists.txt | 4 + examples/host/cdc_msc_hid_freertos/src/main.c | 170 ++++++++++++++++++ .../cdc_msc_hid_freertos/src/tusb_config.h | 133 ++++++++++++++ examples/host/hid_controller/CMakeLists.txt | 5 + .../host/msc_file_explorer/CMakeLists.txt | 5 + examples/make.mk | 3 - .../boards/adafruit_metro_esp32s2/board.h | 8 + .../boards/espressif_kaluga_1/board.h | 8 + .../boards/espressif_s2_devkitc/board.cmake | 2 + .../boards/espressif_s2_devkitc/board.h | 45 +++++ hw/bsp/espressif/boards/family.c | 130 +++++++++++--- .../components/tinyusb_src/CMakeLists.txt | 81 +++++---- src/host/usbh.c | 2 +- src/portable/analog/max3421/hcd_max3421.c | 2 +- 20 files changed, 623 insertions(+), 112 deletions(-) create mode 100644 examples/host/cdc_msc_hid_freertos/CMakeLists.txt create mode 100644 examples/host/cdc_msc_hid_freertos/src/CMakeLists.txt create mode 100644 examples/host/cdc_msc_hid_freertos/src/main.c create mode 100644 examples/host/cdc_msc_hid_freertos/src/tusb_config.h create mode 100644 hw/bsp/espressif/boards/espressif_s2_devkitc/board.cmake create mode 100644 hw/bsp/espressif/boards/espressif_s2_devkitc/board.h diff --git a/.idea/cmake.xml b/.idea/cmake.xml index 89ec1066c..747f0fb58 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -2,23 +2,24 @@ - + - - - - + + + + + + + + - - - @@ -53,7 +54,7 @@ - + diff --git a/examples/device/cdc_msc_freertos/Makefile b/examples/device/cdc_msc_freertos/Makefile index 0bee668b7..3ac62a79c 100644 --- a/examples/device/cdc_msc_freertos/Makefile +++ b/examples/device/cdc_msc_freertos/Makefile @@ -10,7 +10,7 @@ INC += \ src/FreeRTOSConfig \ $(TOP)/hw \ $(TOP)/$(FREERTOS_SRC)/include \ - $(TOP)/$(FREERTOS_PORTABLE_SRC) + $(TOP)/$(FREERTOS_PORTABLE_SRC) \ # Example source EXAMPLE_SOURCE = \ diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index 0b115a595..1dadc4513 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -41,6 +41,7 @@ #define USBD_STACK_SIZE 4096 #else + #include "FreeRTOS.h" #include "semphr.h" #include "queue.h" @@ -54,7 +55,7 @@ #define CDC_STACK_SZIE configMINIMAL_STACK_SIZE //--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF PROTYPES +// MACRO CONSTANT TYPEDEF PROTOTYPES //--------------------------------------------------------------------+ /* Blink pattern @@ -62,7 +63,7 @@ * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, @@ -81,16 +82,15 @@ StaticTask_t cdc_taskdef; TimerHandle_t blinky_tm; -void led_blinky_cb(TimerHandle_t xTimer); -void usb_device_task(void* param); -void cdc_task(void* params); +static void led_blinky_cb(TimerHandle_t xTimer); +static void usb_device_task(void *param); +void cdc_task(void *params); //--------------------------------------------------------------------+ // Main //--------------------------------------------------------------------+ -int main(void) -{ +int main(void) { board_init(); #if configSUPPORT_STATIC_ALLOCATION @@ -104,8 +104,8 @@ int main(void) xTaskCreateStatic(cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); #else blinky_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb); - xTaskCreate( usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, NULL); - xTaskCreate( cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL); + xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); + xTaskCreate(cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES - 2, NULL); #endif xTimerStart(blinky_tm, 0); @@ -119,16 +119,14 @@ int main(void) } #if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) -void app_main(void) -{ +void app_main(void) { main(); } #endif // USB Device Driver task // This top level thread process all usb events and invoke callbacks -void usb_device_task(void* param) -{ +static void usb_device_task(void *param) { (void) param; // init device stack on configured roothub port @@ -141,8 +139,7 @@ void usb_device_task(void* param) } // RTOS forever loop - while (1) - { + while (1) { // put this thread to waiting state until there is new events tud_task(); @@ -156,35 +153,28 @@ void usb_device_task(void* param) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0); } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ +void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_SUSPENDED), 0); } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ - if (tud_mounted()) - { +void tud_resume_cb(void) { + if (tud_mounted()) { xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); - } - else - { + } else { xTimerChangePeriod(blinky_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0); } } @@ -192,20 +182,17 @@ void tud_resume_cb(void) //--------------------------------------------------------------------+ // USB CDC //--------------------------------------------------------------------+ -void cdc_task(void* params) -{ +void cdc_task(void *params) { (void) params; // RTOS forever loop - while ( 1 ) - { + while (1) { // connected() check for DTR bit // Most but not all terminal client set this when making connection // if ( tud_cdc_connected() ) { // There are data available - while ( tud_cdc_available() ) - { + while (tud_cdc_available()) { uint8_t buf[64]; // read and echo back @@ -228,32 +215,27 @@ void cdc_task(void* params) } // Invoked when cdc when line state changed e.g connected/disconnected -void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) -{ +void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { (void) itf; (void) rts; // TODO set some indicator - if ( dtr ) - { + if (dtr) { // Terminal connected - }else - { + } else { // Terminal disconnected } } // Invoked when CDC interface received data from host -void tud_cdc_rx_cb(uint8_t itf) -{ +void tud_cdc_rx_cb(uint8_t itf) { (void) itf; } //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinky_cb(TimerHandle_t xTimer) -{ +static void led_blinky_cb(TimerHandle_t xTimer) { (void) xTimer; static bool led_state = false; diff --git a/examples/host/bare_api/CMakeLists.txt b/examples/host/bare_api/CMakeLists.txt index 05398b079..76182d6fa 100644 --- a/examples/host/bare_api/CMakeLists.txt +++ b/examples/host/bare_api/CMakeLists.txt @@ -10,6 +10,11 @@ project(${PROJECT} C CXX ASM) # Checks this example is valid for the family and initializes the project family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +# Espressif has its own cmake build system +if(FAMILY STREQUAL "espressif") + return() +endif() + add_executable(${PROJECT}) # Example source diff --git a/examples/host/cdc_msc_hid/CMakeLists.txt b/examples/host/cdc_msc_hid/CMakeLists.txt index ad5751705..a7c372a34 100644 --- a/examples/host/cdc_msc_hid/CMakeLists.txt +++ b/examples/host/cdc_msc_hid/CMakeLists.txt @@ -10,6 +10,11 @@ project(${PROJECT} C CXX ASM) # Checks this example is valid for the family and initializes the project family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +# Espressif has its own cmake build system +if(FAMILY STREQUAL "espressif") + return() +endif() + add_executable(${PROJECT}) # Example source diff --git a/examples/host/cdc_msc_hid_freertos/CMakeLists.txt b/examples/host/cdc_msc_hid_freertos/CMakeLists.txt new file mode 100644 index 000000000..2e95a18e0 --- /dev/null +++ b/examples/host/cdc_msc_hid_freertos/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.17) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) + +# gets PROJECT name for the example (e.g. -) +family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) + +project(${PROJECT} C CXX ASM) + +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) + +# Espressif has its own cmake build system +if(FAMILY STREQUAL "espressif") + return() +endif() + +add_executable(${PROJECT}) + +# Example source +target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/cdc_app.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/freertos_hook.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/hid_app.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/msc_app.c + ) + +# Example include +target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + +# Configure compilation flags and libraries for the example without RTOS. +# See the corresponding function in hw/bsp/FAMILY/family.cmake for details. +family_configure_host_example(${PROJECT} freertos) diff --git a/examples/host/cdc_msc_hid_freertos/src/CMakeLists.txt b/examples/host/cdc_msc_hid_freertos/src/CMakeLists.txt new file mode 100644 index 000000000..dd7ec8e58 --- /dev/null +++ b/examples/host/cdc_msc_hid_freertos/src/CMakeLists.txt @@ -0,0 +1,4 @@ +# This file is for ESP-IDF only +idf_component_register(SRCS "hid_app.c" "main.c" + INCLUDE_DIRS "." + REQUIRES boards tinyusb_src) diff --git a/examples/host/cdc_msc_hid_freertos/src/main.c b/examples/host/cdc_msc_hid_freertos/src/main.c new file mode 100644 index 000000000..e2ddd52eb --- /dev/null +++ b/examples/host/cdc_msc_hid_freertos/src/main.c @@ -0,0 +1,170 @@ +/* + * 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. + * + */ + +#include +#include +#include + +#include "bsp/board_api.h" +#include "tusb.h" + +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + // ESP-IDF need "freertos/" prefix in include path. + // CFG_TUSB_OS_INC_PATH should be defined accordingly. + #include "freertos/FreeRTOS.h" + #include "freertos/semphr.h" + #include "freertos/queue.h" + #include "freertos/task.h" + #include "freertos/timers.h" + + #define USBH_STACK_SIZE 4096 +#else + #include "FreeRTOS.h" + #include "semphr.h" + #include "queue.h" + #include "task.h" + #include "timers.h" + + // Increase stack size when debug log is enabled + #define USBH_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) +#endif + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTOTYPES +//--------------------------------------------------------------------+ +/* Blink pattern + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +// static timer & task +#if configSUPPORT_STATIC_ALLOCATION +StaticTimer_t blinky_tmdef; + +StackType_t usb_host_stack[USBH_STACK_SIZE]; +StaticTask_t usb_host_taskdef; + +//StackType_t cdc_stack[CDC_STACK_SZIE]; +//StaticTask_t cdc_taskdef; +#endif + + +TimerHandle_t blinky_tm; + +static void led_blinky_cb(TimerHandle_t xTimer); +static void usb_host_task(void* param); + +extern void cdc_app_task(void); +extern void hid_app_task(void); + +/*------------- MAIN -------------*/ +int main(void) { + board_init(); + + printf("TinyUSB Host CDC MSC HID with FreeRTOS Example\r\n"); + +#if configSUPPORT_STATIC_ALLOCATION + // soft timer for blinky + blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef); + + // Create a task for tinyusb device stack + xTaskCreateStatic(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_host_stack, &usb_host_taskdef); + + // Create CDC task + //xTaskCreateStatic(cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); +#else + blinky_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb); + xTaskCreate( usb_device_task, "usbd", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, NULL); + //xTaskCreate( cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL); +#endif + + xTimerStart(blinky_tm, 0); + + // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 +#if !TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + vTaskStartScheduler(); +#endif + + return 0; +} + +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +void app_main(void) { + main(); +} +#endif + +// USB Host task +// This top level thread process all usb events and invoke callbacks +static void usb_host_task(void *param) { + (void) param; + + // init host stack on configured roothub port + tuh_init(BOARD_TUH_RHPORT); + + if (board_init_after_tusb) { + board_init_after_tusb(); + } + + // RTOS forever loop + while (1) { + // put this thread to waiting state until there is new events + tuh_task(); + + // following code only run if tuh_task() process at least 1 event + } +} + +//--------------------------------------------------------------------+ +// TinyUSB Callbacks +//--------------------------------------------------------------------+ + +void tuh_mount_cb(uint8_t dev_addr) { + // application set-up + printf("A device with address %d is mounted\r\n", dev_addr); +} + +void tuh_umount_cb(uint8_t dev_addr) { + // application tear-down + printf("A device with address %d is unmounted \r\n", dev_addr); +} + + +//--------------------------------------------------------------------+ +// BLINKING TASK +//--------------------------------------------------------------------+ +static void led_blinky_cb(TimerHandle_t xTimer) { + (void) xTimer; + static bool led_state = false; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} diff --git a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h new file mode 100644 index 000000000..1bed9a9b3 --- /dev/null +++ b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h @@ -0,0 +1,133 @@ +/* + * 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. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Board Specific Configuration +//--------------------------------------------------------------------+ + +#if CFG_TUSB_MCU == OPT_MCU_RP2040 + // change to 1 if using pico-pio-usb as host controller for raspberry rp2040 + #define CFG_TUH_RPI_PIO_USB 0 + #define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB +#endif + +// RHPort number used for host can be defined by board.mk, default to port 0 +#ifndef BOARD_TUH_RHPORT +#define BOARD_TUH_RHPORT 0 +#endif + +// RHPort max operational speed can defined by board.mk +#ifndef BOARD_TUH_MAX_SPEED +#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU +#error CFG_TUSB_MCU must be defined +#endif + +#ifndef CFG_TUSB_OS +#define CFG_TUSB_OS OPT_OS_FREERTOS +#endif + +// Espressif IDF requires "freertos/" prefix in include path +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#define CFG_TUSB_OS_INC_PATH freertos/ +#endif + +#ifndef CFG_TUSB_DEBUG +#define CFG_TUSB_DEBUG 0 +#endif + +// Enable Host stack +#define CFG_TUH_ENABLED 1 + +// Default is max speed that hardware controller could support with on-chip PHY +#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUH_MEM_SECTION +#define CFG_TUH_MEM_SECTION +#endif + +#ifndef CFG_TUH_MEM_ALIGN +#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// CONFIGURATION +//-------------------------------------------------------------------- + +// Size of buffer to hold descriptors and other data used for enumeration +#define CFG_TUH_ENUMERATION_BUFSIZE 256 + +#define CFG_TUH_HUB 1 // number of supported hubs +#define CFG_TUH_CDC 1 // CDC ACM +#define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API +#define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API +#define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces +#define CFG_TUH_MSC 1 +#define CFG_TUH_VENDOR 0 + +// max device support (excluding hub device): 1 hub typically has 4 ports +#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1) + +//------------- HID -------------// +#define CFG_TUH_HID_EPIN_BUFSIZE 64 +#define CFG_TUH_HID_EPOUT_BUFSIZE 64 + +//------------- CDC -------------// + +// Set Line Control state on enumeration/mounted: +// DTR ( bit 0), RTS (bit 1) +#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM 0x03 + +// Set Line Coding on enumeration/mounted, value for cdc_line_coding_t +// bit rate = 115200, 1 stop bit, no parity, 8 bit data width +#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } + + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/examples/host/hid_controller/CMakeLists.txt b/examples/host/hid_controller/CMakeLists.txt index 3fb630aaa..c1b500dd8 100644 --- a/examples/host/hid_controller/CMakeLists.txt +++ b/examples/host/hid_controller/CMakeLists.txt @@ -10,6 +10,11 @@ project(${PROJECT} C CXX ASM) # Checks this example is valid for the family and initializes the project family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +# Espressif has its own cmake build system +if(FAMILY STREQUAL "espressif") + return() +endif() + add_executable(${PROJECT}) # Example source diff --git a/examples/host/msc_file_explorer/CMakeLists.txt b/examples/host/msc_file_explorer/CMakeLists.txt index 1868b632e..1a57c7466 100644 --- a/examples/host/msc_file_explorer/CMakeLists.txt +++ b/examples/host/msc_file_explorer/CMakeLists.txt @@ -10,6 +10,11 @@ project(${PROJECT} C CXX ASM) # Checks this example is valid for the family and initializes the project family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +# Espressif has its own cmake build system +if(FAMILY STREQUAL "espressif") + return() +endif() + add_executable(${PROJECT}) # Example source diff --git a/examples/make.mk b/examples/make.mk index 8fe4a3486..448d7883d 100644 --- a/examples/make.mk +++ b/examples/make.mk @@ -26,9 +26,6 @@ ifeq '$(findstring ;,$(PATH))' ';' CMDEXE := 1 # makefile shell commands should use syntax for DOS CMD, not unix sh -# Unfortunately, SHELL may point to sh or bash, which can't accept DOS syntax. -# We can't just use sh, because while sh and/or bash shell may be available, -# many Windows environments won't have utilities like realpath used below, so... # Force DOS command shell on Windows. SHELL := cmd.exe endif diff --git a/hw/bsp/espressif/boards/adafruit_metro_esp32s2/board.h b/hw/bsp/espressif/boards/adafruit_metro_esp32s2/board.h index 2ec80ef47..44ff11aa0 100644 --- a/hw/bsp/espressif/boards/adafruit_metro_esp32s2/board.h +++ b/hw/bsp/espressif/boards/adafruit_metro_esp32s2/board.h @@ -36,6 +36,14 @@ #define BUTTON_PIN 0 #define BUTTON_STATE_ACTIVE 0 +// SPI for USB host shield +#define MAX3421_SPI_HOST SPI2_HOST +#define MAX3421_SCK_PIN 36 +#define MAX3421_MOSI_PIN 35 +#define MAX3421_MISO_PIN 37 +#define MAX3421_CS_PIN 15 +#define MAX3421_INTR_PIN 14 + #ifdef __cplusplus } #endif diff --git a/hw/bsp/espressif/boards/espressif_kaluga_1/board.h b/hw/bsp/espressif/boards/espressif_kaluga_1/board.h index 0acb9c439..613e6ae0c 100644 --- a/hw/bsp/espressif/boards/espressif_kaluga_1/board.h +++ b/hw/bsp/espressif/boards/espressif_kaluga_1/board.h @@ -37,6 +37,14 @@ #define BUTTON_PIN 0 #define BUTTON_STATE_ACTIVE 0 +// SPI for USB host shield +#define MAX3421_SPI_HOST SPI2_HOST +#define MAX3421_SCK_PIN 36 +#define MAX3421_MOSI_PIN 35 +#define MAX3421_MISO_PIN 37 +#define MAX3421_CS_PIN 15 +#define MAX3421_INTR_PIN 14 + #ifdef __cplusplus } #endif diff --git a/hw/bsp/espressif/boards/espressif_s2_devkitc/board.cmake b/hw/bsp/espressif/boards/espressif_s2_devkitc/board.cmake new file mode 100644 index 000000000..abbdf7abc --- /dev/null +++ b/hw/bsp/espressif/boards/espressif_s2_devkitc/board.cmake @@ -0,0 +1,2 @@ +# Apply board specific content here +set(IDF_TARGET "esp32s2") diff --git a/hw/bsp/espressif/boards/espressif_s2_devkitc/board.h b/hw/bsp/espressif/boards/espressif_s2_devkitc/board.h new file mode 100644 index 000000000..e068efef9 --- /dev/null +++ b/hw/bsp/espressif/boards/espressif_s2_devkitc/board.h @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, 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. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// Note: On the production version (v1.2) WS2812 is connected to GPIO 18, +// however earlier revision v1.1 WS2812 is connected to GPIO 17 +#define NEOPIXEL_PIN 18 + +#define BUTTON_PIN 0 +#define BUTTON_STATE_ACTIVE 0 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index 8f857fb71..250b7001e 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -45,16 +45,19 @@ static led_strip_t *strip; #endif -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ +#if CFG_TUH_ENABLED && CFG_TUH_MAX3421 +#include "driver/spi_master.h" +static void max3421_init(void); +#endif static void configure_pins(usb_hal_context_t *usb); -// Initialize on-board peripherals : led, button, uart and USB -void board_init(void) -{ +//--------------------------------------------------------------------+ +// Implementation +//--------------------------------------------------------------------+ +// Initialize on-board peripherals : led, button, uart and USB +void board_init(void) { #ifdef NEOPIXEL_PIN #ifdef NEOPIXEL_POWER_PIN gpio_reset_pin(NEOPIXEL_POWER_PIN); @@ -79,23 +82,27 @@ void board_init(void) gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT); gpio_set_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN_ONLY : GPIO_PULLUP_ONLY); +#if CFG_TUD_ENABLED // USB Controller Hal init periph_module_reset(PERIPH_USB_MODULE); periph_module_enable(PERIPH_USB_MODULE); usb_hal_context_t hal = { - .use_external_phy = false // use built-in PHY + .use_external_phy = false // use built-in PHY }; usb_hal_init(&hal); configure_pins(&hal); +#endif + +#if CFG_TUH_ENABLED && CFG_TUH_MAX3421 + max3421_init(); +#endif } -static void configure_pins(usb_hal_context_t *usb) -{ +static void configure_pins(usb_hal_context_t *usb) { /* usb_periph_iopins currently configures USB_OTG as USB Device. * Introduce additional parameters in usb_hal_context_t when adding support - * for USB Host. - */ + * for USB Host. */ for (const usb_iopin_dsc_t *iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) { if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) { esp_rom_gpio_pad_select_gpio(iopin->pin); @@ -115,6 +122,7 @@ static void configure_pins(usb_hal_context_t *usb) esp_rom_gpio_pad_unhold(iopin->pin); } } + if (!usb->use_external_phy) { gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3); gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3); @@ -122,8 +130,7 @@ static void configure_pins(usb_hal_context_t *usb) } // Turn LED on or off -void board_led_write(bool state) -{ +void board_led_write(bool state) { #ifdef NEOPIXEL_PIN strip->set_pixel(strip, 0, (state ? 0x88 : 0x00), 0x00, 0x00); strip->refresh(strip, 100); @@ -132,21 +139,102 @@ void board_led_write(bool state) // Get the current state of button // a '1' means active (pressed), a '0' means inactive. -uint32_t board_button_read(void) -{ +uint32_t board_button_read(void) { return gpio_get_level(BUTTON_PIN) == BUTTON_STATE_ACTIVE; } // Get characters from UART -int board_uart_read(uint8_t* buf, int len) -{ - (void) buf; (void) len; +int board_uart_read(uint8_t *buf, int len) { + (void) buf; + (void) len; return 0; } // Send characters to UART -int board_uart_write(void const * buf, int len) -{ - (void) buf; (void) len; +int board_uart_write(void const *buf, int len) { + (void) buf; + (void) len; return 0; } + +//--------------------------------------------------------------------+ +// API: SPI transfer with MAX3421E, must be implemented by application +//--------------------------------------------------------------------+ +#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + +static spi_device_handle_t max3421_spi; + +static void IRAM_ATTR max3421_isr_handler(void* arg) +{ + (void) arg; + //uint32_t gpio_num = (uint32_t) arg; + //xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); + tuh_int_handler(1); +} + +static void max3421_init(void) { + // CS pin + gpio_set_direction(MAX3421_CS_PIN, GPIO_MODE_OUTPUT); + gpio_set_level(MAX3421_CS_PIN, 1); + + // SPI + spi_bus_config_t buscfg={ + .miso_io_num = MAX3421_MISO_PIN, + .mosi_io_num = MAX3421_MOSI_PIN, + .sclk_io_num = MAX3421_SCK_PIN, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .data4_io_num = -1, + .data5_io_num = -1, + .data6_io_num = -1, + .data7_io_num = -1, + .max_transfer_sz = 128 + }; + ESP_ERROR_CHECK( spi_bus_initialize(MAX3421_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO) ); + + spi_device_interface_config_t max3421_cfg = { + .command_bits = 8, + .mode = 0, + .clock_speed_hz = 4000000, // 26000000 + .spics_io_num = -1, // manual control CS + .queue_size = 1 + }; + ESP_ERROR_CHECK( spi_bus_add_device(MAX3421_SPI_HOST, &max3421_cfg, &max3421_spi) ); + + // Interrupt pin +// gpio_set_direction(MAX3421_INTR_PIN, GPIO_MODE_INPUT); +// gpio_set_intr_type(MAX3421_INTR_PIN, GPIO_INTR_NEGEDGE); +// +// gpio_install_isr_service(ESP_INTR_FLAG_EDGE); +// gpio_isr_handler_add(MAX3421_INTR_PIN, max3421_isr_handler, NULL); +} + +void tuh_max3421_int_api(uint8_t rhport, bool enabled) { + (void) rhport; + if (enabled) { + gpio_intr_enable(MAX3421_INTR_PIN); + } else { + gpio_intr_disable(MAX3421_INTR_PIN); + } +} + +void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { + (void) rhport; + gpio_set_level(MAX3421_CS_PIN, active ? 0 : 1); +} + +bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { + (void) rhport; + + spi_transaction_t xact = { + .length = tx_len, + .rxlength = rx_len, + .tx_buffer = tx_buf, + .rx_buffer = rx_buf + }; + + ESP_ERROR_CHECK(spi_device_transmit(max3421_spi, &xact)); + return true; +} + +#endif diff --git a/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt b/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt index bf8e45be2..2a154a8ff 100644 --- a/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt +++ b/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt @@ -16,40 +16,57 @@ else() return() endif() -list(APPEND compile_options - "-DCFG_TUSB_MCU=${tusb_mcu}" - "-DCFG_TUSB_OS=OPT_OS_FREERTOS" - #"-DCFG_TUSB_DEBUG=1" - ) - -idf_component_get_property(freertos_component_dir freertos COMPONENT_DIR) - -list(APPEND includes_public - "${tusb_src}" - # The FreeRTOS API include convention in tinyusb is different from esp-idf - #"${freertos_component_dir}/include/freertos" - ) +list(APPEND compile_definitions + CFG_TUSB_MCU=${tusb_mcu} + CFG_TUSB_OS=OPT_OS_FREERTOS + ) list(APPEND srcs - "${tusb_src}/tusb.c" - "${tusb_src}/common/tusb_fifo.c" - "${tusb_src}/device/usbd.c" - "${tusb_src}/device/usbd_control.c" - "${tusb_src}/class/cdc/cdc_device.c" - "${tusb_src}/class/dfu/dfu_rt_device.c" - "${tusb_src}/class/hid/hid_device.c" - "${tusb_src}/class/midi/midi_device.c" - "${tusb_src}/class/msc/msc_device.c" - "${tusb_src}/class/net/ecm_rndis_device.c" - "${tusb_src}/class/net/ncm_device.c" - "${tusb_src}/class/usbtmc/usbtmc_device.c" - "${tusb_src}/class/vendor/vendor_device.c" - "${tusb_src}/portable/synopsys/dwc2/dcd_dwc2.c" - ) + # common + ${tusb_src}/tusb.c + ${tusb_src}/common/tusb_fifo.c + # device + ${tusb_src}/device/usbd.c + ${tusb_src}/device/usbd_control.c + ${tusb_src}/class/audio/audio_device.c + ${tusb_src}/class/cdc/cdc_device.c + ${tusb_src}/class/dfu/dfu_device.c + ${tusb_src}/class/dfu/dfu_rt_device.c + ${tusb_src}/class/hid/hid_device.c + ${tusb_src}/class/midi/midi_device.c + ${tusb_src}/class/msc/msc_device.c + ${tusb_src}/class/net/ecm_rndis_device.c + ${tusb_src}/class/net/ncm_device.c + ${tusb_src}/class/usbtmc/usbtmc_device.c + ${tusb_src}/class/vendor/vendor_device.c + ${tusb_src}/class/video/video_device.c + ${tusb_src}/portable/synopsys/dwc2/dcd_dwc2.c + # host + ${tusb_src}/host/usbh.c + ${tusb_src}/host/hub.c + ${tusb_src}/class/cdc/cdc_host.c + ${tusb_src}/class/hid/hid_host.c + ${tusb_src}/class/msc/msc_host.c + ${tusb_src}/class/vendor/vendor_host.c + ) + +# use max3421 as host controller +if (MAX3421_HOST STREQUAL "1") + list(APPEND srcs ${tusb_src}/portable/analog/max3421/hcd_max3421.c) + list(APPEND compile_definitions CFG_TUH_MAX3421=1) +endif () + +if (DEFINED LOG) + list(APPEND compile_definitions CFG_TUSB_DEBUG=${LOG}) + if (LOG STREQUAL "4") + # no inline for debug level 4 + list(APPEND compile_definitions TU_ATTR_ALWAYS_INLINE=) + endif () +endif() idf_component_register(SRCS ${srcs} - INCLUDE_DIRS ${includes_public} - REQUIRES src - ) + INCLUDE_DIRS ${tusb_src} + REQUIRES src + ) -target_compile_options(${COMPONENT_LIB} PUBLIC ${compile_options}) +target_compile_definitions(${COMPONENT_LIB} PUBLIC ${compile_definitions}) diff --git a/src/host/usbh.c b/src/host/usbh.c index e332f35cc..dc2831da3 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -659,7 +659,7 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result tusb_control_request_t const * request = &_ctrl_xfer.request; if (XFER_RESULT_SUCCESS != result) { - TU_LOG1("[%u:%u] Control %s, xferred_bytes = %lu\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes); + TU_LOG1("[%u:%u] Control %s, xferred_bytes = %u\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes); TU_LOG1_BUF(request, 8); TU_LOG1("\r\n"); diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index f3f76fd58..3f6747404 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -882,7 +882,7 @@ void hcd_int_handler(uint8_t rhport) { if ( hirq & HIRQ_RCVDAV_IRQ ) { uint8_t const ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK; max3421_ep_t *ep = find_opened_ep(_hcd_data.peraddr, ep_num, 1); - uint8_t xact_len; + uint8_t xact_len = 0; // RCVDAV_IRQ can trigger 2 times (dual buffered) while ( hirq & HIRQ_RCVDAV_IRQ ) { From f6ca86c3ddeaec18f52b15f1065a5c9eea210c00 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 26 Sep 2023 19:09:36 +0700 Subject: [PATCH 49/71] tested cdc_msc_hid_freertos with samd51 add -Wno-error=format for espressif wrap up cdc_msc_hid_freertos --- examples/host/cdc_msc_hid_freertos/Makefile | 32 +++ examples/host/cdc_msc_hid_freertos/only.txt | 13 + .../cdc_msc_hid_freertos/src/CMakeLists.txt | 4 +- .../host/cdc_msc_hid_freertos/src/cdc_app.c | 109 ++++++++ .../cdc_msc_hid_freertos/src/freertos_hook.c | 111 ++++++++ .../host/cdc_msc_hid_freertos/src/hid_app.c | 263 ++++++++++++++++++ examples/host/cdc_msc_hid_freertos/src/main.c | 22 +- .../host/cdc_msc_hid_freertos/src/msc_app.c | 67 +++++ hw/bsp/espressif/boards/CMakeLists.txt | 2 + hw/bsp/espressif/boards/family.c | 39 +-- .../components/tinyusb_src/CMakeLists.txt | 1 + hw/bsp/nrf/family.c | 106 +++---- hw/bsp/samd21/family.c | 9 +- hw/bsp/samd51/FreeRTOSConfig/FreeRTOSConfig.h | 2 +- hw/bsp/samd51/family.c | 8 +- src/host/usbh.c | 2 +- 16 files changed, 703 insertions(+), 87 deletions(-) create mode 100644 examples/host/cdc_msc_hid_freertos/Makefile create mode 100644 examples/host/cdc_msc_hid_freertos/only.txt create mode 100644 examples/host/cdc_msc_hid_freertos/src/cdc_app.c create mode 100644 examples/host/cdc_msc_hid_freertos/src/freertos_hook.c create mode 100644 examples/host/cdc_msc_hid_freertos/src/hid_app.c create mode 100644 examples/host/cdc_msc_hid_freertos/src/msc_app.c diff --git a/examples/host/cdc_msc_hid_freertos/Makefile b/examples/host/cdc_msc_hid_freertos/Makefile new file mode 100644 index 000000000..67bb6da55 --- /dev/null +++ b/examples/host/cdc_msc_hid_freertos/Makefile @@ -0,0 +1,32 @@ +include ../../make.mk + +FREERTOS_SRC = lib/FreeRTOS-Kernel +FREERTOS_PORTABLE_PATH= $(FREERTOS_SRC)/portable/$(if $(USE_IAR),IAR,GCC) + +INC += \ + src \ + $(TOP)/hw \ + $(TOP)/$(FREERTOS_SRC)/include \ + $(TOP)/$(FREERTOS_PORTABLE_SRC) \ + +# Example source +EXAMPLE_SOURCE = \ + src/cdc_app.c \ + src/freertos_hook.c \ + src/hid_app.c \ + src/main.c \ + src/msc_app.c \ + +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +# TinyUSB Host Stack source +SRC_C += \ + src/class/cdc/cdc_host.c \ + src/class/hid/hid_host.c \ + src/class/msc/msc_host.c \ + src/host/hub.c \ + src/host/usbh.c \ + src/portable/ohci/ohci.c \ + src/portable/nxp/lpc17_40/hcd_lpc17_40.c + +include ../../rules.mk diff --git a/examples/host/cdc_msc_hid_freertos/only.txt b/examples/host/cdc_msc_hid_freertos/only.txt new file mode 100644 index 000000000..3837ac8a2 --- /dev/null +++ b/examples/host/cdc_msc_hid_freertos/only.txt @@ -0,0 +1,13 @@ +mcu:LPC175X_6X +mcu:LPC177X_8X +mcu:LPC18XX +mcu:LPC40XX +mcu:LPC43XX +mcu:MIMXRT1XXX +mcu:MIMXRT10XX +mcu:MIMXRT11XX +mcu:RP2040 +mcu:MSP432E4 +mcu:RX65X +mcu:RAXXX +mcu:MAX3421 diff --git a/examples/host/cdc_msc_hid_freertos/src/CMakeLists.txt b/examples/host/cdc_msc_hid_freertos/src/CMakeLists.txt index dd7ec8e58..6f057c106 100644 --- a/examples/host/cdc_msc_hid_freertos/src/CMakeLists.txt +++ b/examples/host/cdc_msc_hid_freertos/src/CMakeLists.txt @@ -1,4 +1,6 @@ # This file is for ESP-IDF only -idf_component_register(SRCS "hid_app.c" "main.c" +idf_component_register(SRCS "cdc_app.c" "hid_app.c" "main.c" "msc_app.c" INCLUDE_DIRS "." REQUIRES boards tinyusb_src) + +target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=format) diff --git a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c new file mode 100644 index 000000000..fc2b1228d --- /dev/null +++ b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c @@ -0,0 +1,109 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2022, 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. + */ + +#include "tusb.h" +#include "bsp/board_api.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + + +//------------- IMPLEMENTATION -------------// + +size_t get_console_inputs(uint8_t *buf, size_t bufsize) { + size_t count = 0; + while (count < bufsize) { + int ch = board_getchar(); + if (ch <= 0) break; + + buf[count] = (uint8_t) ch; + count++; + } + + return count; +} + +void cdc_app_task(void* param) { + (void) param; + + uint8_t buf[64 + 1]; // +1 for extra null character + uint32_t const bufsize = sizeof(buf) - 1; + + while (1) { + uint32_t count = get_console_inputs(buf, bufsize); + buf[count] = 0; + + if (count) { + // loop over all mounted interfaces + for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) { + if (tuh_cdc_mounted(idx)) { + // console --> cdc interfaces + tuh_cdc_write(idx, buf, count); + tuh_cdc_write_flush(idx); + } + } + } + + taskYIELD(); + } +} + +// Invoked when received new data +void tuh_cdc_rx_cb(uint8_t idx) { + uint8_t buf[64 + 1]; // +1 for extra null character + uint32_t const bufsize = sizeof(buf) - 1; + + // forward cdc interfaces -> console + uint32_t count = tuh_cdc_read(idx, buf, bufsize); + buf[count] = 0; + + printf((char *) buf); +} + +void tuh_cdc_mount_cb(uint8_t idx) { + tuh_itf_info_t itf_info = { 0 }; + tuh_cdc_itf_get_info(idx, &itf_info); + + printf("CDC Interface is mounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber); + +#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM + // CFG_TUH_CDC_LINE_CODING_ON_ENUM must be defined for line coding is set by tinyusb in enumeration + // otherwise you need to call tuh_cdc_set_line_coding() first + cdc_line_coding_t line_coding = { 0 }; + if (tuh_cdc_get_local_line_coding(idx, &line_coding)) { + printf(" Baudrate: %lu, Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits); + printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity, line_coding.data_bits); + } +#endif +} + +void tuh_cdc_umount_cb(uint8_t idx) { + tuh_itf_info_t itf_info = { 0 }; + tuh_cdc_itf_get_info(idx, &itf_info); + + printf("CDC Interface is unmounted: address = %u, itf_num = %u\r\n", itf_info.daddr, itf_info.desc.bInterfaceNumber); +} diff --git a/examples/host/cdc_msc_hid_freertos/src/freertos_hook.c b/examples/host/cdc_msc_hid_freertos/src/freertos_hook.c new file mode 100644 index 000000000..07d159fd5 --- /dev/null +++ b/examples/host/cdc_msc_hid_freertos/src/freertos_hook.c @@ -0,0 +1,111 @@ +/* + * 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. + * + */ + +//--------------------------------------------------------------------+ +// INCLUDE +//--------------------------------------------------------------------+ +#include "FreeRTOS.h" +#include "task.h" +#include "common/tusb_common.h" + +void vApplicationMallocFailedHook(void) { + taskDISABLE_INTERRUPTS(); + TU_ASSERT(false,); +} + +void vApplicationStackOverflowHook(xTaskHandle pxTask, char *pcTaskName) { + (void) pxTask; + (void) pcTaskName; + + taskDISABLE_INTERRUPTS(); + TU_ASSERT(false,); +} + +/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an + * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is + * used by the Idle task. */ +void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, + uint32_t *pulIdleTaskStackSize) { + /* If the buffers to be provided to the Idle task are declared inside this + * function then they must be declared static - otherwise they will be allocated on + * the stack and so not exists after this function exits. */ + static StaticTask_t xIdleTaskTCB; + static StackType_t uxIdleTaskStack[configMINIMAL_STACK_SIZE]; + + /* Pass out a pointer to the StaticTask_t structure in which the Idle task's + state will be stored. */ + *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; + + /* Pass out the array that will be used as the Idle task's stack. */ + *ppxIdleTaskStackBuffer = uxIdleTaskStack; + + /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; +} + +/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the + * application must provide an implementation of vApplicationGetTimerTaskMemory() + * to provide the memory that is used by the Timer service task. */ +void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, + uint32_t *pulTimerTaskStackSize) { + /* If the buffers to be provided to the Timer task are declared inside this + * function then they must be declared static - otherwise they will be allocated on + * the stack and so not exists after this function exits. */ + static StaticTask_t xTimerTaskTCB; + static StackType_t uxTimerTaskStack[configTIMER_TASK_STACK_DEPTH]; + + /* Pass out a pointer to the StaticTask_t structure in which the Timer + task's state will be stored. */ + *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; + + /* Pass out the array that will be used as the Timer task's stack. */ + *ppxTimerTaskStackBuffer = uxTimerTaskStack; + + /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */ + *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; +} + +#if CFG_TUSB_MCU == OPT_MCU_RX63X | CFG_TUSB_MCU == OPT_MCU_RX65X +#include "iodefine.h" +void vApplicationSetupTimerInterrupt(void) +{ + /* Enable CMT0 */ + SYSTEM.PRCR.WORD = (0xA5u<<8) | TU_BIT(1); + MSTP(CMT0) = 0; + SYSTEM.PRCR.WORD = (0xA5u<<8); + + CMT0.CMCNT = 0; + CMT0.CMCOR = (unsigned short)(((configPERIPHERAL_CLOCK_HZ/configTICK_RATE_HZ)-1)/128); + CMT0.CMCR.WORD = TU_BIT(6) | 2; + IR(CMT0, CMI0) = 0; + IPR(CMT0, CMI0) = configKERNEL_INTERRUPT_PRIORITY; + IEN(CMT0, CMI0) = 1; + CMT.CMSTR0.BIT.STR0 = 1; +} +#endif diff --git a/examples/host/cdc_msc_hid_freertos/src/hid_app.c b/examples/host/cdc_msc_hid_freertos/src/hid_app.c new file mode 100644 index 000000000..a2df3b909 --- /dev/null +++ b/examples/host/cdc_msc_hid_freertos/src/hid_app.c @@ -0,0 +1,263 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, 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. + * + */ + +#include "bsp/board_api.h" +#include "tusb.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM DECLARATION +//--------------------------------------------------------------------+ + +// If your host terminal support ansi escape code such as TeraTerm +// it can be use to simulate mouse cursor movement within terminal +#define USE_ANSI_ESCAPE 0 + +#define MAX_REPORT 4 + +static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; + +// Each HID instance can has multiple reports +static struct { + uint8_t report_count; + tuh_hid_report_info_t report_info[MAX_REPORT]; +} hid_info[CFG_TUH_HID]; + +static void process_kbd_report(hid_keyboard_report_t const *report); +static void process_mouse_report(hid_mouse_report_t const *report); +static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len); + +//--------------------------------------------------------------------+ +// TinyUSB Callbacks +//--------------------------------------------------------------------+ + +// Invoked when device with hid interface is mounted +// Report descriptor is also available for use. tuh_hid_parse_report_descriptor() +// can be used to parse common/simple enough descriptor. +// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped +// therefore report_desc = NULL, desc_len = 0 +void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) { + printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); + + // Interface protocol (hid_interface_protocol_enum_t) + const char *protocol_str[] = { "None", "Keyboard", "Mouse" }; + uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance); + + printf("HID Interface Protocol = %s\r\n", protocol_str[itf_protocol]); + + // By default host stack will use activate boot protocol on supported interface. + // Therefore for this simple example, we only need to parse generic report descriptor (with built-in parser) + if (itf_protocol == HID_ITF_PROTOCOL_NONE) { + hid_info[instance].report_count = tuh_hid_parse_report_descriptor(hid_info[instance].report_info, MAX_REPORT, + desc_report, desc_len); + printf("HID has %u reports \r\n", hid_info[instance].report_count); + } + + // request to receive report + // tuh_hid_report_received_cb() will be invoked when report is available + if (!tuh_hid_receive_report(dev_addr, instance)) { + printf("Error: cannot request to receive report\r\n"); + } +} + +// Invoked when device with hid interface is un-mounted +void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) { + printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); +} + +// Invoked when received report from device via interrupt endpoint +void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) { + uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance); + + switch (itf_protocol) { + case HID_ITF_PROTOCOL_KEYBOARD: + TU_LOG2("HID receive boot keyboard report\r\n"); + process_kbd_report((hid_keyboard_report_t const *) report); + break; + + case HID_ITF_PROTOCOL_MOUSE: + TU_LOG2("HID receive boot mouse report\r\n"); + process_mouse_report((hid_mouse_report_t const *) report); + break; + + default: + // Generic report requires matching ReportID and contents with previous parsed report info + process_generic_report(dev_addr, instance, report, len); + break; + } + + // continue to request to receive report + if (!tuh_hid_receive_report(dev_addr, instance)) { + printf("Error: cannot request to receive report\r\n"); + } +} + +//--------------------------------------------------------------------+ +// Keyboard +//--------------------------------------------------------------------+ + +// look up new key in previous keys +static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8_t keycode) { + for (uint8_t i = 0; i < 6; i++) { + if (report->keycode[i] == keycode) return true; + } + + return false; +} + +static void process_kbd_report(hid_keyboard_report_t const *report) { + static hid_keyboard_report_t prev_report = { 0, 0, { 0 } }; // previous report to check key released + + //------------- example code ignore control (non-printable) key affects -------------// + for (uint8_t i = 0; i < 6; i++) { + if (report->keycode[i]) { + if (find_key_in_report(&prev_report, report->keycode[i])) { + // exist in previous report means the current key is holding + } else { + // not existed in previous report means the current key is pressed + bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT); + uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0]; + putchar(ch); + if (ch == '\r') putchar('\n'); // added new line for enter key + + #ifndef __ICCARM__ // TODO IAR doesn't support stream control ? + fflush(stdout); // flush right away, else nanolib will wait for newline + #endif + } + } + // TODO example skips key released + } + + prev_report = *report; +} + +//--------------------------------------------------------------------+ +// Mouse +//--------------------------------------------------------------------+ + +void cursor_movement(int8_t x, int8_t y, int8_t wheel) { +#if USE_ANSI_ESCAPE + // Move X using ansi escape + if ( x < 0) { + printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left + }else if ( x > 0) { + printf(ANSI_CURSOR_FORWARD(%d), x); // move right + } + + // Move Y using ansi escape + if ( y < 0) { + printf(ANSI_CURSOR_UP(%d), (-y)); // move up + }else if ( y > 0) { + printf(ANSI_CURSOR_DOWN(%d), y); // move down + } + + // Scroll using ansi escape + if (wheel < 0) { + printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up + }else if (wheel > 0) { + printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down + } + + printf("\r\n"); +#else + printf("(%d %d %d)\r\n", x, y, wheel); +#endif +} + +static void process_mouse_report(hid_mouse_report_t const *report) { + static hid_mouse_report_t prev_report = { 0 }; + + //------------- button state -------------// + uint8_t button_changed_mask = report->buttons ^ prev_report.buttons; + if (button_changed_mask & report->buttons) { + printf(" %c%c%c ", + report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-', + report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-', + report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-'); + } + + //------------- cursor movement -------------// + cursor_movement(report->x, report->y, report->wheel); +} + +//--------------------------------------------------------------------+ +// Generic Report +//--------------------------------------------------------------------+ +static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) { + (void) dev_addr; + + uint8_t const rpt_count = hid_info[instance].report_count; + tuh_hid_report_info_t *rpt_info_arr = hid_info[instance].report_info; + tuh_hid_report_info_t *rpt_info = NULL; + + if (rpt_count == 1 && rpt_info_arr[0].report_id == 0) { + // Simple report without report ID as 1st byte + rpt_info = &rpt_info_arr[0]; + } else { + // Composite report, 1st byte is report ID, data starts from 2nd byte + uint8_t const rpt_id = report[0]; + + // Find report id in the array + for (uint8_t i = 0; i < rpt_count; i++) { + if (rpt_id == rpt_info_arr[i].report_id) { + rpt_info = &rpt_info_arr[i]; + break; + } + } + + report++; + len--; + } + + if (!rpt_info) { + printf("Couldn't find report info !\r\n"); + return; + } + + // For complete list of Usage Page & Usage checkout src/class/hid/hid.h. For examples: + // - Keyboard : Desktop, Keyboard + // - Mouse : Desktop, Mouse + // - Gamepad : Desktop, Gamepad + // - Consumer Control (Media Key) : Consumer, Consumer Control + // - System Control (Power key) : Desktop, System Control + // - Generic (vendor) : 0xFFxx, xx + if (rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP) { + switch (rpt_info->usage) { + case HID_USAGE_DESKTOP_KEYBOARD: + TU_LOG1("HID receive keyboard report\r\n"); + // Assume keyboard follow boot report layout + process_kbd_report((hid_keyboard_report_t const *) report); + break; + + case HID_USAGE_DESKTOP_MOUSE: + TU_LOG1("HID receive mouse report\r\n"); + // Assume mouse follow boot report layout + process_mouse_report((hid_mouse_report_t const *) report); + break; + + default: + break; + } + } +} diff --git a/examples/host/cdc_msc_hid_freertos/src/main.c b/examples/host/cdc_msc_hid_freertos/src/main.c index e2ddd52eb..d5574789f 100644 --- a/examples/host/cdc_msc_hid_freertos/src/main.c +++ b/examples/host/cdc_msc_hid_freertos/src/main.c @@ -51,6 +51,8 @@ #define USBH_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) #endif +#define CDC_STACK_SZIE (3*configMINIMAL_STACK_SIZE/2) + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTOTYPES //--------------------------------------------------------------------+ @@ -72,18 +74,16 @@ StaticTimer_t blinky_tmdef; StackType_t usb_host_stack[USBH_STACK_SIZE]; StaticTask_t usb_host_taskdef; -//StackType_t cdc_stack[CDC_STACK_SZIE]; -//StaticTask_t cdc_taskdef; +StackType_t cdc_stack[CDC_STACK_SZIE]; +StaticTask_t cdc_taskdef; #endif - TimerHandle_t blinky_tm; static void led_blinky_cb(TimerHandle_t xTimer); static void usb_host_task(void* param); -extern void cdc_app_task(void); -extern void hid_app_task(void); +extern void cdc_app_task(void* param); /*------------- MAIN -------------*/ int main(void) { @@ -91,19 +91,15 @@ int main(void) { printf("TinyUSB Host CDC MSC HID with FreeRTOS Example\r\n"); + // Create soft timer for blinky, task for tinyusb stack and CDC #if configSUPPORT_STATIC_ALLOCATION - // soft timer for blinky blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef); - - // Create a task for tinyusb device stack xTaskCreateStatic(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_host_stack, &usb_host_taskdef); - - // Create CDC task - //xTaskCreateStatic(cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); + xTaskCreateStatic(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); #else blinky_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb); - xTaskCreate( usb_device_task, "usbd", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, NULL); - //xTaskCreate( cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL); + xTaskCreate(usb_host_task, "usbd", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, NULL); + xTaskCreate(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL); #endif xTimerStart(blinky_tm, 0); diff --git a/examples/host/cdc_msc_hid_freertos/src/msc_app.c b/examples/host/cdc_msc_hid_freertos/src/msc_app.c new file mode 100644 index 000000000..a8d6fbfaa --- /dev/null +++ b/examples/host/cdc_msc_hid_freertos/src/msc_app.c @@ -0,0 +1,67 @@ +/* + * 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. + * + */ + +#include "tusb.h" + +#if CFG_TUH_MSC + +static scsi_inquiry_resp_t inquiry_resp; + +bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_data) { + msc_cbw_t const *cbw = cb_data->cbw; + msc_csw_t const *csw = cb_data->csw; + + if (csw->status != 0) { + printf("Inquiry failed\r\n"); + return false; + } + + // Print out Vendor ID, Product ID and Rev + printf("%.8s %.16s rev %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev); + + // Get capacity of device + uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun); + uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun); + + printf("Disk Size: %lu MB\r\n", block_count / ((1024 * 1024) / block_size)); + printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size); + + return true; +} + +//------------- IMPLEMENTATION -------------// +void tuh_msc_mount_cb(uint8_t dev_addr) { + printf("A MassStorage device is mounted\r\n"); + + uint8_t const lun = 0; + tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb, 0); +} + +void tuh_msc_umount_cb(uint8_t dev_addr) { + (void) dev_addr; + printf("A MassStorage device is unmounted\r\n"); +} + +#endif diff --git a/hw/bsp/espressif/boards/CMakeLists.txt b/hw/bsp/espressif/boards/CMakeLists.txt index 325263c1d..8209e8747 100644 --- a/hw/bsp/espressif/boards/CMakeLists.txt +++ b/hw/bsp/espressif/boards/CMakeLists.txt @@ -4,3 +4,5 @@ idf_component_register(SRCS family.c INCLUDE_DIRS "." ${BOARD} ${hw_dir} PRIV_REQUIRES "driver" REQUIRES led_strip src tinyusb_src) + +target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=format) diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index 250b7001e..d96d86670 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -33,6 +33,7 @@ #include "soc/usb_periph.h" #include "driver/rmt.h" +#include "driver/uart.h" #if ESP_IDF_VERSION_MAJOR > 4 #include "esp_private/periph_ctrl.h" @@ -145,9 +146,7 @@ uint32_t board_button_read(void) { // Get characters from UART int board_uart_read(uint8_t *buf, int len) { - (void) buf; - (void) len; - return 0; + return uart_read_bytes(UART_NUM_0, buf, len, 0); } // Send characters to UART @@ -157,6 +156,11 @@ int board_uart_write(void const *buf, int len) { return 0; } +int board_getchar(void) { + char c; + return (uart_read_bytes(UART_NUM_0, &c, 1, 0) > 0) ? (int) c : (-1); +} + //--------------------------------------------------------------------+ // API: SPI transfer with MAX3421E, must be implemented by application //--------------------------------------------------------------------+ @@ -164,12 +168,12 @@ int board_uart_write(void const *buf, int len) { static spi_device_handle_t max3421_spi; -static void IRAM_ATTR max3421_isr_handler(void* arg) -{ - (void) arg; - //uint32_t gpio_num = (uint32_t) arg; +static void IRAM_ATTR max3421_isr_handler(void* arg) { + (void) arg; // arg is gpio num //xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); + gpio_set_level(13, 1); tuh_int_handler(1); + gpio_set_level(13, 0); } static void max3421_init(void) { @@ -188,12 +192,11 @@ static void max3421_init(void) { .data5_io_num = -1, .data6_io_num = -1, .data7_io_num = -1, - .max_transfer_sz = 128 + .max_transfer_sz = 1024 }; ESP_ERROR_CHECK( spi_bus_initialize(MAX3421_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO) ); spi_device_interface_config_t max3421_cfg = { - .command_bits = 8, .mode = 0, .clock_speed_hz = 4000000, // 26000000 .spics_io_num = -1, // manual control CS @@ -201,12 +204,16 @@ static void max3421_init(void) { }; ESP_ERROR_CHECK( spi_bus_add_device(MAX3421_SPI_HOST, &max3421_cfg, &max3421_spi) ); + // debug + gpio_set_direction(13, GPIO_MODE_OUTPUT); + gpio_set_level(13, 0); + // Interrupt pin -// gpio_set_direction(MAX3421_INTR_PIN, GPIO_MODE_INPUT); -// gpio_set_intr_type(MAX3421_INTR_PIN, GPIO_INTR_NEGEDGE); -// -// gpio_install_isr_service(ESP_INTR_FLAG_EDGE); -// gpio_isr_handler_add(MAX3421_INTR_PIN, max3421_isr_handler, NULL); + gpio_set_direction(MAX3421_INTR_PIN, GPIO_MODE_INPUT); + gpio_set_intr_type(MAX3421_INTR_PIN, GPIO_INTR_NEGEDGE); + + gpio_install_isr_service(0); + gpio_isr_handler_add(MAX3421_INTR_PIN, max3421_isr_handler, NULL); } void tuh_max3421_int_api(uint8_t rhport, bool enabled) { @@ -227,8 +234,8 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_l (void) rhport; spi_transaction_t xact = { - .length = tx_len, - .rxlength = rx_len, + .length = tx_len << 3, // length in bits + .rxlength = rx_len << 3, // length in bits .tx_buffer = tx_buf, .rx_buffer = rx_buf }; diff --git a/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt b/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt index 2a154a8ff..abe276910 100644 --- a/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt +++ b/hw/bsp/espressif/components/tinyusb_src/CMakeLists.txt @@ -70,3 +70,4 @@ idf_component_register(SRCS ${srcs} ) target_compile_definitions(${COMPONENT_LIB} PUBLIC ${compile_definitions}) +target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=format) diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 6fcfd9476..3620bc8cc 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -95,13 +95,8 @@ TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) { //------------- Host using MAX2341E -------------// #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 +static void max3421_init(void); static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(1); - -void max3421_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { - if (!(pin == MAX3421_INTR_PIN && action == NRF_GPIOTE_POLARITY_HITOLO)) return; - - tuh_int_handler(1); -} #endif @@ -191,50 +186,7 @@ void board_init(void) { #endif #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 - // MAX3421 need 3.3v signal (may not be needed) - #if defined(UICR_REGOUT0_VOUT_Msk) && 0 - if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) != UICR_REGOUT0_VOUT_3V3) { - NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos; - while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} - - NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~UICR_REGOUT0_VOUT_Msk) | UICR_REGOUT0_VOUT_3V3; - - NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos; - while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} - - NVIC_SystemReset(); - } - #endif - - // manually manage CS - nrf_gpio_cfg_output(MAX3421_CS_PIN); - nrf_gpio_pin_write(MAX3421_CS_PIN, 1); - - // USB host using max3421e usb controller via SPI - nrfx_spim_config_t cfg = { - .sck_pin = MAX3421_SCK_PIN, - .mosi_pin = MAX3421_MOSI_PIN, - .miso_pin = MAX3421_MISO_PIN, - .ss_pin = NRFX_SPIM_PIN_NOT_USED, - .ss_active_high = false, - .irq_priority = 3, - .orc = 0xFF, - // default setting 4 Mhz, Mode 0, MSB first - .frequency = NRF_SPIM_FREQ_4M, - .mode = NRF_SPIM_MODE_0, - .bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST, - }; - - // no handler --> blocking - nrfx_spim_init(&_spi, &cfg, NULL, NULL); - - // max3421e interrupt pin - nrfx_gpiote_init(1); - nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true); - in_config.pull = NRF_GPIO_PIN_PULLUP; - - nrfx_gpiote_in_init(MAX3421_INTR_PIN, &in_config, max3421_int_handler); - nrfx_gpiote_trigger_enable(MAX3421_INTR_PIN, true); + max3421_init(); #endif } @@ -317,6 +269,60 @@ void nrf_error_cb(uint32_t id, uint32_t pc, uint32_t info) { //--------------------------------------------------------------------+ #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 +void max3421_int_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { + if (!(pin == MAX3421_INTR_PIN && action == NRF_GPIOTE_POLARITY_HITOLO)) return; + tuh_int_handler(1); +} + +static void max3421_init(void) { + // MAX3421 need 3.3v signal (may not be needed) +// #if defined(UICR_REGOUT0_VOUT_Msk) +// if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) != UICR_REGOUT0_VOUT_3V3) { +// NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos; +// while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} +// +// NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~UICR_REGOUT0_VOUT_Msk) | UICR_REGOUT0_VOUT_3V3; +// +// NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos; +// while (NRF_NVMC->READY == NVMC_READY_READY_Busy){} +// +// NVIC_SystemReset(); +// } +// #endif + + // manually manage CS + nrf_gpio_cfg_output(MAX3421_CS_PIN); + nrf_gpio_pin_write(MAX3421_CS_PIN, 1); + + // USB host using max3421e usb controller via SPI + nrfx_spim_config_t cfg = { + .sck_pin = MAX3421_SCK_PIN, + .mosi_pin = MAX3421_MOSI_PIN, + .miso_pin = MAX3421_MISO_PIN, + .ss_pin = NRFX_SPIM_PIN_NOT_USED, + .ss_active_high = false, + .irq_priority = 3, + .orc = 0xFF, + // default setting 4 Mhz, Mode 0, MSB first + .frequency = NRF_SPIM_FREQ_4M, + .mode = NRF_SPIM_MODE_0, + .bit_order = NRF_SPIM_BIT_ORDER_MSB_FIRST, + }; + + // no handler --> blocking + nrfx_spim_init(&_spi, &cfg, NULL, NULL); + + // max3421e interrupt pin + nrfx_gpiote_init(1); + nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true); + in_config.pull = NRF_GPIO_PIN_PULLUP; + + NVIC_SetPriority(GPIOTE_IRQn, 2); + + nrfx_gpiote_in_init(MAX3421_INTR_PIN, &in_config, max3421_int_handler); + nrfx_gpiote_trigger_enable(MAX3421_INTR_PIN, true); +} + void tuh_max3421_int_api(uint8_t rhport, bool enabled) { (void) rhport; diff --git a/hw/bsp/samd21/family.c b/hw/bsp/samd21/family.c index 395155548..335039e2f 100644 --- a/hw/bsp/samd21/family.c +++ b/hw/bsp/samd21/family.c @@ -261,6 +261,7 @@ void SysTick_Handler(void) { uint32_t board_millis(void) { return system_ticks; } +#endif //--------------------------------------------------------------------+ // @@ -344,6 +345,11 @@ static void max3421_init(void) { EIC->CONFIG[0].reg &= ~(7 << sense_shift); EIC->CONFIG[0].reg |= 2 << sense_shift; +#if CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(EIC_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); +#endif + // Enable External Interrupt EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << MAX3421_INTR_EIC_ID); @@ -413,6 +419,3 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_l } #endif - - -#endif diff --git a/hw/bsp/samd51/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/samd51/FreeRTOSConfig/FreeRTOSConfig.h index e3ee529cf..32db4ad95 100644 --- a/hw/bsp/samd51/FreeRTOSConfig/FreeRTOSConfig.h +++ b/hw/bsp/samd51/FreeRTOSConfig/FreeRTOSConfig.h @@ -59,7 +59,7 @@ #define configTICK_RATE_HZ ( 1000 ) #define configMAX_PRIORITIES ( 5 ) #define configMINIMAL_STACK_SIZE ( 128 ) -#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*6*1024 ) #define configMAX_TASK_NAME_LEN 16 #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 diff --git a/hw/bsp/samd51/family.c b/hw/bsp/samd51/family.c index c1b914a02..7b9de35c9 100644 --- a/hw/bsp/samd51/family.c +++ b/hw/bsp/samd51/family.c @@ -175,6 +175,7 @@ void SysTick_Handler(void) { uint32_t board_millis(void) { return system_ticks; } +#endif //--------------------------------------------------------------------+ // API: SPI transfer with MAX3421E, must be implemented by application @@ -290,6 +291,11 @@ static void max3421_init(void) { *eic_config &= ~(7 << sense_shift); *eic_config |= 2 << sense_shift; +#if CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(EIC_0_IRQn + MAX3421_INTR_EIC_ID, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); +#endif + // Enable External Interrupt EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << MAX3421_INTR_EIC_ID); @@ -360,5 +366,3 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_l } #endif - -#endif diff --git a/src/host/usbh.c b/src/host/usbh.c index dc2831da3..e332f35cc 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -659,7 +659,7 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result tusb_control_request_t const * request = &_ctrl_xfer.request; if (XFER_RESULT_SUCCESS != result) { - TU_LOG1("[%u:%u] Control %s, xferred_bytes = %u\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes); + TU_LOG1("[%u:%u] Control %s, xferred_bytes = %lu\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes); TU_LOG1_BUF(request, 8); TU_LOG1("\r\n"); From 2f6592de7f94851cfcca411242398c5da7b792de Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 Sep 2023 11:30:18 +0700 Subject: [PATCH 50/71] update max3421 to have hcd_int_handler_ext() --- hw/bsp/espressif/boards/family.c | 22 +++++++- src/host/hcd.h | 3 ++ src/portable/analog/max3421/hcd_max3421.c | 62 ++++++++++++----------- 3 files changed, 55 insertions(+), 32 deletions(-) diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index d96d86670..a04e1e7c5 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -167,15 +167,30 @@ int board_getchar(void) { #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 static spi_device_handle_t max3421_spi; +SemaphoreHandle_t max3421_intr_sem; static void IRAM_ATTR max3421_isr_handler(void* arg) { (void) arg; // arg is gpio num - //xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); gpio_set_level(13, 1); - tuh_int_handler(1); + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xSemaphoreGiveFromISR(max3421_intr_sem, &xHigherPriorityTaskWoken); + if (xHigherPriorityTaskWoken) { + portYIELD_FROM_ISR(); + } + gpio_set_level(13, 0); } +static void max3421_intr_task(void* param) { + (void) param; + + while (1) { + xSemaphoreTake(max3421_intr_sem, portMAX_DELAY); + tuh_int_handler(BOARD_TUH_RHPORT); + } +} + static void max3421_init(void) { // CS pin gpio_set_direction(MAX3421_CS_PIN, GPIO_MODE_OUTPUT); @@ -209,6 +224,9 @@ static void max3421_init(void) { gpio_set_level(13, 0); // Interrupt pin + max3421_intr_sem = xSemaphoreCreateBinary(); + xTaskCreate(max3421_intr_task, "max3421 intr", 2048, NULL, configMAX_PRIORITIES-1, NULL); + gpio_set_direction(MAX3421_INTR_PIN, GPIO_MODE_INPUT); gpio_set_intr_type(MAX3421_INTR_PIN, GPIO_INTR_NEGEDGE); diff --git a/src/host/hcd.h b/src/host/hcd.h index e25b20ea3..a2d4da85d 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -133,6 +133,9 @@ bool hcd_init(uint8_t rhport); // Interrupt Handler void hcd_int_handler(uint8_t rhport); +// Interrupt Hanndler (extended version) +void hcd_int_handler_ext(uint8_t rhport, bool in_isr); + // Enable USB interrupt void hcd_int_enable (uint8_t rhport); diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 3f6747404..652a971ee 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -428,8 +428,8 @@ bool hcd_init(uint8_t rhport) { reg_write(rhport, PINCTL_ADDR, PINCTL_FDUPSPI, false); // V1 is 0x01, V2 is 0x12, V3 is 0x13 - // uint8_t const revision = reg_read(rhport, REVISION_ADDR, false); - // TU_LOG2_HEX(revision); + uint8_t const revision = reg_read(rhport, REVISION_ADDR, false); + TU_LOG2_HEX(revision); // reset reg_write(rhport, USBCTL_ADDR, USBCTL_CHIPRES, false); @@ -693,9 +693,7 @@ static void handle_connect_irq(uint8_t rhport, bool in_isr) { // port reset anyway, this will help to stable bus signal for next connection reg_write(rhport, HCTL_ADDR, HCTL_BUSRST, in_isr); - hcd_event_device_remove(rhport, in_isr); - reg_write(rhport, HCTL_ADDR, 0, in_isr); break; @@ -721,13 +719,12 @@ static void handle_connect_irq(uint8_t rhport, bool in_isr) { free_ep(daddr); hcd_event_device_attach(rhport, in_isr); - break; } } } -static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t result, uint8_t hrsl) { +static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t result, uint8_t hrsl, bool in_isr) { uint8_t const ep_addr = tu_edpt_addr(ep->ep_num, ep->ep_dir); // save data toggle @@ -738,20 +735,20 @@ static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t re } ep->xfer_pending = 0; - hcd_event_xfer_complete(ep->daddr, ep_addr, ep->xferred_len, result, true); + hcd_event_xfer_complete(ep->daddr, ep_addr, ep->xferred_len, result, in_isr); // Find next pending endpoint max3421_ep_t *next_ep = find_next_pending_ep(ep); if (next_ep) { - xact_inout(rhport, next_ep, true, true); + xact_inout(rhport, next_ep, true, in_isr); }else { // no more pending atomic_flag_clear(&_hcd_data.busy); } } -static void handle_xfer_done(uint8_t rhport) { - uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, true); +static void handle_xfer_done(uint8_t rhport, bool in_isr) { + uint8_t const hrsl = reg_read(rhport, HRSL_ADDR, in_isr); uint8_t const hresult = hrsl & HRSL_RESULT_MASK; uint8_t const ep_num = _hcd_data.hxfr & HXFR_EPNUM_MASK; @@ -774,17 +771,17 @@ static void handle_xfer_done(uint8_t rhport) { case HRSL_NAK: if (ep_num == 0) { // NAK on control, retry immediately - hxfr_write(rhport, _hcd_data.hxfr, true); + hxfr_write(rhport, _hcd_data.hxfr, in_isr); }else { // NAK on non-control, find next pending to switch max3421_ep_t *next_ep = find_next_pending_ep(ep); if (ep == next_ep) { // this endpoint is only one pending, retry immediately - hxfr_write(rhport, _hcd_data.hxfr, true); + hxfr_write(rhport, _hcd_data.hxfr, in_isr); }else if (next_ep) { // switch to next pending TODO could have issue with double buffered if not clear previously out data - xact_inout(rhport, next_ep, true, true); + xact_inout(rhport, next_ep, true, in_isr); }else { TU_ASSERT(false,); } @@ -802,7 +799,7 @@ static void handle_xfer_done(uint8_t rhport) { } if (xfer_result != XFER_RESULT_SUCCESS) { - xfer_complete_isr(rhport, ep, xfer_result, hrsl); + xfer_complete_isr(rhport, ep, xfer_result, hrsl, in_isr); return; } @@ -814,10 +811,10 @@ static void handle_xfer_done(uint8_t rhport) { // short packet or all bytes transferred if ( ep->xfer_complete ) { - xfer_complete_isr(rhport, ep, xfer_result, hrsl); + xfer_complete_isr(rhport, ep, xfer_result, hrsl, in_isr); }else { // more to transfer - hxfr_write(rhport, _hcd_data.hxfr, true); + hxfr_write(rhport, _hcd_data.hxfr, in_isr); } } else { // SETUP or OUT transfer @@ -835,10 +832,10 @@ static void handle_xfer_done(uint8_t rhport) { ep->buf += xact_len; if (xact_len < ep->packet_size || ep->xferred_len >= ep->total_len) { - xfer_complete_isr(rhport, ep, xfer_result, hrsl); + xfer_complete_isr(rhport, ep, xfer_result, hrsl, in_isr); } else { // more to transfer - xact_out(rhport, ep, false, true); + xact_out(rhport, ep, false, in_isr); } } } @@ -862,9 +859,9 @@ void print_hirq(uint8_t hirq) { #define print_hirq(hirq) #endif -// Interrupt Handler -void hcd_int_handler(uint8_t rhport) { - uint8_t hirq = reg_read(rhport, HIRQ_ADDR, true) & _hcd_data.hien; +// Interrupt handler (extended) +void hcd_int_handler_ext(uint8_t rhport, bool in_isr) { + uint8_t hirq = reg_read(rhport, HIRQ_ADDR, in_isr) & _hcd_data.hien; if (!hirq) return; // print_hirq(hirq); @@ -873,7 +870,7 @@ void hcd_int_handler(uint8_t rhport) { } if (hirq & HIRQ_CONDET_IRQ) { - handle_connect_irq(rhport, true); + handle_connect_irq(rhport, in_isr); } // queue more transfer in handle_xfer_done() can cause hirq to be set again while external IRQ may not catch and/or @@ -886,17 +883,17 @@ void hcd_int_handler(uint8_t rhport) { // RCVDAV_IRQ can trigger 2 times (dual buffered) while ( hirq & HIRQ_RCVDAV_IRQ ) { - uint8_t rcvbc = reg_read(rhport, RCVBC_ADDR, true); + uint8_t rcvbc = reg_read(rhport, RCVBC_ADDR, in_isr); xact_len = (uint8_t) tu_min16(rcvbc, ep->total_len - ep->xferred_len); if ( xact_len ) { - fifo_read(rhport, ep->buf, xact_len, true); + fifo_read(rhport, ep->buf, xact_len, in_isr); ep->buf += xact_len; ep->xferred_len += xact_len; } // ack RCVDVAV IRQ - hirq_write(rhport, HIRQ_RCVDAV_IRQ, true); - hirq = reg_read(rhport, HIRQ_ADDR, true); + hirq_write(rhport, HIRQ_RCVDAV_IRQ, in_isr); + hirq = reg_read(rhport, HIRQ_ADDR, in_isr); } if ( xact_len < ep->packet_size || ep->xferred_len >= ep->total_len ) { @@ -905,18 +902,23 @@ void hcd_int_handler(uint8_t rhport) { } if ( hirq & HIRQ_HXFRDN_IRQ ) { - hirq_write(rhport, HIRQ_HXFRDN_IRQ, true); - handle_xfer_done(rhport); + hirq_write(rhport, HIRQ_HXFRDN_IRQ, in_isr); + handle_xfer_done(rhport, in_isr); } - hirq = reg_read(rhport, HIRQ_ADDR, true); + hirq = reg_read(rhport, HIRQ_ADDR, in_isr); } // clear all interrupt except SNDBAV_IRQ (never clear by us). Note RCVDAV_IRQ, HXFRDN_IRQ already clear while processing hirq &= ~HIRQ_SNDBAV_IRQ; if ( hirq ) { - hirq_write(rhport, hirq, true); + hirq_write(rhport, hirq, in_isr); } } +// Interrupt Handler +void hcd_int_handler(uint8_t rhport) { + hcd_int_handler_ext(rhport, true); +} + #endif From 6dc64eaa28ab905063233895345ba3c1186b836d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 Sep 2023 12:33:36 +0700 Subject: [PATCH 51/71] max3421 communication work with esp32 up to enumeration, seems still have a bit of issue --- .idea/cmake.xml | 7 +++++++ examples/host/cdc_msc_hid_freertos/src/cdc_app.c | 2 +- examples/host/cdc_msc_hid_freertos/src/main.c | 3 ++- hw/bsp/espressif/boards/family.c | 15 ++++++++++----- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/.idea/cmake.xml b/.idea/cmake.xml index 747f0fb58..ddeeb69fd 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -56,6 +56,13 @@ + + + + + + + \ No newline at end of file diff --git a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c index fc2b1228d..943e534d8 100644 --- a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c @@ -68,7 +68,7 @@ void cdc_app_task(void* param) { } } - taskYIELD(); + vTaskDelay(1); } } diff --git a/examples/host/cdc_msc_hid_freertos/src/main.c b/examples/host/cdc_msc_hid_freertos/src/main.c index d5574789f..88e742ee2 100644 --- a/examples/host/cdc_msc_hid_freertos/src/main.c +++ b/examples/host/cdc_msc_hid_freertos/src/main.c @@ -40,6 +40,7 @@ #include "freertos/timers.h" #define USBH_STACK_SIZE 4096 + #define CDC_STACK_SZIE 2048 #else #include "FreeRTOS.h" #include "semphr.h" @@ -49,9 +50,9 @@ // Increase stack size when debug log is enabled #define USBH_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) + #define CDC_STACK_SZIE (3*configMINIMAL_STACK_SIZE/2) #endif -#define CDC_STACK_SZIE (3*configMINIMAL_STACK_SIZE/2) //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTOTYPES diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index a04e1e7c5..5226f7e61 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -83,7 +83,6 @@ void board_init(void) { gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT); gpio_set_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN_ONLY : GPIO_PULLUP_ONLY); -#if CFG_TUD_ENABLED // USB Controller Hal init periph_module_reset(PERIPH_USB_MODULE); periph_module_enable(PERIPH_USB_MODULE); @@ -93,7 +92,6 @@ void board_init(void) { }; usb_hal_init(&hal); configure_pins(&hal); -#endif #if CFG_TUH_ENABLED && CFG_TUH_MAX3421 max3421_init(); @@ -157,8 +155,9 @@ int board_uart_write(void const *buf, int len) { } int board_getchar(void) { - char c; - return (uart_read_bytes(UART_NUM_0, &c, 1, 0) > 0) ? (int) c : (-1); +// char c; +// return (uart_read_bytes(UART_NUM_0, &c, 1, 0) > 0) ? (int) c : (-1); + return -1; } //--------------------------------------------------------------------+ @@ -187,7 +186,7 @@ static void max3421_intr_task(void* param) { while (1) { xSemaphoreTake(max3421_intr_sem, portMAX_DELAY); - tuh_int_handler(BOARD_TUH_RHPORT); + hcd_int_handler_ext(BOARD_TUH_RHPORT, false); } } @@ -251,6 +250,12 @@ void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { (void) rhport; + if (tx_len == 0) { + // fifo read, transmit rx_buf as dummy + tx_buf = rx_buf; + tx_len = rx_len; + } + spi_transaction_t xact = { .length = tx_len << 3, // length in bits .rxlength = rx_len << 3, // length in bits From 3b0ffd0f488671f1bafa4bcd9e22dd51f8bb6dee Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 Sep 2023 15:51:03 +0700 Subject: [PATCH 52/71] change hcd_int_handler(rhport, in_isr) signature: add in_isr change tuh_int_handler() to take in_isr as optional parameter (default = true) --- examples/host/bare_api/only.txt | 1 + examples/host/cdc_msc_hid/only.txt | 1 + examples/host/hid_controller/only.txt | 1 + examples/host/msc_file_explorer/only.txt | 1 + hw/bsp/imxrt/family.c | 4 +- hw/bsp/kinetis_kl/family.c | 2 +- hw/bsp/kinetis_kl/family.cmake | 75 +++++++++-------- .../boards/lpcxpresso1769/lpcxpresso1769.c | 2 +- hw/bsp/lpc17/boards/mbed1768/mbed1768.c | 2 +- hw/bsp/lpc18/family.c | 55 ++++++------- hw/bsp/lpc40/family.c | 2 +- hw/bsp/lpc43/family.c | 4 +- hw/bsp/msp432e4/family.c | 2 +- hw/bsp/ngx4330/ngx4330.c | 4 +- hw/bsp/nrf/family.c | 2 +- hw/bsp/ra/family.c | 6 +- hw/bsp/rx/boards/rx65n_target/rx65n_target.c | 2 +- hw/bsp/samd21/family.c | 2 +- hw/bsp/samd51/family.c | 2 +- hw/bsp/stm32g4/family.cmake | 79 +++++++++--------- hw/bsp/tm4c123/family.c | 2 +- src/common/tusb_common.h | 2 - src/common/tusb_timeout.h | 80 ------------------- src/common/tusb_verify.h | 52 ++++-------- src/host/hcd.h | 2 +- src/host/usbh.h | 11 ++- src/portable/analog/max3421/hcd_max3421.c | 3 +- src/portable/ehci/ehci.c | 4 +- src/portable/mentor/musb/hcd_musb.c | 4 +- src/portable/nxp/khci/hcd_khci.c | 7 +- src/portable/ohci/ohci.c | 5 +- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 4 +- src/portable/renesas/rusb2/hcd_rusb2.c | 5 +- src/portable/template/hcd_template.c | 3 +- src/tusb.h | 4 +- 35 files changed, 171 insertions(+), 266 deletions(-) delete mode 100644 src/common/tusb_timeout.h diff --git a/examples/host/bare_api/only.txt b/examples/host/bare_api/only.txt index 3837ac8a2..fee10f9e2 100644 --- a/examples/host/bare_api/only.txt +++ b/examples/host/bare_api/only.txt @@ -1,3 +1,4 @@ +mcu:KINETIS_KL mcu:LPC175X_6X mcu:LPC177X_8X mcu:LPC18XX diff --git a/examples/host/cdc_msc_hid/only.txt b/examples/host/cdc_msc_hid/only.txt index 3837ac8a2..fee10f9e2 100644 --- a/examples/host/cdc_msc_hid/only.txt +++ b/examples/host/cdc_msc_hid/only.txt @@ -1,3 +1,4 @@ +mcu:KINETIS_KL mcu:LPC175X_6X mcu:LPC177X_8X mcu:LPC18XX diff --git a/examples/host/hid_controller/only.txt b/examples/host/hid_controller/only.txt index 3837ac8a2..fee10f9e2 100644 --- a/examples/host/hid_controller/only.txt +++ b/examples/host/hid_controller/only.txt @@ -1,3 +1,4 @@ +mcu:KINETIS_KL mcu:LPC175X_6X mcu:LPC177X_8X mcu:LPC18XX diff --git a/examples/host/msc_file_explorer/only.txt b/examples/host/msc_file_explorer/only.txt index 3837ac8a2..fee10f9e2 100644 --- a/examples/host/msc_file_explorer/only.txt +++ b/examples/host/msc_file_explorer/only.txt @@ -1,3 +1,4 @@ +mcu:KINETIS_KL mcu:LPC175X_6X mcu:LPC177X_8X mcu:LPC18XX diff --git a/hw/bsp/imxrt/family.c b/hw/bsp/imxrt/family.c index ec95a8b24..32d89f794 100644 --- a/hw/bsp/imxrt/family.c +++ b/hw/bsp/imxrt/family.c @@ -188,7 +188,7 @@ void USB_OTG1_IRQHandler(void) #endif #if PORT_SUPPORT_HOST(0) - tuh_int_handler(0); + tuh_int_handler(0, true); #endif } @@ -199,7 +199,7 @@ void USB_OTG2_IRQHandler(void) #endif #if PORT_SUPPORT_HOST(1) - tuh_int_handler(1); + tuh_int_handler(1, true); #endif } diff --git a/hw/bsp/kinetis_kl/family.c b/hw/bsp/kinetis_kl/family.c index 3e9aa83a4..c436be3e6 100644 --- a/hw/bsp/kinetis_kl/family.c +++ b/hw/bsp/kinetis_kl/family.c @@ -39,7 +39,7 @@ void USB0_IRQHandler(void) { #if CFG_TUH_ENABLED - tuh_int_handler(0); + tuh_int_handler(0, true); #endif #if CFG_TUD_ENABLED tud_int_handler(0); diff --git a/hw/bsp/kinetis_kl/family.cmake b/hw/bsp/kinetis_kl/family.cmake index 793ef1783..4151979a0 100644 --- a/hw/bsp/kinetis_kl/family.cmake +++ b/hw/bsp/kinetis_kl/family.cmake @@ -22,48 +22,47 @@ set(FAMILY_MCUS KINETIS_KL CACHE INTERNAL "") #------------------------------------ # only need to be built ONCE for all examples function(add_board_target BOARD_TARGET) - if (NOT TARGET ${BOARD_TARGET}) - add_library(${BOARD_TARGET} STATIC - ${SDK_DIR}/drivers/gpio/fsl_gpio.c - ${SDK_DIR}/drivers/lpsci/fsl_lpsci.c - ${SDK_DIR}/drivers/uart/fsl_uart.c - ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c - ${SDK_DIR}/devices/${MCU_VARIANT}/system_${MCU_VARIANT}.c - ) - target_compile_definitions(${BOARD_TARGET} PUBLIC - ) - target_include_directories(${BOARD_TARGET} PUBLIC - ${CMSIS_DIR}/CMSIS/Core/Include - ${SDK_DIR}/devices/${MCU_VARIANT} - ${SDK_DIR}/devices/${MCU_VARIANT}/drivers - ${SDK_DIR}/drivers/common - ${SDK_DIR}/drivers/gpio - ${SDK_DIR}/drivers/lpsci - ${SDK_DIR}/drivers/port - ${SDK_DIR}/drivers/smc - ${SDK_DIR}/drivers/uart - ) + if (TARGET ${BOARD_TARGET}) + return() + endif () - update_board(${BOARD_TARGET}) + add_library(${BOARD_TARGET} STATIC + ${SDK_DIR}/drivers/gpio/fsl_gpio.c + ${SDK_DIR}/drivers/lpsci/fsl_lpsci.c + ${SDK_DIR}/drivers/uart/fsl_uart.c + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c + ${SDK_DIR}/devices/${MCU_VARIANT}/system_${MCU_VARIANT}.c + ) + target_compile_definitions(${BOARD_TARGET} PUBLIC + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMSIS_DIR}/CMSIS/Core/Include + ${SDK_DIR}/devices/${MCU_VARIANT} + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers + ${SDK_DIR}/drivers/common + ${SDK_DIR}/drivers/gpio + ${SDK_DIR}/drivers/lpsci + ${SDK_DIR}/drivers/port + ${SDK_DIR}/drivers/smc + ${SDK_DIR}/drivers/uart + ) + update_board(${BOARD_TARGET}) - # LD_FILE and STARTUP_FILE can be defined in board.cmake + # LD_FILE and STARTUP_FILE can be defined in board.cmake + target_sources(${BOARD_TARGET} PUBLIC + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) - target_sources(${BOARD_TARGET} PUBLIC - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + # nanolib + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" ) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - # nanolib - --specs=nosys.specs - --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endif () endfunction() diff --git a/hw/bsp/lpc17/boards/lpcxpresso1769/lpcxpresso1769.c b/hw/bsp/lpc17/boards/lpcxpresso1769/lpcxpresso1769.c index c7d655368..8c26b906f 100644 --- a/hw/bsp/lpc17/boards/lpcxpresso1769/lpcxpresso1769.c +++ b/hw/bsp/lpc17/boards/lpcxpresso1769/lpcxpresso1769.c @@ -37,7 +37,7 @@ void USB_IRQHandler(void) #endif #if CFG_TUH_ENABLED - tuh_int_handler(0); + tuh_int_handler(0, true); #endif } diff --git a/hw/bsp/lpc17/boards/mbed1768/mbed1768.c b/hw/bsp/lpc17/boards/mbed1768/mbed1768.c index b2c92d640..613dcb570 100644 --- a/hw/bsp/lpc17/boards/mbed1768/mbed1768.c +++ b/hw/bsp/lpc17/boards/mbed1768/mbed1768.c @@ -151,7 +151,7 @@ void USB_IRQHandler(void) #endif #if CFG_TUH_ENABLED - tuh_int_handler(0); + tuh_int_handler(0, true); #endif } diff --git a/hw/bsp/lpc18/family.c b/hw/bsp/lpc18/family.c index b11f4fe0e..e6abecb4b 100644 --- a/hw/bsp/lpc18/family.c +++ b/hw/bsp/lpc18/family.c @@ -43,25 +43,23 @@ //--------------------------------------------------------------------+ // USB Interrupt Handler //--------------------------------------------------------------------+ -void USB0_IRQHandler(void) -{ +void USB0_IRQHandler(void) { #if PORT_SUPPORT_DEVICE(0) - tud_int_handler(0); + tud_int_handler(0); #endif #if PORT_SUPPORT_HOST(0) - tuh_int_handler(0); + tuh_int_handler(0, true); #endif } -void USB1_IRQHandler(void) -{ +void USB1_IRQHandler(void) { #if PORT_SUPPORT_DEVICE(1) - tud_int_handler(1); + tud_int_handler(1); #endif #if PORT_SUPPORT_HOST(1) - tuh_int_handler(1); + tuh_int_handler(1, true); #endif } @@ -74,28 +72,26 @@ const uint32_t OscRateIn = 12000000; const uint32_t ExtRateIn = 0; // Invoked by startup code -void SystemInit(void) -{ +void SystemInit(void) { #ifdef __USE_LPCOPEN - extern void (* const g_pfnVectors[])(void); + extern void (*const g_pfnVectors[])(void); unsigned int *pSCB_VTOR = (unsigned int *) 0xE000ED08; - *pSCB_VTOR = (unsigned int) g_pfnVectors; + *pSCB_VTOR = (unsigned int) g_pfnVectors; #endif board_lpc18_pinmux(); - #ifdef TRACE_ETM +#ifdef TRACE_ETM // Trace clock is limited to 60MHz, limit CPU clock to 120MHz Chip_SetupCoreClock(CLKIN_CRYSTAL, 120000000UL, true); - #else +#else // CPU clock max to 180 Mhz Chip_SetupCoreClock(CLKIN_CRYSTAL, MAX_CLOCK_FREQ, true); - #endif +#endif } -void board_init(void) -{ +void board_init(void) { SystemCoreClockUpdate(); #if CFG_TUSB_OS == OPT_OS_NONE @@ -135,27 +131,22 @@ void board_init(void) // Board porting API //--------------------------------------------------------------------+ -void board_led_write(bool state) -{ +void board_led_write(bool state) { Chip_GPIO_SetPinState(LPC_GPIO_PORT, LED_PORT, LED_PIN, state); } -uint32_t board_button_read(void) -{ +uint32_t board_button_read(void) { // active low return Chip_GPIO_GetPinState(LPC_GPIO_PORT, BUTTON_PORT, BUTTON_PIN) ? 0 : 1; } -int board_uart_read(uint8_t* buf, int len) -{ +int board_uart_read(uint8_t *buf, int len) { return Chip_UART_Read(UART_DEV, buf, len); } -int board_uart_write(void const * buf, int len) -{ - uint8_t const* buf8 = (uint8_t const*) buf; - for(int i=0; iINTFLAG.reg = EIC_INTFLAG_EXTINT(1 << MAX3421_INTR_EIC_ID); // Call the TinyUSB interrupt handler - tuh_int_handler(1); + tuh_int_handler(1, true); } void tuh_max3421_int_api(uint8_t rhport, bool enabled) { diff --git a/hw/bsp/samd51/family.c b/hw/bsp/samd51/family.c index 2cf00c7af..268d60e48 100644 --- a/hw/bsp/samd51/family.c +++ b/hw/bsp/samd51/family.c @@ -296,7 +296,7 @@ void MAX3421_EIC_Handler(void) { EIC->INTFLAG.reg = EIC_INTFLAG_EXTINT(1 << MAX3421_INTR_EIC_ID); // Call the TinyUSB interrupt handler - tuh_int_handler(1); + tuh_int_handler(1, true); } void tuh_max3421_int_api(uint8_t rhport, bool enabled) { diff --git a/hw/bsp/stm32g4/family.cmake b/hw/bsp/stm32g4/family.cmake index 675a96c74..f8cabcbe5 100644 --- a/hw/bsp/stm32g4/family.cmake +++ b/hw/bsp/stm32g4/family.cmake @@ -26,50 +26,47 @@ set(FAMILY_MCUS STM32G4 CACHE INTERNAL "") #------------------------------------ # only need to be built ONCE for all examples function(add_board_target BOARD_TARGET) - if (NOT TARGET ${BOARD_TARGET}) - # Startup & Linker script - set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) - set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) + if (TARGET ${BOARD_TARGET}) + return() + endif () - add_library(${BOARD_TARGET} STATIC - ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_cortex.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr_ex.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} - ) - target_include_directories(${BOARD_TARGET} PUBLIC - ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${CMSIS_5}/CMSIS/Core/Include - ${ST_CMSIS}/Include - ${ST_HAL_DRIVER}/Inc - ) - target_compile_options(${BOARD_TARGET} PUBLIC - ) - target_compile_definitions(${BOARD_TARGET} PUBLIC - ) + # Startup & Linker script + set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) + set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) + set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) - update_board(${BOARD_TARGET}) + add_library(${BOARD_TARGET} STATIC + ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_cortex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMSIS_5}/CMSIS/Core/Include + ${ST_CMSIS}/Include + ${ST_HAL_DRIVER}/Inc + ) + update_board(${BOARD_TARGET}) - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - # nanolib - --specs=nosys.specs - --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + # nanolib + --specs=nosys.specs + --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) endif () endfunction() diff --git a/hw/bsp/tm4c123/family.c b/hw/bsp/tm4c123/family.c index ad5ae505f..738bc3fa0 100644 --- a/hw/bsp/tm4c123/family.c +++ b/hw/bsp/tm4c123/family.c @@ -8,7 +8,7 @@ void USB0_Handler(void) { #if CFG_TUH_ENABLED - tuh_int_handler(0); + tuh_int_handler(0, true); #endif #if CFG_TUD_ENABLED diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 6fffed11c..caeb5f2ef 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -75,8 +75,6 @@ #include "tusb_types.h" #include "tusb_debug.h" -#include "tusb_timeout.h" // TODO remove - //--------------------------------------------------------------------+ // Optional API implemented by application if needed // TODO move to a more ovious place/file diff --git a/src/common/tusb_timeout.h b/src/common/tusb_timeout.h deleted file mode 100644 index 533e67ab8..000000000 --- a/src/common/tusb_timeout.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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_Common Common Files - * \defgroup Group_TimeoutTimer timeout timer - * @{ */ - -#ifndef _TUSB_TIMEOUT_H_ -#define _TUSB_TIMEOUT_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - uint32_t start; - uint32_t interval; -}tu_timeout_t; - -#if 0 - -extern uint32_t tusb_hal_millis(void); - -static inline void tu_timeout_set(tu_timeout_t* tt, uint32_t msec) -{ - tt->interval = msec; - tt->start = tusb_hal_millis(); -} - -static inline bool tu_timeout_expired(tu_timeout_t* tt) -{ - return ( tusb_hal_millis() - tt->start ) >= tt->interval; -} - -// For used with periodic event to prevent drift -static inline void tu_timeout_reset(tu_timeout_t* tt) -{ - tt->start += tt->interval; -} - -static inline void tu_timeout_restart(tu_timeout_t* tt) -{ - tt->start = tusb_hal_millis(); -} - -#endif - -#ifdef __cplusplus - } -#endif - -#endif /* _TUSB_TIMEOUT_H_ */ - -/** @} */ diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 12355e8be..1b5f53dfc 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -56,12 +56,8 @@ * #define TU_VERIFY(cond) if(cond) return false; * #define TU_VERIFY(cond,ret) if(cond) return ret; * - * #define TU_VERIFY_HDLR(cond,handler) if(cond) {handler; return false;} - * #define TU_VERIFY_HDLR(cond,ret,handler) if(cond) {handler; return ret;} - * * #define TU_ASSERT(cond) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return false;} * #define TU_ASSERT(cond,ret) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return ret;} - * *------------------------------------------------------------------*/ #ifdef __cplusplus @@ -97,40 +93,23 @@ #define TU_BREAKPOINT() do {} while (0) #endif -/*------------------------------------------------------------------*/ -/* Macro Generator - *------------------------------------------------------------------*/ - // Helper to implement optional parameter for TU_VERIFY Macro family #define _GET_3RD_ARG(arg1, arg2, arg3, ...) arg3 -#define _GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4 - -/*------------- Generator for TU_VERIFY and TU_VERIFY_HDLR -------------*/ -#define TU_VERIFY_DEFINE(_cond, _handler, _ret) do \ -{ \ - if ( !(_cond) ) { _handler; return _ret; } \ -} while(0) /*------------------------------------------------------------------*/ /* TU_VERIFY * - TU_VERIFY_1ARGS : return false if failed * - TU_VERIFY_2ARGS : return provided value if failed *------------------------------------------------------------------*/ -#define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, , false) -#define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, , _ret) +#define TU_VERIFY_DEFINE(_cond, _ret) \ + do { \ + if ( !(_cond) ) { return _ret; } \ + } while(0) -#define TU_VERIFY(...) _GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, UNUSED)(__VA_ARGS__) +#define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, false) +#define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _ret) - -/*------------------------------------------------------------------*/ -/* TU_VERIFY WITH HANDLER - * - TU_VERIFY_HDLR_2ARGS : execute handler, return false if failed - * - TU_VERIFY_HDLR_3ARGS : execute handler, return provided error if failed - *------------------------------------------------------------------*/ -#define TU_VERIFY_HDLR_2ARGS(_cond, _handler) TU_VERIFY_DEFINE(_cond, _handler, false) -#define TU_VERIFY_HDLR_3ARGS(_cond, _handler, _ret) TU_VERIFY_DEFINE(_cond, _handler, _ret) - -#define TU_VERIFY_HDLR(...) _GET_4TH_ARG(__VA_ARGS__, TU_VERIFY_HDLR_3ARGS, TU_VERIFY_HDLR_2ARGS,UNUSED)(__VA_ARGS__) +#define TU_VERIFY(...) _GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, _dummy)(__VA_ARGS__) /*------------------------------------------------------------------*/ /* ASSERT @@ -138,19 +117,20 @@ * - 1 arg : return false if failed * - 2 arg : return error if failed *------------------------------------------------------------------*/ -#define ASSERT_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), false) -#define ASSERT_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _MESS_FAILED(); TU_BREAKPOINT(), _ret) +#define TU_ASSERT_DEFINE(_cond, _ret) \ + do { \ + if ( !(_cond) ) { _MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \ + } while(0) + +#define TU_ASSERT_1ARGS(_cond) TU_ASSERT_DEFINE(_cond, false) +#define TU_ASSERT_2ARGS(_cond, _ret) TU_ASSERT_DEFINE(_cond, _ret) #ifndef TU_ASSERT -#define TU_ASSERT(...) _GET_3RD_ARG(__VA_ARGS__, ASSERT_2ARGS, ASSERT_1ARGS,UNUSED)(__VA_ARGS__) +#define TU_ASSERT(...) _GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_2ARGS, TU_ASSERT_1ARGS, _dummy)(__VA_ARGS__) #endif -/*------------------------------------------------------------------*/ -/* ASSERT HDLR - *------------------------------------------------------------------*/ - #ifdef __cplusplus } #endif -#endif /* TUSB_VERIFY_H_ */ +#endif diff --git a/src/host/hcd.h b/src/host/hcd.h index e25b20ea3..2bde289df 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -131,7 +131,7 @@ bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) TU_AT bool hcd_init(uint8_t rhport); // Interrupt Handler -void hcd_int_handler(uint8_t rhport); +void hcd_int_handler(uint8_t rhport, bool in_isr); // Enable USB interrupt void hcd_int_enable (uint8_t rhport); diff --git a/src/host/usbh.h b/src/host/usbh.h index 684e8240e..770d70dfe 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -124,11 +124,16 @@ void tuh_task(void) { bool tuh_task_event_ready(void); #ifndef _TUSB_HCD_H_ -extern void hcd_int_handler(uint8_t rhport); +extern void hcd_int_handler(uint8_t rhport, bool in_isr); #endif -// Interrupt handler, name alias to HCD -#define tuh_int_handler hcd_int_handler +// Interrupt handler alias to HCD with in_isr as optional parameter +// - tuh_int_handler(rhport) --> hcd_int_handler(rhport, true) +// - tuh_int_handler(rhport, in_isr) --> hcd_int_handler(rhport, in_isr) +// Note: this is similar to TU_VERIFY(), _GET_3RD_ARG() is defined in tusb_verify.h +#define _tuh_int_handler_1arg(_rhport) hcd_int_handler(_rhport, true) +#define _tuh_int_hanlder_2arg(_rhport, _in_isr) hcd_int_handler(_rhport, _in_isr) +#define tuh_int_handler(...) _GET_3RD_ARG(__VA_ARGS__, _tuh_int_hanlder_2arg, _tuh_int_handler_1arg, _dummy)(__VA_ARGS__) // Check if roothub port is initialized and active as a host bool tuh_rhport_is_active(uint8_t rhport); diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 238b518a0..d013d6179 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -863,7 +863,8 @@ void print_hirq(uint8_t hirq) { #endif // Interrupt Handler -void hcd_int_handler(uint8_t rhport) { +void hcd_int_handler(uint8_t rhport, bool in_isr) { + (void) in_isr; uint8_t hirq = reg_read(rhport, HIRQ_ADDR, true) & _hcd_data.hien; if (!hirq) return; // print_hirq(hirq); diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index c93c33fc0..572b9826c 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -656,8 +656,8 @@ void process_period_xfer_isr(uint8_t rhport, uint32_t interval_ms) } //------------- Host Controller Driver's Interrupt Handler -------------// -void hcd_int_handler(uint8_t rhport) -{ +void hcd_int_handler(uint8_t rhport, bool in_isr) { + (void) in_isr; ehci_registers_t* regs = ehci_data.regs; uint32_t const int_status = regs->status; diff --git a/src/portable/mentor/musb/hcd_musb.c b/src/portable/mentor/musb/hcd_musb.c index 02090df85..5312c2812 100644 --- a/src/portable/mentor/musb/hcd_musb.c +++ b/src/portable/mentor/musb/hcd_musb.c @@ -847,8 +847,10 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { /*------------------------------------------------------------------- * ISR *-------------------------------------------------------------------*/ -void hcd_int_handler(uint8_t rhport) +void hcd_int_handler(uint8_t rhport, bool in_isr) { + (void) in_isr; + uint_fast8_t is, txis, rxis; is = USB0->IS; /* read and clear interrupt status */ diff --git a/src/portable/nxp/khci/hcd_khci.c b/src/portable/nxp/khci/hcd_khci.c index 55327e02d..57684b259 100644 --- a/src/portable/nxp/khci/hcd_khci.c +++ b/src/portable/nxp/khci/hcd_khci.c @@ -447,6 +447,10 @@ void hcd_port_reset(uint8_t rhport) _hcd.need_reset = false; } +void hcd_port_reset_end(uint8_t rhport) { + (void) rhport; +} + tusb_speed_t hcd_port_speed_get(uint8_t rhport) { (void)rhport; @@ -583,8 +587,9 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { /*--------------------------------------------------------------------+ * ISR *--------------------------------------------------------------------+*/ -void hcd_int_handler(uint8_t rhport) +void hcd_int_handler(uint8_t rhport, bool in_isr) { + (void) in_isr; uint32_t is = KHCI->ISTAT; uint32_t msk = KHCI->INTEN; diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index 413e72037..f978b0965 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -667,8 +667,9 @@ static void done_queue_isr(uint8_t hostid) } } -void hcd_int_handler(uint8_t hostid) -{ +void hcd_int_handler(uint8_t hostid, bool in_isr) { + (void) in_isr; + uint32_t const int_en = OHCI_REG->interrupt_enable; uint32_t const int_status = OHCI_REG->interrupt_status & int_en; diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 21dc3f67d..4ed6d36bb 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -252,9 +252,9 @@ static void __tusb_irq_path_func(hcd_rp2040_irq)(void) } } -void __tusb_irq_path_func(hcd_int_handler)(uint8_t rhport) -{ +void __tusb_irq_path_func(hcd_int_handler)(uint8_t rhport, bool in_isr) { (void) rhport; + (void) in_isr; hcd_rp2040_irq(); } diff --git a/src/portable/renesas/rusb2/hcd_rusb2.c b/src/portable/renesas/rusb2/hcd_rusb2.c index 790cd6b32..bf95be707 100644 --- a/src/portable/renesas/rusb2/hcd_rusb2.c +++ b/src/portable/renesas/rusb2/hcd_rusb2.c @@ -771,8 +771,9 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { //--------------------------------------------------------------------+ // ISR //--------------------------------------------------------------------+ -void hcd_int_handler(uint8_t rhport) -{ +void hcd_int_handler(uint8_t rhport, bool in_isr) { + (void) in_isr; + rusb2_reg_t* rusb = RUSB2_REG(rhport); unsigned is0 = rusb->INTSTS0; unsigned is1 = rusb->INTSTS1; diff --git a/src/portable/template/hcd_template.c b/src/portable/template/hcd_template.c index 3e3b91558..b073d6057 100644 --- a/src/portable/template/hcd_template.c +++ b/src/portable/template/hcd_template.c @@ -51,8 +51,9 @@ bool hcd_init(uint8_t rhport) { } // Interrupt Handler -void hcd_int_handler(uint8_t rhport) { +void hcd_int_handler(uint8_t rhport, bool in_isr) { (void) rhport; + (void) in_isr; } // Enable USB interrupt diff --git a/src/tusb.h b/src/tusb.h index d6534ca28..c9d56d3c3 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -66,7 +66,7 @@ #endif #else #ifndef tuh_int_handler - #define tuh_int_handler(_x) + #define tuh_int_handler(...) #endif #endif @@ -123,7 +123,7 @@ #endif #else #ifndef tud_int_handler - #define tud_int_handler(_x) + #define tud_int_handler(...) #endif #endif From 0a4fb6963de9a62be613cab5ab33f70c2e836b3d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 Sep 2023 16:19:39 +0700 Subject: [PATCH 53/71] fix build with lpc54 --- .github/workflows/build_arm.yml | 2 +- .github/workflows/cmake_arm.yml | 2 +- hw/bsp/family_support.cmake | 1 + hw/bsp/lpc54/FreeRTOSConfig/FreeRTOSConfig.h | 165 ++++++++++++++++++ .../lpc54/boards/lpcxpresso54114/board.cmake | 21 +++ .../lpc54/boards/lpcxpresso54608/board.cmake | 22 +++ hw/bsp/lpc54/family.cmake | 138 +++++++-------- 7 files changed, 281 insertions(+), 70 deletions(-) create mode 100644 hw/bsp/lpc54/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/lpc54/boards/lpcxpresso54114/board.cmake create mode 100644 hw/bsp/lpc54/boards/lpcxpresso54608/board.cmake diff --git a/.github/workflows/build_arm.yml b/.github/workflows/build_arm.yml index 975f351a0..c7462f0d7 100644 --- a/.github/workflows/build_arm.yml +++ b/.github/workflows/build_arm.yml @@ -36,7 +36,7 @@ jobs: - 'broadcom_32bit' - 'kinetis_k32l2' - 'lpc11 lpc13 lpc15 lpc17' - - 'lpc51 lpc54' + - 'lpc51' - 'mm32 msp432e4' - 'samd11 same5x saml2x' - 'stm32f2 stm32f3' diff --git a/.github/workflows/cmake_arm.yml b/.github/workflows/cmake_arm.yml index 4b788a213..5dc36ee2c 100644 --- a/.github/workflows/cmake_arm.yml +++ b/.github/workflows/cmake_arm.yml @@ -36,7 +36,7 @@ jobs: - 'imxrt' - 'kinetis_kl' - 'lpc18 lpc40 lpc43' - - 'lpc55' + - 'lpc54 lpc55' - 'mcx' - 'nrf' - 'ra' diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 642282b0e..9c625b58e 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -40,6 +40,7 @@ if (NOT FAMILY STREQUAL rp2040) # enable LTO if supported skip rp2040 include(CheckIPOSupported) check_ipo_supported(RESULT IPO_SUPPORTED) + cmake_print_variables(IPO_SUPPORTED) if (IPO_SUPPORTED) set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) endif() diff --git a/hw/bsp/lpc54/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/lpc54/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..fc0ab1f2d --- /dev/null +++ b/hw/bsp/lpc54/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,165 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + #include "fsl_device_registers.h" +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 0 +#define configSUPPORT_DYNAMIC_ALLOCATION 1 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* Define to trap errors during development. */ +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 +#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) + #define configASSERT(_exp) \ + do {\ + if ( !(_exp) ) { \ + volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ + if ( (*ARM_CM_DHCSR) & 1UL ) { /* Only halt mcu if debugger is attached */ \ + taskDISABLE_INTERRUPTS(); \ + __asm("BKPT #0\n"); \ + }\ + }\ + } while(0) +#else + #define configASSERT( x ) +#endif + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +#define configPRIO_BITS 3 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<) #------------------------------------ # only need to be built ONCE for all examples function(add_board_target BOARD_TARGET) - if (NOT TARGET ${BOARD_TARGET}) - add_library(${BOARD_TARGET} STATIC - # driver - ${SDK_DIR}/drivers/lpc_gpio/fsl_gpio.c - ${SDK_DIR}/drivers/common/fsl_common_arm.c - ${SDK_DIR}/drivers/flexcomm/fsl_flexcomm.c - ${SDK_DIR}/drivers/flexcomm/fsl_usart.c - # mcu - ${SDK_DIR}/devices/${MCU_VARIANT}/system_${MCU_CORE}.c - ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c - ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_power.c - ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_reset.c - ) + if (TARGET ${BOARD_TARGET}) + return() + endif() + add_library(${BOARD_TARGET} STATIC + # driver + ${SDK_DIR}/drivers/lpc_gpio/fsl_gpio.c + ${SDK_DIR}/drivers/common/fsl_common_arm.c + ${SDK_DIR}/drivers/flexcomm/fsl_flexcomm.c + ${SDK_DIR}/drivers/flexcomm/fsl_usart.c + # mcu + ${SDK_DIR}/devices/${MCU_VARIANT}/system_${MCU_CORE}.c + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_power.c + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_reset.c + ) + + target_compile_definitions(${BOARD_TARGET} PUBLIC + CFG_TUSB_MEM_ALIGN=TU_ATTR_ALIGNED\(64\) + BOARD_TUD_RHPORT=${PORT} + BOARD_TUH_RHPORT=${HOST_PORT} + ) + # Port 0 is Fullspeed, Port 1 is Highspeed. Port1 controller can only access USB_SRAM + if (PORT EQUAL 1) target_compile_definitions(${BOARD_TARGET} PUBLIC - CFG_TUSB_MEM_ALIGN=TU_ATTR_ALIGNED\(64\) - BOARD_TUD_RHPORT=${PORT} - BOARD_TUH_RHPORT=${HOST_PORT} + BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED + BOARD_TUH_MAX_SPEED=OPT_MODE_FULL_SPEED + CFG_TUD_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\) ) - # Port 0 is Fullspeed, Port 1 is Highspeed. Port1 controller can only access USB_SRAM - if (PORT EQUAL 1) - target_compile_definitions(${BOARD_TARGET} PUBLIC - BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED - BOARD_TUH_MAX_SPEED=OPT_MODE_FULL_SPEED - CFG_TUD_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\) - ) - else () - target_compile_definitions(${BOARD_TARGET} PUBLIC - BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED - BOARD_TUH_MAX_SPEED=OPT_MODE_HIGH_SPEED - CFG_TUH_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\) - #CFG_TUD_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\) - ) - endif () - - target_include_directories(${BOARD_TARGET} PUBLIC - ${TOP}/lib/sct_neopixel - # driver - ${SDK_DIR}/drivers/common - ${SDK_DIR}/drivers/flexcomm - ${SDK_DIR}/drivers/lpc_iocon - ${SDK_DIR}/drivers/lpc_gpio - ${SDK_DIR}/drivers/lpuart - ${SDK_DIR}/drivers/sctimer - # mcu - ${CMSIS_DIR}/CMSIS/Core/Include - ${SDK_DIR}/devices/${MCU_VARIANT} - ${SDK_DIR}/devices/${MCU_VARIANT}/drivers + else () + target_compile_definitions(${BOARD_TARGET} PUBLIC + BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED + BOARD_TUH_MAX_SPEED=OPT_MODE_HIGH_SPEED + CFG_TUH_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\) + #CFG_TUD_MEM_SECTION=__attribute__\(\(section\(\"m_usb_global\"\)\)\) ) + endif () - update_board(${BOARD_TARGET}) + target_include_directories(${BOARD_TARGET} PUBLIC + ${TOP}/lib/sct_neopixel + # driver + ${SDK_DIR}/drivers/common + ${SDK_DIR}/drivers/flexcomm + ${SDK_DIR}/drivers/lpc_iocon + ${SDK_DIR}/drivers/lpc_gpio + ${SDK_DIR}/drivers/lpuart + ${SDK_DIR}/drivers/sctimer + # mcu + ${CMSIS_DIR}/CMSIS/Core/Include + ${SDK_DIR}/devices/${MCU_VARIANT} + ${SDK_DIR}/devices/${MCU_VARIANT}/drivers + ) - if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) - set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld) - endif () + update_board(${BOARD_TARGET}) - if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID}) - set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_CORE}.S) - endif () + if (NOT DEFINED LD_FILE_${CMAKE_C_COMPILER_ID}) + set(LD_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/${MCU_CORE}_flash.ld) + endif () - target_sources(${BOARD_TARGET} PUBLIC - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + if (NOT DEFINED STARTUP_FILE_${CMAKE_C_COMPILER_ID}) + set(STARTUP_FILE_GNU ${SDK_DIR}/devices/${MCU_VARIANT}/gcc/startup_${MCU_CORE}.S) + endif () + + target_sources(${BOARD_TARGET} PUBLIC + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + # linker file + "LINKER:--script=${LD_FILE_GNU}" + # nanolib + --specs=nosys.specs + --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" ) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - # linker file - "LINKER:--script=${LD_FILE_GNU}" - # nanolib - --specs=nosys.specs - --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () endif () endfunction() From 58c49cea5b94dcf45b0b2117afc3fc8ce646732c Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 Sep 2023 16:31:46 +0700 Subject: [PATCH 54/71] remove sct_neopixel from lpc54 (due to warnings and not used) --- hw/bsp/lpc54/family.cmake | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/bsp/lpc54/family.cmake b/hw/bsp/lpc54/family.cmake index a1f876844..cdd513fe4 100644 --- a/hw/bsp/lpc54/family.cmake +++ b/hw/bsp/lpc54/family.cmake @@ -126,8 +126,6 @@ function(family_configure_example TARGET RTOS) # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c - # external driver - ${TOP}/lib/sct_neopixel/sct_neopixel.c ) # https://github.com/gsteiert/sct_neopixel/pull/1 From b35621fc63defdd3191d569c8248dae52997ce8f Mon Sep 17 00:00:00 2001 From: Mengsk Date: Wed, 27 Sep 2023 11:37:16 +0200 Subject: [PATCH 55/71] Update IAR template. --- tools/iar_gen.py | 123 ++++++++++------ tools/iar_template.ipcf | 316 +++++++++++++++++++++------------------- 2 files changed, 241 insertions(+), 198 deletions(-) diff --git a/tools/iar_gen.py b/tools/iar_gen.py index 73c8b29fc..646a581f4 100644 --- a/tools/iar_gen.py +++ b/tools/iar_gen.py @@ -1,51 +1,84 @@ #!/usr/bin/python3 import os +import sys import xml.dom.minidom as XML +import glob -# Read base configuration -base = "" -with open("iar_template.ipcf") as f: - base = f.read() +def Main(): + # Read base configuration + base = "" + with open("iar_template.ipcf") as f: + base = f.read() -# Enumerate all device/host examples -dir_1 = os.listdir("../examples") -for dir_2 in dir_1: - if os.path.isdir("../examples/{}".format(dir_2)): - print(dir_2) - examples = os.listdir("../examples/{}".format(dir_2)) - for example in examples: - if os.path.isdir("../examples/{}/{}".format(dir_2, example)): - print("../examples/{}/{}".format(dir_2, example)) - conf = XML.parseString(base) - files = conf.getElementsByTagName("files")[0] - inc = conf.getElementsByTagName("includePath")[0] - # Add bsp inc - path = conf.createElement('path') - path_txt = conf.createTextNode("$TUSB_DIR$/hw") - path.appendChild(path_txt) - inc.appendChild(path) - # Add board.c/.h - grp = conf.createElement('group') - grp.setAttribute("name", "bsp") - path = conf.createElement('path') - path_txt = conf.createTextNode("$TUSB_DIR$/hw/bsp/board.c") - path.appendChild(path_txt) - grp.appendChild(path) - files.appendChild(grp) - # Add example's .c/.h - grp = conf.createElement('group') - grp.setAttribute("name", "example") - for file in os.listdir("../examples/{}/{}/src".format(dir_2, example)): - if file.endswith(".c") or file.endswith(".h"): - path = conf.createElement('path') - path.setAttribute("copyTo", "$PROJ_DIR$/{}".format(file)) - path_txt = conf.createTextNode("$TUSB_DIR$/examples/{0}/{1}/src/{2}".format(dir_2, example, file)) - path.appendChild(path_txt) - grp.appendChild(path) - files.appendChild(grp) - cfg_str = conf.toprettyxml() - cfg_str = '\n'.join([s for s in cfg_str.splitlines() if s.strip()]) - #print(cfg_str) - with open("../examples/{0}/{1}/iar_{1}.ipcf".format(dir_2, example), 'w') as f: - f.write(cfg_str) + # Enumerate all device/host examples + dir_1 = os.listdir("../examples") + for dir_2 in dir_1: + if os.path.isdir("../examples/{}".format(dir_2)): + print(dir_2) + examples = os.listdir("../examples/{}".format(dir_2)) + for example in examples: + if os.path.isdir("../examples/{}/{}".format(dir_2, example)): + print("../examples/{}/{}".format(dir_2, example)) + conf = XML.parseString(base) + files = conf.getElementsByTagName("files")[0] + inc = conf.getElementsByTagName("includePath")[0] + # Add bsp inc + path = conf.createElement('path') + path_txt = conf.createTextNode("$TUSB_DIR$/hw") + path.appendChild(path_txt) + inc.appendChild(path) + # Add board.c/.h + grp = conf.createElement('group') + grp.setAttribute("name", "bsp") + path = conf.createElement('path') + path_txt = conf.createTextNode("$TUSB_DIR$/hw/bsp/board.c") + path.appendChild(path_txt) + grp.appendChild(path) + files.appendChild(grp) + # Add example's .c/.h + grp = conf.createElement('group') + grp.setAttribute("name", "example") + for file in os.listdir("../examples/{}/{}/src".format(dir_2, example)): + if file.endswith(".c") or file.endswith(".h"): + path = conf.createElement('path') + path.setAttribute("copyTo", "$PROJ_DIR$/{}".format(file)) + path_txt = conf.createTextNode("$TUSB_DIR$/examples/{0}/{1}/src/{2}".format(dir_2, example, file)) + path.appendChild(path_txt) + grp.appendChild(path) + files.appendChild(grp) + cfg_str = conf.toprettyxml() + cfg_str = '\n'.join([s for s in cfg_str.splitlines() if s.strip()]) + #print(cfg_str) + with open("../examples/{0}/{1}/iar_{1}.ipcf".format(dir_2, example), 'w') as f: + f.write(cfg_str) + +def ListPath(path, blacklist=[]): + # Get all .c files + files = glob.glob(f'../{path}/**/*.c', recursive=True) + # Filter + files = [x for x in files if all(y not in x for y in blacklist)] + # Get common dir list + dirs = [] + for file in files: + dir = os.path.dirname(file) + if dir not in dirs: + dirs.append(dir) + # Print .c groupped by dir + for dir in dirs: + print('') + for file in files: + if os.path.dirname(file) == dir: + print(' $TUSB_DIR$/' + file.replace('../','').replace('\\','/')+'') + print('') + +def List(): + ListPath('src', [ 'template.c', 'dcd_synopsys.c', 'dcd_esp32sx.c' ]) + ListPath('lib/SEGGER_RTT') + +if __name__ == "__main__": + if (len(sys.argv) > 1): + if (sys.argv[1] == 'l'): + List() + else: + Main() diff --git a/tools/iar_template.ipcf b/tools/iar_template.ipcf index 6ea1d576d..4919fe7b4 100644 --- a/tools/iar_template.ipcf +++ b/tools/iar_template.ipcf @@ -4,166 +4,176 @@ $TUSB_DIR$/src $TUSB_DIR$/lib/SEGGER_RTT/RTT + $TUSB_DIR$/lib/SEGGER_RTT/Config $PROJ_DIR$ - - $TUSB_DIR$/src/device/usbd.c - $TUSB_DIR$/src/device/usbd_control.c - - - $TUSB_DIR$/src/common/tusb_fifo.c - - - $TUSB_DIR$/src/class/audio/audio_device.c - - - $TUSB_DIR$/src/class/bth/bth_device.c - - - $TUSB_DIR$/src/class/cdc/cdc_device.c - $TUSB_DIR$/src/class/cdc/cdc_host.c - $TUSB_DIR$/src/class/cdc/cdc_rndis_host.c - - - $TUSB_DIR$/src/class/dfu/dfu_device.c - $TUSB_DIR$/src/class/dfu/dfu_rt_device.c - - - $TUSB_DIR$/src/class/hid/hid_device.c - $TUSB_DIR$/src/class/hid/hid_host.c - - - $TUSB_DIR$/src/class/midi/midi_device.c - - - $TUSB_DIR$/src/class/msc/msc_device.c - $TUSB_DIR$/src/class/msc/msc_host.c - - - $TUSB_DIR$/src/class/net/ecm_rndis_device.c - $TUSB_DIR$/src/class/net/ncm_device.c - - - $TUSB_DIR$/src/class/usbtmc/usbtmc_device.c - - - $TUSB_DIR$/src/class/vendor/vendor_device.c - $TUSB_DIR$/src/class/vendor/vendor_host.c - $TUSB_DIR$/src/tusb.c - - $TUSB_DIR$/src/host/hub.c - $TUSB_DIR$/src/host/usbh.c - - - $TUSB_DIR$/src/portable/bridgetek/ft9xx/dcd_ft9xx.c - - - $TUSB_DIR$/src/portable/chipidea/ci_hs/dcd_ci_hs.c - $TUSB_DIR$/src/portable/chipidea/ci_hs/hcd_ci_hs.c - - - $TUSB_DIR$/src/portable/synopsys/dwc2/dcd_dwc2.c - - - $TUSB_DIR$/src/portable/dialog/da146xx/dcd_da146xx.c - - - $TUSB_DIR$/src/portable/ehci/ehci.c - - - $TUSB_DIR$/src/portable/espressif/esp32sx/dcd_esp32sx.c - - - $TUSB_DIR$/src/portable/mentor/musb/dcd_musb.c - $TUSB_DIR$/src/portable/mentor/musb/hcd_musb.c - - - $TUSB_DIR$/src/portable/microchip/samd/dcd_samd.c - - - $TUSB_DIR$/src/portable/microchip/samg/dcd_samg.c - - - $TUSB_DIR$/src/portable/microchip/samx7x/dcd_samx7x.c - - - $TUSB_DIR$/src/portable/microchip/pic/dcd_pic.c - - - $TUSB_DIR$/src/portable/microchip/pic32mz/dcd_pic32mz.c - - - $TUSB_DIR$/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c - - - $TUSB_DIR$/src/portable/nordic/nrf5x/dcd_nrf5x.c - - - $TUSB_DIR$/src/portable/nuvoton/nuc120/dcd_nuc120.c - - - $TUSB_DIR$/src/portable/nuvoton/nuc121/dcd_nuc121.c - - - $TUSB_DIR$/src/portable/nuvoton/nuc505/dcd_nuc505.c - - - $TUSB_DIR$/src/portable/nxp/khci/dcd_khci.c - $TUSB_DIR$/src/portable/nxp/khci/hcd_khci.c - - - $TUSB_DIR$/src/portable/nxp/lpc17_40/dcd_lpc17_40.c - $TUSB_DIR$/src/portable/nxp/lpc17_40/hcd_lpc17_40.c - - - $TUSB_DIR$/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c - - - $TUSB_DIR$/src/portable/nxp/transdimension/dcd_transdimension.c - $TUSB_DIR$/src/portable/nxp/transdimension/hcd_transdimension.c - - - $TUSB_DIR$/src/portable/ohci/ohci.c - - - $TUSB_DIR$/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c - $TUSB_DIR$/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c - - - $TUSB_DIR$/src/portable/raspberrypi/rp2040/dcd_rp2040.c - $TUSB_DIR$/src/portable/raspberrypi/rp2040/hcd_rp2040.c - - - $TUSB_DIR$/src/portable/renesas/rusb2/dcd_rusb2.c - $TUSB_DIR$/src/portable/renesas/rusb2/hcd_rusb2.c - - - $TUSB_DIR$/src/portable/sony/cxd56/dcd_cxd56.c - - - $TUSB_DIR$/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c - - - $TUSB_DIR$/src/portable/sunxi/dcd_sunxi_musb.c - - - $TUSB_DIR$/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c - - - $TUSB_DIR$/src/portable/valentyusb/eptri/dcd_eptri.c - - - $TUSB_DIR$/src/portable/wch/ch32v307/dcd_usbhs.c - - - $TUSB_DIR$/lib/SEGGER_RTT/RTT/SEGGER_RTT.c + + $TUSB_DIR$/src/class/audio/audio_device.c + + + $TUSB_DIR$/src/class/bth/bth_device.c + + + $TUSB_DIR$/src/class/cdc/cdc_device.c + $TUSB_DIR$/src/class/cdc/cdc_host.c + $TUSB_DIR$/src/class/cdc/cdc_rndis_host.c + + + $TUSB_DIR$/src/class/dfu/dfu_device.c + $TUSB_DIR$/src/class/dfu/dfu_rt_device.c + + + $TUSB_DIR$/src/class/hid/hid_device.c + $TUSB_DIR$/src/class/hid/hid_host.c + + + $TUSB_DIR$/src/class/midi/midi_device.c + + + $TUSB_DIR$/src/class/msc/msc_device.c + $TUSB_DIR$/src/class/msc/msc_host.c + + + $TUSB_DIR$/src/class/net/ecm_rndis_device.c + $TUSB_DIR$/src/class/net/ncm_device.c + + + $TUSB_DIR$/src/class/usbtmc/usbtmc_device.c + + + $TUSB_DIR$/src/class/vendor/vendor_device.c + $TUSB_DIR$/src/class/vendor/vendor_host.c + + + $TUSB_DIR$/src/class/video/video_device.c + + + $TUSB_DIR$/src/common/tusb_fifo.c + + + $TUSB_DIR$/src/device/usbd.c + $TUSB_DIR$/src/device/usbd_control.c + + + $TUSB_DIR$/src/host/hub.c + $TUSB_DIR$/src/host/usbh.c + + + $TUSB_DIR$/src/portable/analog/max3421/hcd_max3421.c + + + $TUSB_DIR$/src/portable/bridgetek/ft9xx/dcd_ft9xx.c + + + $TUSB_DIR$/src/portable/chipidea/ci_fs/dcd_ci_fs.c + + + $TUSB_DIR$/src/portable/chipidea/ci_hs/dcd_ci_hs.c + $TUSB_DIR$/src/portable/chipidea/ci_hs/hcd_ci_hs.c + + + $TUSB_DIR$/src/portable/dialog/da146xx/dcd_da146xx.c + + + $TUSB_DIR$/src/portable/ehci/ehci.c + + + $TUSB_DIR$/src/portable/mentor/musb/dcd_musb.c + $TUSB_DIR$/src/portable/mentor/musb/hcd_musb.c + + + $TUSB_DIR$/src/portable/microchip/pic/dcd_pic.c + + + $TUSB_DIR$/src/portable/microchip/pic32mz/dcd_pic32mz.c + + + $TUSB_DIR$/src/portable/microchip/samd/dcd_samd.c + + + $TUSB_DIR$/src/portable/microchip/samg/dcd_samg.c + + + $TUSB_DIR$/src/portable/microchip/samx7x/dcd_samx7x.c + + + $TUSB_DIR$/src/portable/mindmotion/mm32/dcd_mm32f327x_otg.c + + + $TUSB_DIR$/src/portable/nordic/nrf5x/dcd_nrf5x.c + + + $TUSB_DIR$/src/portable/nuvoton/nuc120/dcd_nuc120.c + + + $TUSB_DIR$/src/portable/nuvoton/nuc121/dcd_nuc121.c + + + $TUSB_DIR$/src/portable/nuvoton/nuc505/dcd_nuc505.c + + + $TUSB_DIR$/src/portable/nxp/khci/dcd_khci.c + $TUSB_DIR$/src/portable/nxp/khci/hcd_khci.c + + + $TUSB_DIR$/src/portable/nxp/lpc17_40/dcd_lpc17_40.c + $TUSB_DIR$/src/portable/nxp/lpc17_40/hcd_lpc17_40.c + + + $TUSB_DIR$/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c + + + $TUSB_DIR$/src/portable/ohci/ohci.c + + + $TUSB_DIR$/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c + $TUSB_DIR$/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c + + + $TUSB_DIR$/src/portable/raspberrypi/rp2040/dcd_rp2040.c + $TUSB_DIR$/src/portable/raspberrypi/rp2040/hcd_rp2040.c + $TUSB_DIR$/src/portable/raspberrypi/rp2040/rp2040_usb.c + + + $TUSB_DIR$/src/portable/renesas/rusb2/dcd_rusb2.c + $TUSB_DIR$/src/portable/renesas/rusb2/hcd_rusb2.c + $TUSB_DIR$/src/portable/renesas/rusb2/rusb2_common.c + + + $TUSB_DIR$/src/portable/sony/cxd56/dcd_cxd56.c + + + $TUSB_DIR$/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + + + $TUSB_DIR$/src/portable/st/typec/typec_stm32.c + + + $TUSB_DIR$/src/portable/sunxi/dcd_sunxi_musb.c + + + $TUSB_DIR$/src/portable/synopsys/dwc2/dcd_dwc2.c + + + $TUSB_DIR$/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c + + + $TUSB_DIR$/src/portable/valentyusb/eptri/dcd_eptri.c + + + $TUSB_DIR$/src/portable/wch/ch32v307/dcd_usbhs.c + + + $TUSB_DIR$/src/typec/usbc.c + + + $TUSB_DIR$/lib/SEGGER_RTT/RTT/SEGGER_RTT.c $TUSB_DIR$/lib/SEGGER_RTT/RTT/SEGGER_RTT_printf.c - $TUSB_DIR$/lib/SEGGER_RTT/Syscalls/SEGGER_RTT_Syscalls_IAR.c - + From 42eb4e0da0f5218d43ef81631bbbe2f369cc13fa Mon Sep 17 00:00:00 2001 From: Mengsk Date: Wed, 27 Sep 2023 11:46:52 +0200 Subject: [PATCH 56/71] Fix CI. --- tools/iar_gen.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/iar_gen.py b/tools/iar_gen.py index 646a581f4..264dd9a58 100644 --- a/tools/iar_gen.py +++ b/tools/iar_gen.py @@ -64,18 +64,18 @@ def ListPath(path, blacklist=[]): dir = os.path.dirname(file) if dir not in dirs: dirs.append(dir) - # Print .c groupped by dir + # Print .c grouped by dir for dir in dirs: print('') for file in files: if os.path.dirname(file) == dir: print(' $TUSB_DIR$/' + file.replace('../','').replace('\\','/')+'') print('') - + def List(): ListPath('src', [ 'template.c', 'dcd_synopsys.c', 'dcd_esp32sx.c' ]) ListPath('lib/SEGGER_RTT') - + if __name__ == "__main__": if (len(sys.argv) > 1): if (sys.argv[1] == 'l'): From 3a10b6a3d55e76020d0fdb6adb937f98df5638e1 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 Sep 2023 18:09:19 +0700 Subject: [PATCH 57/71] fix esp32 build --- hw/bsp/espressif/boards/family.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index 5226f7e61..e4c2c3414 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -186,7 +186,7 @@ static void max3421_intr_task(void* param) { while (1) { xSemaphoreTake(max3421_intr_sem, portMAX_DELAY); - hcd_int_handler_ext(BOARD_TUH_RHPORT, false); + tuh_int_handler(BOARD_TUH_RHPORT, false); } } From 10abece264e3d5a4551be750f3c726890598a40b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 27 Sep 2023 18:15:20 +0700 Subject: [PATCH 58/71] esp32 hid device work well --- hw/bsp/espressif/boards/family.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index e4c2c3414..4d2cab9e8 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -224,7 +224,7 @@ static void max3421_init(void) { // Interrupt pin max3421_intr_sem = xSemaphoreCreateBinary(); - xTaskCreate(max3421_intr_task, "max3421 intr", 2048, NULL, configMAX_PRIORITIES-1, NULL); + xTaskCreate(max3421_intr_task, "max3421 intr", 2048, NULL, configMAX_PRIORITIES-2, NULL); gpio_set_direction(MAX3421_INTR_PIN, GPIO_MODE_INPUT); gpio_set_intr_type(MAX3421_INTR_PIN, GPIO_INTR_NEGEDGE); From 277852afc1798f2acdb61917984e76b4bafa699e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 Sep 2023 10:56:38 +0700 Subject: [PATCH 59/71] fix esp32 msc example --- .../host/cdc_msc_hid_freertos/src/cdc_app.c | 8 +- .../host/cdc_msc_hid_freertos/src/hid_app.c | 4 + examples/host/cdc_msc_hid_freertos/src/main.c | 12 +- .../host/cdc_msc_hid_freertos/src/msc_app.c | 8 +- src/class/msc/msc_host.c | 265 ++++++++---------- src/class/msc/msc_host.h | 8 +- src/host/usbh.c | 22 +- 7 files changed, 151 insertions(+), 176 deletions(-) diff --git a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c index 943e534d8..91dcc2e1a 100644 --- a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c @@ -31,9 +31,7 @@ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ - -//------------- IMPLEMENTATION -------------// - +// helper size_t get_console_inputs(uint8_t *buf, size_t bufsize) { size_t count = 0; while (count < bufsize) { @@ -47,6 +45,10 @@ size_t get_console_inputs(uint8_t *buf, size_t bufsize) { return count; } +void cdc_app_init(void) { + // nothing to do +} + void cdc_app_task(void* param) { (void) param; diff --git a/examples/host/cdc_msc_hid_freertos/src/hid_app.c b/examples/host/cdc_msc_hid_freertos/src/hid_app.c index a2df3b909..9ea5c1be0 100644 --- a/examples/host/cdc_msc_hid_freertos/src/hid_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/hid_app.c @@ -48,6 +48,10 @@ static void process_kbd_report(hid_keyboard_report_t const *report); static void process_mouse_report(hid_mouse_report_t const *report); static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len); +void hid_app_init(void) { + // nothing to do +} + //--------------------------------------------------------------------+ // TinyUSB Callbacks //--------------------------------------------------------------------+ diff --git a/examples/host/cdc_msc_hid_freertos/src/main.c b/examples/host/cdc_msc_hid_freertos/src/main.c index 88e742ee2..b60be015b 100644 --- a/examples/host/cdc_msc_hid_freertos/src/main.c +++ b/examples/host/cdc_msc_hid_freertos/src/main.c @@ -82,10 +82,15 @@ StaticTask_t cdc_taskdef; TimerHandle_t blinky_tm; static void led_blinky_cb(TimerHandle_t xTimer); -static void usb_host_task(void* param); +extern void cdc_app_init(void); +extern void hid_app_init(void); +extern void msc_app_init(void); +static void usb_host_task(void* param); extern void cdc_app_task(void* param); + + /*------------- MAIN -------------*/ int main(void) { board_init(); @@ -131,6 +136,10 @@ static void usb_host_task(void *param) { board_init_after_tusb(); } + cdc_app_init(); + hid_app_init(); + msc_app_init(); + // RTOS forever loop while (1) { // put this thread to waiting state until there is new events @@ -154,7 +163,6 @@ void tuh_umount_cb(uint8_t dev_addr) { printf("A device with address %d is unmounted \r\n", dev_addr); } - //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ diff --git a/examples/host/cdc_msc_hid_freertos/src/msc_app.c b/examples/host/cdc_msc_hid_freertos/src/msc_app.c index a8d6fbfaa..ee02ba917 100644 --- a/examples/host/cdc_msc_hid_freertos/src/msc_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/msc_app.c @@ -25,10 +25,12 @@ #include "tusb.h" -#if CFG_TUH_MSC - static scsi_inquiry_resp_t inquiry_resp; +void msc_app_init(void) { + // nothing to do +} + bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_data) { msc_cbw_t const *cbw = cb_data->cbw; msc_csw_t const *csw = cb_data->csw; @@ -63,5 +65,3 @@ void tuh_msc_umount_cb(uint8_t dev_addr) { (void) dev_addr; printf("A MassStorage device is unmounted\r\n"); } - -#endif diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index da264142c..39f2d9f1c 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -43,16 +43,14 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -enum -{ +enum { MSC_STAGE_IDLE = 0, MSC_STAGE_CMD, MSC_STAGE_DATA, MSC_STAGE_STATUS, }; -typedef struct -{ +typedef struct { uint8_t itf_num; uint8_t ep_in; uint8_t ep_out; @@ -69,13 +67,13 @@ typedef struct //------------- SCSI -------------// uint8_t stage; - void* buffer; + void* buffer; tuh_msc_complete_cb_t complete_cb; uintptr_t complete_arg; CFG_TUH_MEM_ALIGN msc_cbw_t cbw; CFG_TUH_MEM_ALIGN msc_csw_t csw; -}msch_interface_t; +} msch_interface_t; CFG_TUH_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUH_DEVICE_MAX]; @@ -86,40 +84,34 @@ static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)]; // FIXME potential nul reference TU_ATTR_ALWAYS_INLINE -static inline msch_interface_t* get_itf(uint8_t dev_addr) -{ - return &_msch_itf[dev_addr-1]; +static inline msch_interface_t* get_itf(uint8_t dev_addr) { + return &_msch_itf[dev_addr - 1]; } //--------------------------------------------------------------------+ // PUBLIC API //--------------------------------------------------------------------+ -uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) -{ +uint8_t tuh_msc_get_maxlun(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); return p_msc->max_lun; } -uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun) -{ +uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun) { msch_interface_t* p_msc = get_itf(dev_addr); return p_msc->capacity[lun].block_count; } -uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun) -{ +uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun) { msch_interface_t* p_msc = get_itf(dev_addr); return p_msc->capacity[lun].block_size; } -bool tuh_msc_mounted(uint8_t dev_addr) -{ +bool tuh_msc_mounted(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); return p_msc->mounted; } -bool tuh_msc_ready(uint8_t dev_addr) -{ +bool tuh_msc_ready(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in) && !usbh_edpt_busy(dev_addr, p_msc->ep_out); } @@ -127,20 +119,20 @@ bool tuh_msc_ready(uint8_t dev_addr) //--------------------------------------------------------------------+ // PUBLIC API: SCSI COMMAND //--------------------------------------------------------------------+ -static inline void cbw_init(msc_cbw_t *cbw, uint8_t lun) -{ +static inline void cbw_init(msc_cbw_t* cbw, uint8_t lun) { tu_memclr(cbw, sizeof(msc_cbw_t)); cbw->signature = MSC_CBW_SIGNATURE; cbw->tag = 0x54555342; // TUSB cbw->lun = lun; } -bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msch_interface_t* p_msc = get_itf(dev_addr); +bool tuh_msc_scsi_command(uint8_t daddr, msc_cbw_t const* cbw, void* data, + tuh_msc_complete_cb_t complete_cb, uintptr_t arg) { + msch_interface_t* p_msc = get_itf(daddr); TU_VERIFY(p_msc->configured); - // TODO claim endpoint + // claim endpoint + TU_VERIFY(usbh_edpt_claim(daddr, p_msc->ep_out)); p_msc->cbw = *cbw; p_msc->stage = MSC_STAGE_CMD; @@ -148,15 +140,18 @@ bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tu p_msc->complete_cb = complete_cb; p_msc->complete_arg = arg; - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t))); + if (!usbh_edpt_xfer(daddr, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t))) { + usbh_edpt_release(daddr, p_msc->ep_out); + return false; + } return true; } -bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ - msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->configured); +bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, + tuh_msc_complete_cb_t complete_cb, uintptr_t arg) { + msch_interface_t* p_msc = get_itf(dev_addr); + TU_VERIFY(p_msc->configured); msc_cbw_t cbw; cbw_init(&cbw, lun); @@ -169,8 +164,8 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg); } -bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ +bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, + tuh_msc_complete_cb_t complete_cb, uintptr_t arg) { msch_interface_t* p_msc = get_itf(dev_addr); TU_VERIFY(p_msc->mounted); @@ -181,18 +176,16 @@ bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* respons cbw.dir = TUSB_DIR_IN_MASK; cbw.cmd_len = sizeof(scsi_inquiry_t); - scsi_inquiry_t const cmd_inquiry = - { - .cmd_code = SCSI_CMD_INQUIRY, - .alloc_length = sizeof(scsi_inquiry_resp_t) + scsi_inquiry_t const cmd_inquiry = { + .cmd_code = SCSI_CMD_INQUIRY, + .alloc_length = sizeof(scsi_inquiry_resp_t) }; memcpy(cbw.command, &cmd_inquiry, cbw.cmd_len); return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg); } -bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ +bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) { msch_interface_t* p_msc = get_itf(dev_addr); TU_VERIFY(p_msc->configured); @@ -200,16 +193,16 @@ bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_ cbw_init(&cbw, lun); cbw.total_bytes = 0; - cbw.dir = TUSB_DIR_OUT; - cbw.cmd_len = sizeof(scsi_test_unit_ready_t); - cbw.command[0] = SCSI_CMD_TEST_UNIT_READY; - cbw.command[1] = lun; // according to wiki TODO need verification + cbw.dir = TUSB_DIR_OUT; + cbw.cmd_len = sizeof(scsi_test_unit_ready_t); + cbw.command[0] = SCSI_CMD_TEST_UNIT_READY; + cbw.command[1] = lun; // according to wiki TODO need verification return tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb, arg); } -bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ +bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void* response, + tuh_msc_complete_cb_t complete_cb, uintptr_t arg) { msc_cbw_t cbw; cbw_init(&cbw, lun); @@ -217,73 +210,64 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *response, tuh_ms cbw.dir = TUSB_DIR_IN_MASK; cbw.cmd_len = sizeof(scsi_request_sense_t); - scsi_request_sense_t const cmd_request_sense = - { - .cmd_code = SCSI_CMD_REQUEST_SENSE, - .alloc_length = 18 + scsi_request_sense_t const cmd_request_sense = { + .cmd_code = SCSI_CMD_REQUEST_SENSE, + .alloc_length = 18 }; - memcpy(cbw.command, &cmd_request_sense, cbw.cmd_len); return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb, arg); } -bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ +bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void* buffer, uint32_t lba, uint16_t block_count, + tuh_msc_complete_cb_t complete_cb, uintptr_t arg) { msch_interface_t* p_msc = get_itf(dev_addr); TU_VERIFY(p_msc->mounted); msc_cbw_t cbw; cbw_init(&cbw, lun); - cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; - cbw.dir = TUSB_DIR_IN_MASK; - cbw.cmd_len = sizeof(scsi_read10_t); + cbw.total_bytes = block_count * p_msc->capacity[lun].block_size; + cbw.dir = TUSB_DIR_IN_MASK; + cbw.cmd_len = sizeof(scsi_read10_t); - scsi_read10_t const cmd_read10 = - { - .cmd_code = SCSI_CMD_READ_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) + scsi_read10_t const cmd_read10 = { + .cmd_code = SCSI_CMD_READ_10, + .lba = tu_htonl(lba), + .block_count = tu_htons(block_count) }; - memcpy(cbw.command, &cmd_read10, cbw.cmd_len); return tuh_msc_scsi_command(dev_addr, &cbw, buffer, complete_cb, arg); } -bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg) -{ +bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const* buffer, uint32_t lba, uint16_t block_count, + tuh_msc_complete_cb_t complete_cb, uintptr_t arg) { msch_interface_t* p_msc = get_itf(dev_addr); TU_VERIFY(p_msc->mounted); msc_cbw_t cbw; cbw_init(&cbw, lun); - cbw.total_bytes = block_count*p_msc->capacity[lun].block_size; + cbw.total_bytes = block_count * p_msc->capacity[lun].block_size; cbw.dir = TUSB_DIR_OUT; cbw.cmd_len = sizeof(scsi_write10_t); - scsi_write10_t const cmd_write10 = - { - .cmd_code = SCSI_CMD_WRITE_10, - .lba = tu_htonl(lba), - .block_count = tu_htons(block_count) + scsi_write10_t const cmd_write10 = { + .cmd_code = SCSI_CMD_WRITE_10, + .lba = tu_htonl(lba), + .block_count = tu_htons(block_count) }; - memcpy(cbw.command, &cmd_write10, cbw.cmd_len); - return tuh_msc_scsi_command(dev_addr, &cbw, (void*)(uintptr_t) buffer, complete_cb, arg); + return tuh_msc_scsi_command(dev_addr, &cbw, (void*) (uintptr_t) buffer, complete_cb, arg); } #if 0 // MSC interface Reset (not used now) -bool tuh_msc_reset(uint8_t dev_addr) -{ - tusb_control_request_t const new_request = - { - .bmRequestType_bit = - { +bool tuh_msc_reset(uint8_t dev_addr) { + tusb_control_request_t const new_request = { + .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT @@ -300,79 +284,71 @@ bool tuh_msc_reset(uint8_t dev_addr) //--------------------------------------------------------------------+ // CLASS-USBH API //--------------------------------------------------------------------+ -void msch_init(void) -{ +void msch_init(void) { tu_memclr(_msch_itf, sizeof(_msch_itf)); } -void msch_close(uint8_t dev_addr) -{ - TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); +void msch_close(uint8_t dev_addr) { + TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX,); msch_interface_t* p_msc = get_itf(dev_addr); - TU_VERIFY(p_msc->configured, ); + TU_VERIFY(p_msc->configured,); TU_LOG_DRV(" MSCh close addr = %d\r\n", dev_addr); // invoke Application Callback if (p_msc->mounted) { - if(tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); + if (tuh_msc_umount_cb) tuh_msc_umount_cb(dev_addr); } tu_memclr(p_msc, sizeof(msch_interface_t)); } -bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) -{ +bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { msch_interface_t* p_msc = get_itf(dev_addr); msc_cbw_t const * cbw = &p_msc->cbw; msc_csw_t * csw = &p_msc->csw; - switch (p_msc->stage) - { + switch (p_msc->stage) { case MSC_STAGE_CMD: // Must be Command Block - TU_ASSERT(ep_addr == p_msc->ep_out && event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t)); + TU_ASSERT(ep_addr == p_msc->ep_out && event == XFER_RESULT_SUCCESS && xferred_bytes == sizeof(msc_cbw_t)); - if ( cbw->total_bytes && p_msc->buffer ) - { + if (cbw->total_bytes && p_msc->buffer) { // Data stage if any p_msc->stage = MSC_STAGE_DATA; - uint8_t const ep_data = (cbw->dir & TUSB_DIR_IN_MASK) ? p_msc->ep_in : p_msc->ep_out; TU_ASSERT(usbh_edpt_xfer(dev_addr, ep_data, p_msc->buffer, (uint16_t) cbw->total_bytes)); - }else - { + } else { // Status stage p_msc->stage = MSC_STAGE_STATUS; TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, (uint16_t) sizeof(msc_csw_t))); } - break; + break; case MSC_STAGE_DATA: // Status stage p_msc->stage = MSC_STAGE_STATUS; TU_ASSERT(usbh_edpt_xfer(dev_addr, p_msc->ep_in, (uint8_t*) &p_msc->csw, (uint16_t) sizeof(msc_csw_t))); - break; + break; case MSC_STAGE_STATUS: // SCSI op is complete p_msc->stage = MSC_STAGE_IDLE; - if (p_msc->complete_cb) - { - tuh_msc_complete_data_t const cb_data = - { - .cbw = cbw, - .csw = csw, - .scsi_data = p_msc->buffer, - .user_arg = p_msc->complete_arg + if (p_msc->complete_cb) { + tuh_msc_complete_data_t const cb_data = { + .cbw = cbw, + .csw = csw, + .scsi_data = p_msc->buffer, + .user_arg = p_msc->complete_arg }; p_msc->complete_cb(dev_addr, &cb_data); } - break; + break; - // unknown state - default: break; + // unknown state + default: + break; } return true; @@ -381,39 +357,35 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32 //--------------------------------------------------------------------+ // MSC Enumeration //--------------------------------------------------------------------+ - -static void config_get_maxlun_complete (tuh_xfer_t* xfer); -static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data); +static void config_get_maxlun_complete(tuh_xfer_t* xfer); +static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data); static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data); static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data); -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) -{ +bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const* desc_itf, uint16_t max_len) { (void) rhport; TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && - MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); + MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); // msc driver length is fixed - uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); + uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + + desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); TU_ASSERT(drv_len <= max_len); msch_interface_t* p_msc = get_itf(dev_addr); - tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf); + tusb_desc_endpoint_t const* ep_desc = (tusb_desc_endpoint_t const*) tu_desc_next(desc_itf); - for(uint32_t i=0; i<2; i++) - { + for (uint32_t i = 0; i < 2; i++) { TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); TU_ASSERT(tuh_edpt_open(dev_addr, ep_desc)); - if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ) - { + if (TUSB_DIR_IN == tu_edpt_dir(ep_desc->bEndpointAddress)) { p_msc->ep_in = ep_desc->bEndpointAddress; - }else - { + } else { p_msc->ep_out = ep_desc->bEndpointAddress; } - ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(ep_desc); + ep_desc = (tusb_desc_endpoint_t const*) tu_desc_next(ep_desc); } p_msc->itf_num = desc_itf->bInterfaceNumber; @@ -430,32 +402,31 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) { //------------- Get Max Lun -------------// TU_LOG_DRV("MSC Get Max Lun\r\n"); tusb_control_request_t const request = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_IN - }, - .bRequest = MSC_REQ_GET_MAX_LUN, - .wValue = 0, - .wIndex = itf_num, - .wLength = 1 + .bmRequestType_bit = { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_IN + }, + .bRequest = MSC_REQ_GET_MAX_LUN, + .wValue = 0, + .wIndex = itf_num, + .wLength = 1 }; tuh_xfer_t xfer = { - .daddr = dev_addr, - .ep_addr = 0, - .setup = &request, - .buffer = _msch_buffer, - .complete_cb = config_get_maxlun_complete, - .user_data = 0 + .daddr = dev_addr, + .ep_addr = 0, + .setup = &request, + .buffer = _msch_buffer, + .complete_cb = config_get_maxlun_complete, + .user_data = 0 }; TU_ASSERT(tuh_control_xfer(&xfer)); return true; } -static void config_get_maxlun_complete (tuh_xfer_t* xfer) -{ +static void config_get_maxlun_complete(tuh_xfer_t* xfer) { uint8_t const daddr = xfer->daddr; msch_interface_t* p_msc = get_itf(daddr); @@ -471,18 +442,16 @@ static void config_get_maxlun_complete (tuh_xfer_t* xfer) tuh_msc_test_unit_ready(daddr, lun, config_test_unit_ready_complete, 0); } -static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) -{ +static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data) { msc_cbw_t const* cbw = cb_data->cbw; msc_csw_t const* csw = cb_data->csw; - if (csw->status == 0) - { + if (csw->status == 0) { // Unit is ready, read its capacity TU_LOG_DRV("SCSI Read Capacity\r\n"); - tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer), config_read_capacity_complete, 0); - }else - { + tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer), + config_read_capacity_complete, 0); + } else { // Note: During enumeration, some device fails Test Unit Ready and require a few retries // with Request Sense to start working !! // TODO limit number of retries @@ -493,8 +462,7 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_d return true; } -static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) -{ +static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data) { msc_cbw_t const* cbw = cb_data->cbw; msc_csw_t const* csw = cb_data->csw; @@ -503,8 +471,7 @@ static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_dat return true; } -static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) -{ +static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data) { msc_cbw_t const* cbw = cb_data->cbw; msc_csw_t const* csw = cb_data->csw; diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index 6c0e5c9dd..9ca1b4703 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_MSC_HOST_H_ -#define _TUSB_MSC_HOST_H_ +#ifndef TUSB_MSC_HOST_H_ +#define TUSB_MSC_HOST_H_ #include "msc.h" @@ -73,7 +73,7 @@ uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun); // Perform a full SCSI command (cbw, data, csw) in non-blocking manner. // Complete callback is invoked when SCSI op is complete. // return true if success, false if there is already pending operation. -bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); +bool tuh_msc_scsi_command(uint8_t daddr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); // Perform SCSI Inquiry command // Complete callback is invoked when SCSI op is complete. @@ -123,4 +123,4 @@ bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, ui } #endif -#endif /* _TUSB_MSC_HOST_H_ */ +#endif diff --git a/src/host/usbh.c b/src/host/usbh.c index e332f35cc..8d75c9726 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -817,6 +817,7 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) } // Submit an transfer +// TODO call usbh_edpt_release if failed bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { @@ -1713,19 +1714,16 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur return true; } -void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) -{ +void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) { usbh_device_t* dev = get_device(dev_addr); - for(itf_num++; itf_num < CFG_TUH_INTERFACE_MAX; itf_num++) - { + for(itf_num++; itf_num < CFG_TUH_INTERFACE_MAX; itf_num++) { // continue with next valid interface // IAD binding interface such as CDCs should return itf_num + 1 when complete // with usbh_driver_set_config_complete() uint8_t const drv_id = dev->itf2drv[itf_num]; usbh_class_driver_t const * driver = get_driver(drv_id); - if (driver) - { + if (driver) { TU_LOG_USBH("%s set config: itf = %u\r\n", driver->name, itf_num); driver->set_config(dev_addr, itf_num); break; @@ -1733,23 +1731,19 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) } // all interface are configured - if (itf_num == CFG_TUH_INTERFACE_MAX) - { + if (itf_num == CFG_TUH_INTERFACE_MAX) { enum_full_complete(); - if (is_hub_addr(dev_addr)) - { + if (is_hub_addr(dev_addr)) { TU_LOG(CFG_TUH_LOG_LEVEL, "HUB address = %u is mounted\r\n", dev_addr); - }else - { + }else { // Invoke callback if available if (tuh_mount_cb) tuh_mount_cb(dev_addr); } } } -static void enum_full_complete(void) -{ +static void enum_full_complete(void) { // mark enumeration as complete _dev0.enumerating = 0; From 7dc1a66f917408992cf672009a307f7200a3fd32 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 Sep 2023 11:12:22 +0700 Subject: [PATCH 60/71] esp32 cdc host with max3421 work well --- .../host/cdc_msc_hid_freertos/src/cdc_app.c | 44 ++++++++++++++++--- examples/host/cdc_msc_hid_freertos/src/main.c | 16 ++----- hw/bsp/espressif/boards/family.c | 20 +++++++-- 3 files changed, 58 insertions(+), 22 deletions(-) diff --git a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c index 91dcc2e1a..6ff513be1 100644 --- a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c @@ -27,9 +27,43 @@ #include "tusb.h" #include "bsp/board_api.h" +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +// ESP-IDF need "freertos/" prefix in include path. +// CFG_TUSB_OS_INC_PATH should be defined accordingly. + #include "freertos/FreeRTOS.h" + #include "freertos/semphr.h" + #include "freertos/queue.h" + #include "freertos/task.h" + #include "freertos/timers.h" + + #define CDC_STACK_SZIE 2048 +#else + #include "FreeRTOS.h" + #include "semphr.h" + #include "queue.h" + #include "task.h" + #include "timers.h" + + #define CDC_STACK_SZIE (3*configMINIMAL_STACK_SIZE/2) +#endif + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ +#if configSUPPORT_STATIC_ALLOCATION +StackType_t cdc_stack[CDC_STACK_SZIE]; +StaticTask_t cdc_taskdef; +#endif + +static void cdc_app_task(void* param); + +void cdc_app_init(void) { + #if configSUPPORT_STATIC_ALLOCATION + xTaskCreateStatic(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); + #else + xTaskCreate(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL); + #endif +} // helper size_t get_console_inputs(uint8_t *buf, size_t bufsize) { @@ -45,11 +79,7 @@ size_t get_console_inputs(uint8_t *buf, size_t bufsize) { return count; } -void cdc_app_init(void) { - // nothing to do -} - -void cdc_app_task(void* param) { +static void cdc_app_task(void* param) { (void) param; uint8_t buf[64 + 1]; // +1 for extra null character @@ -74,6 +104,10 @@ void cdc_app_task(void* param) { } } +//--------------------------------------------------------------------+ +// TinyUSB Callbacks +//--------------------------------------------------------------------+ + // Invoked when received new data void tuh_cdc_rx_cb(uint8_t idx) { uint8_t buf[64 + 1]; // +1 for extra null character diff --git a/examples/host/cdc_msc_hid_freertos/src/main.c b/examples/host/cdc_msc_hid_freertos/src/main.c index b60be015b..691ff3e29 100644 --- a/examples/host/cdc_msc_hid_freertos/src/main.c +++ b/examples/host/cdc_msc_hid_freertos/src/main.c @@ -40,7 +40,6 @@ #include "freertos/timers.h" #define USBH_STACK_SIZE 4096 - #define CDC_STACK_SZIE 2048 #else #include "FreeRTOS.h" #include "semphr.h" @@ -50,7 +49,6 @@ // Increase stack size when debug log is enabled #define USBH_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) - #define CDC_STACK_SZIE (3*configMINIMAL_STACK_SIZE/2) #endif @@ -74,38 +72,30 @@ StaticTimer_t blinky_tmdef; StackType_t usb_host_stack[USBH_STACK_SIZE]; StaticTask_t usb_host_taskdef; - -StackType_t cdc_stack[CDC_STACK_SZIE]; -StaticTask_t cdc_taskdef; #endif TimerHandle_t blinky_tm; static void led_blinky_cb(TimerHandle_t xTimer); +static void usb_host_task(void* param); + extern void cdc_app_init(void); extern void hid_app_init(void); extern void msc_app_init(void); -static void usb_host_task(void* param); -extern void cdc_app_task(void* param); - - - /*------------- MAIN -------------*/ int main(void) { board_init(); printf("TinyUSB Host CDC MSC HID with FreeRTOS Example\r\n"); - // Create soft timer for blinky, task for tinyusb stack and CDC + // Create soft timer for blinky, task for tinyusb stack #if configSUPPORT_STATIC_ALLOCATION blinky_tm = xTimerCreateStatic(NULL, pdMS_TO_TICKS(BLINK_MOUNTED), true, NULL, led_blinky_cb, &blinky_tmdef); xTaskCreateStatic(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_host_stack, &usb_host_taskdef); - xTaskCreateStatic(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, cdc_stack, &cdc_taskdef); #else blinky_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb); xTaskCreate(usb_host_task, "usbd", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, NULL); - xTaskCreate(cdc_app_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES-2, NULL); #endif xTimerStart(blinky_tm, 0); diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index 4d2cab9e8..e45765fd1 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -41,6 +41,8 @@ #include "driver/periph_ctrl.h" #endif +#define UART_ID UART_NUM_0 + #ifdef NEOPIXEL_PIN #include "led_strip.h" static led_strip_t *strip; @@ -59,6 +61,17 @@ static void configure_pins(usb_hal_context_t *usb); // Initialize on-board peripherals : led, button, uart and USB void board_init(void) { + // uart init + uart_config_t uart_config = { + .baud_rate = 115200, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE + }; + uart_driver_install(UART_ID, 1024, 0, 0, NULL, 0); + uart_param_config(UART_ID, &uart_config); + #ifdef NEOPIXEL_PIN #ifdef NEOPIXEL_POWER_PIN gpio_reset_pin(NEOPIXEL_POWER_PIN); @@ -144,7 +157,7 @@ uint32_t board_button_read(void) { // Get characters from UART int board_uart_read(uint8_t *buf, int len) { - return uart_read_bytes(UART_NUM_0, buf, len, 0); + return uart_read_bytes(UART_ID, buf, len, 0); } // Send characters to UART @@ -155,9 +168,8 @@ int board_uart_write(void const *buf, int len) { } int board_getchar(void) { -// char c; -// return (uart_read_bytes(UART_NUM_0, &c, 1, 0) > 0) ? (int) c : (-1); - return -1; + char c; + return (uart_read_bytes(UART_ID, &c, 1, 0) > 0) ? (int) c : (-1); } //--------------------------------------------------------------------+ From 6b8933cfe838b369c58d4fc9ced8aa5c9382a6d6 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 28 Sep 2023 12:55:59 +0700 Subject: [PATCH 61/71] fix build with new freertos host example --- examples/device/cdc_msc_freertos/Makefile | 2 - examples/host/bare_api/Makefile | 10 - examples/host/cdc_msc_hid/Makefile | 10 - examples/host/cdc_msc_hid_freertos/Makefile | 18 +- .../src/FreeRTOSConfig/FreeRTOSConfig.h | 215 ++++++++++++++++++ examples/host/hid_controller/Makefile | 10 - examples/host/msc_file_explorer/Makefile | 10 - hw/bsp/lpc17/family.mk | 4 +- src/portable/analog/max3421/hcd_max3421.c | 4 +- src/tinyusb.mk | 7 + 10 files changed, 237 insertions(+), 53 deletions(-) create mode 100644 examples/host/cdc_msc_hid_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h diff --git a/examples/device/cdc_msc_freertos/Makefile b/examples/device/cdc_msc_freertos/Makefile index 3ac62a79c..84c833fb5 100644 --- a/examples/device/cdc_msc_freertos/Makefile +++ b/examples/device/cdc_msc_freertos/Makefile @@ -1,5 +1,3 @@ -DEPS_SUBMODULES += lib/FreeRTOS-Kernel - include ../../make.mk FREERTOS_SRC = lib/FreeRTOS-Kernel diff --git a/examples/host/bare_api/Makefile b/examples/host/bare_api/Makefile index 058307c40..161f8c774 100644 --- a/examples/host/bare_api/Makefile +++ b/examples/host/bare_api/Makefile @@ -10,14 +10,4 @@ EXAMPLE_SOURCE += \ SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -# TinyUSB Host Stack source -SRC_C += \ - src/class/cdc/cdc_host.c \ - src/class/hid/hid_host.c \ - src/class/msc/msc_host.c \ - src/host/hub.c \ - src/host/usbh.c \ - src/portable/ohci/ohci.c \ - src/portable/nxp/lpc17_40/hcd_lpc17_40.c - include ../../rules.mk diff --git a/examples/host/cdc_msc_hid/Makefile b/examples/host/cdc_msc_hid/Makefile index 7c16b39d3..15b8a5b31 100644 --- a/examples/host/cdc_msc_hid/Makefile +++ b/examples/host/cdc_msc_hid/Makefile @@ -13,14 +13,4 @@ EXAMPLE_SOURCE = \ SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -# TinyUSB Host Stack source -SRC_C += \ - src/class/cdc/cdc_host.c \ - src/class/hid/hid_host.c \ - src/class/msc/msc_host.c \ - src/host/hub.c \ - src/host/usbh.c \ - src/portable/ohci/ohci.c \ - src/portable/nxp/lpc17_40/hcd_lpc17_40.c - include ../../rules.mk diff --git a/examples/host/cdc_msc_hid_freertos/Makefile b/examples/host/cdc_msc_hid_freertos/Makefile index 67bb6da55..a9670b4f2 100644 --- a/examples/host/cdc_msc_hid_freertos/Makefile +++ b/examples/host/cdc_msc_hid_freertos/Makefile @@ -5,6 +5,7 @@ FREERTOS_PORTABLE_PATH= $(FREERTOS_SRC)/portable/$(if $(USE_IAR),IAR,GCC) INC += \ src \ + src/FreeRTOSConfig \ $(TOP)/hw \ $(TOP)/$(FREERTOS_SRC)/include \ $(TOP)/$(FREERTOS_PORTABLE_SRC) \ @@ -19,14 +20,15 @@ EXAMPLE_SOURCE = \ SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -# TinyUSB Host Stack source +# FreeRTOS source, all files in port folder SRC_C += \ - src/class/cdc/cdc_host.c \ - src/class/hid/hid_host.c \ - src/class/msc/msc_host.c \ - src/host/hub.c \ - src/host/usbh.c \ - src/portable/ohci/ohci.c \ - src/portable/nxp/lpc17_40/hcd_lpc17_40.c + $(FREERTOS_SRC)/list.c \ + $(FREERTOS_SRC)/queue.c \ + $(FREERTOS_SRC)/tasks.c \ + $(FREERTOS_SRC)/timers.c \ + $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.c)) + +SRC_S += \ + $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.s)) include ../../rules.mk diff --git a/examples/host/cdc_msc_hid_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/host/cdc_msc_hid_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..a1fc8bb09 --- /dev/null +++ b/examples/host/cdc_msc_hid_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,215 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * 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. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + +// Include MCU header +#include "bsp/board_mcu.h" + +#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 + #error "ESP32-Sx should use IDF's FreeRTOSConfig.h" +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + +// TODO fix later +// FIXME cause redundant-decls warnings +#if CFG_TUSB_MCU == OPT_MCU_MM32F327X + extern u32 SystemCoreClock; +#else + extern uint32_t SystemCoreClock; +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE ( 1024 ) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 0 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* Define to trap errors during development. */ +// Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7 +#if defined(__ARM_ARCH_7M__) || defined (__ARM_ARCH_7EM__) + #define configASSERT(_exp) \ + do {\ + if ( !(_exp) ) { \ + volatile uint32_t* ARM_CM_DHCSR = ((volatile uint32_t*) 0xE000EDF0UL); /* Cortex M CoreDebug->DHCSR */ \ + if ( (*ARM_CM_DHCSR) & 1UL ) { /* Only halt mcu if debugger is attached */ \ + taskDISABLE_INTERRUPTS(); \ + __asm("BKPT #0\n"); \ + }\ + }\ + } while(0) +#else + #define configASSERT( x ) +#endif + +#ifdef __RX__ +/* Renesas RX series */ +#define vSoftwareInterruptISR INT_Excep_ICU_SWINT +#define vTickISR INT_Excep_CMT0_CMI0 +#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2) +#define configKERNEL_INTERRUPT_PRIORITY 1 +#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4 + +#else + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ +#if defined(__NVIC_PRIO_BITS) + // For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h + #define configPRIO_BITS __NVIC_PRIO_BITS + +#elif defined(__ECLIC_INTCTLBITS) + // RISC-V Bumblebee core from nuclei + #define configPRIO_BITS __ECLIC_INTCTLBITS + +#elif defined(__IASMARM__) + // FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS. + // Therefore we will hard coded it to minimum value of 2 to get pass ci build. + // IAR user must update this to correct value of the target MCU + #message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU" + #define configPRIO_BITS 2 + +#else + #error "FreeRTOS configPRIO_BITS to be defined" +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< Date: Thu, 28 Sep 2023 16:15:31 +0700 Subject: [PATCH 62/71] improve esp32 ci, build esp32 with -DDMAX3421_HOST=1 for max3421 testing revert change in hcd.h --- .github/workflows/build_esp.yml | 21 +------ .../boards/espressif_s3_devkitm/board.h | 8 +++ src/host/hcd.h | 3 - tools/build_esp32.py | 61 +++++++++++-------- 4 files changed, 44 insertions(+), 49 deletions(-) diff --git a/.github/workflows/build_esp.yml b/.github/workflows/build_esp.yml index 29585cb36..897616f09 100644 --- a/.github/workflows/build_esp.yml +++ b/.github/workflows/build_esp.yml @@ -29,12 +29,10 @@ jobs: fail-fast: false matrix: board: - # Alphabetical order # ESP32-S2 - - 'espressif_saola_1' + - 'espressif_kaluga_1' # ESP32-S3 - #- 'espressif_s3_devkitm' - # S3 compile error with "dangerous relocation: call8: call target out of range: memcpy" + - 'espressif_s3_devkitm' steps: - name: Setup Python @@ -48,20 +46,5 @@ jobs: - name: Checkout TinyUSB uses: actions/checkout@v3 - - name: Checkout hathach/linkermap - uses: actions/checkout@v3 - with: - repository: hathach/linkermap - path: linkermap - - name: Build run: docker run --rm -v $PWD:/project -w /project espressif/idf:latest python3 tools/build_esp32.py ${{ matrix.board }} - - - name: Linker Map - run: | - pip install linkermap/ - # find -quit to only print linkermap of 1 board per example - for ex in `ls -d examples/device/*/` - do - find ${ex} -maxdepth 3 -name *.map -print -quit | xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"' - done diff --git a/hw/bsp/espressif/boards/espressif_s3_devkitm/board.h b/hw/bsp/espressif/boards/espressif_s3_devkitm/board.h index fe33b5c43..4b4151e72 100644 --- a/hw/bsp/espressif/boards/espressif_s3_devkitm/board.h +++ b/hw/bsp/espressif/boards/espressif_s3_devkitm/board.h @@ -36,6 +36,14 @@ #define BUTTON_PIN 0 #define BUTTON_STATE_ACTIVE 0 +// SPI for USB host shield +#define MAX3421_SPI_HOST SPI2_HOST +#define MAX3421_SCK_PIN 36 +#define MAX3421_MOSI_PIN 35 +#define MAX3421_MISO_PIN 37 +#define MAX3421_CS_PIN 15 +#define MAX3421_INTR_PIN 14 + #ifdef __cplusplus } #endif diff --git a/src/host/hcd.h b/src/host/hcd.h index edffb34cb..2bde289df 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -133,9 +133,6 @@ bool hcd_init(uint8_t rhport); // Interrupt Handler void hcd_int_handler(uint8_t rhport, bool in_isr); -// Interrupt Hanndler (extended version) -void hcd_int_handler_ext(uint8_t rhport, bool in_isr); - // Enable USB interrupt void hcd_int_enable (uint8_t rhport); diff --git a/tools/build_esp32.py b/tools/build_esp32.py index 00783bf58..1f73d3b22 100644 --- a/tools/build_esp32.py +++ b/tools/build_esp32.py @@ -17,8 +17,8 @@ exit_status = 0 total_time = time.monotonic() -build_format = '| {:23} | {:30} | {:18} | {:7} | {:6} | {:6} |' -build_separator = '-' * 100 +build_format = '| {:30} | {:30} | {:18} | {:7} | {:6} | {:6} |' +build_separator = '-' * 107 def filter_with_input(mylist): if len(sys.argv) > 1: @@ -26,12 +26,9 @@ def filter_with_input(mylist): if len(input_args) > 0: mylist[:] = input_args + # Build all examples if not specified -all_examples = [] -for entry in os.scandir("examples/device"): - # Only includes example with CMakeLists.txt for esp32s, and skip board_test to speed up ci - if entry.is_dir() and os.path.exists(entry.path + "/sdkconfig.defaults") and entry.name != 'board_test': - all_examples.append(entry.name) +all_examples = [entry.replace('examples/', '') for entry in glob.glob("examples/*/*_freertos")] filter_with_input(all_examples) all_examples.sort() @@ -46,32 +43,41 @@ all_boards.sort() def build_board(example, board): global success_count, fail_count, skip_count, exit_status start_time = time.monotonic() + + # Check if board is skipped + build_dir = f"cmake-build/cmake-build-{board}/{example}" + + # Generate and build + r = subprocess.run(f"cmake examples/{example} -B {build_dir} -G \"Ninja\" -DBOARD={board} -DMAX3421_HOST=1", + shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + if r.returncode == 0: + r = subprocess.run(f"cmake --build {build_dir}", shell=True, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + build_duration = time.monotonic() - start_time flash_size = "-" sram_size = "-" - # Check if board is skipped - if build_utils.skip_example(example, board): - success = SKIPPED - skip_count += 1 - print(build_format.format(example, board, success, '-', flash_size, sram_size)) + if r.returncode == 0: + success = SUCCEEDED + success_count += 1 + #(flash_size, sram_size) = build_size(example, board) else: - subprocess.run("make -C examples/device/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - build_result = subprocess.run("make -j -C examples/device/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + exit_status = r.returncode + success = FAILED + fail_count += 1 - if build_result.returncode == 0: - success = SUCCEEDED - success_count += 1 - (flash_size, sram_size) = build_size(example, board) - else: - exit_status = build_result.returncode - success = FAILED - fail_count += 1 + title = build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size) + if os.getenv('CI'): + # always print build output if in CI + print(f"::group::{title}") + print(r.stdout.decode("utf-8")) + print(f"::endgroup::") + else: + # print build output if failed + print(title) + if r.returncode != 0: + print(r.stdout.decode("utf-8")) - build_duration = time.monotonic() - start_time - print(build_format.format(example, board, success, "{:.2f}s".format(build_duration), flash_size, sram_size)) - - if build_result.returncode != 0: - print(build_result.stdout.decode("utf-8")) def build_size(example, board): #elf_file = 'examples/device/{}/_build/{}/{}-firmware.elf'.format(example, board, board) @@ -82,6 +88,7 @@ def build_size(example, board): sram_size = int(size_list[1]) + int(size_list[2]) return (flash_size, sram_size) + print(build_separator) print(build_format.format('Example', 'Board', '\033[39mResult\033[0m', 'Time', 'Flash', 'SRAM')) print(build_separator) From f36e0b7b923f632fbcc65373d77e0e127f03aace Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 3 Oct 2023 16:27:35 +0700 Subject: [PATCH 63/71] esp32 comment out uart, increase max3421 spi speed to 26mhz --- .idea/cmake.xml | 18 +++++++++--------- hw/bsp/espressif/boards/family.c | 14 +++++++++++--- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/.idea/cmake.xml b/.idea/cmake.xml index c6ebf2a46..9721af5ea 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -9,7 +9,7 @@ - + @@ -54,16 +54,16 @@ - + - + - - - - - - + + + + + + \ No newline at end of file diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index e45765fd1..c6a592627 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -41,6 +41,8 @@ #include "driver/periph_ctrl.h" #endif +// Note; current code use UART0 can cause device to reset while monitoring +#define USE_UART 0 #define UART_ID UART_NUM_0 #ifdef NEOPIXEL_PIN @@ -61,6 +63,7 @@ static void configure_pins(usb_hal_context_t *usb); // Initialize on-board peripherals : led, button, uart and USB void board_init(void) { +#if USE_UART // uart init uart_config_t uart_config = { .baud_rate = 115200, @@ -71,6 +74,7 @@ void board_init(void) { }; uart_driver_install(UART_ID, 1024, 0, 0, NULL, 0); uart_param_config(UART_ID, &uart_config); +#endif #ifdef NEOPIXEL_PIN #ifdef NEOPIXEL_POWER_PIN @@ -157,7 +161,11 @@ uint32_t board_button_read(void) { // Get characters from UART int board_uart_read(uint8_t *buf, int len) { +#if USE_UART return uart_read_bytes(UART_ID, buf, len, 0); +#else + return -1; +#endif } // Send characters to UART @@ -168,8 +176,8 @@ int board_uart_write(void const *buf, int len) { } int board_getchar(void) { - char c; - return (uart_read_bytes(UART_ID, &c, 1, 0) > 0) ? (int) c : (-1); + uint8_t c = 0; + return board_uart_read(&c, 1) > 0 ? (int) c : (-1); } //--------------------------------------------------------------------+ @@ -224,7 +232,7 @@ static void max3421_init(void) { spi_device_interface_config_t max3421_cfg = { .mode = 0, - .clock_speed_hz = 4000000, // 26000000 + .clock_speed_hz = 26000000, .spics_io_num = -1, // manual control CS .queue_size = 1 }; From 67e34267a68c81f62ff315ac990f07a60f4dc93c Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 4 Oct 2023 18:00:32 +0700 Subject: [PATCH 64/71] change tuh_max3421_spi_xfer_api() signature tested working with sam d21 and d51, not tested with nrf52, seem not working with esp32 --- hw/bsp/espressif/boards/family.c | 39 ++++++++++++++--------- hw/bsp/nrf/family.c | 20 ++++++++---- hw/bsp/samd21/family.c | 27 +++++++++------- hw/bsp/samd51/family.c | 35 +++++++++++--------- src/portable/analog/max3421/hcd_max3421.c | 27 +++++++++------- 5 files changed, 88 insertions(+), 60 deletions(-) diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index c6a592627..912ca5f35 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -38,7 +38,9 @@ #if ESP_IDF_VERSION_MAJOR > 4 #include "esp_private/periph_ctrl.h" #else + #include "driver/periph_ctrl.h" + #endif // Note; current code use UART0 can cause device to reset while monitoring @@ -46,16 +48,21 @@ #define UART_ID UART_NUM_0 #ifdef NEOPIXEL_PIN + #include "led_strip.h" -static led_strip_t *strip; + +static led_strip_t* strip; #endif #if CFG_TUH_ENABLED && CFG_TUH_MAX3421 + #include "driver/spi_master.h" + static void max3421_init(void); + #endif -static void configure_pins(usb_hal_context_t *usb); +static void configure_pins(usb_hal_context_t* usb); //--------------------------------------------------------------------+ // Implementation @@ -115,11 +122,11 @@ void board_init(void) { #endif } -static void configure_pins(usb_hal_context_t *usb) { +static void configure_pins(usb_hal_context_t* usb) { /* usb_periph_iopins currently configures USB_OTG as USB Device. * Introduce additional parameters in usb_hal_context_t when adding support * for USB Host. */ - for (const usb_iopin_dsc_t *iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) { + for (const usb_iopin_dsc_t* iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) { if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) { esp_rom_gpio_pad_select_gpio(iopin->pin); if (iopin->is_output) { @@ -160,7 +167,7 @@ uint32_t board_button_read(void) { } // Get characters from UART -int board_uart_read(uint8_t *buf, int len) { +int board_uart_read(uint8_t* buf, int len) { #if USE_UART return uart_read_bytes(UART_ID, buf, len, 0); #else @@ -169,7 +176,7 @@ int board_uart_read(uint8_t *buf, int len) { } // Send characters to UART -int board_uart_write(void const *buf, int len) { +int board_uart_write(void const* buf, int len) { (void) buf; (void) len; return 0; @@ -216,7 +223,7 @@ static void max3421_init(void) { gpio_set_level(MAX3421_CS_PIN, 1); // SPI - spi_bus_config_t buscfg={ + spi_bus_config_t buscfg = { .miso_io_num = MAX3421_MISO_PIN, .mosi_io_num = MAX3421_MOSI_PIN, .sclk_io_num = MAX3421_SCK_PIN, @@ -228,7 +235,7 @@ static void max3421_init(void) { .data7_io_num = -1, .max_transfer_sz = 1024 }; - ESP_ERROR_CHECK( spi_bus_initialize(MAX3421_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO) ); + ESP_ERROR_CHECK(spi_bus_initialize(MAX3421_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO)); spi_device_interface_config_t max3421_cfg = { .mode = 0, @@ -236,7 +243,7 @@ static void max3421_init(void) { .spics_io_num = -1, // manual control CS .queue_size = 1 }; - ESP_ERROR_CHECK( spi_bus_add_device(MAX3421_SPI_HOST, &max3421_cfg, &max3421_spi) ); + ESP_ERROR_CHECK(spi_bus_add_device(MAX3421_SPI_HOST, &max3421_cfg, &max3421_spi)); // debug gpio_set_direction(13, GPIO_MODE_OUTPUT); @@ -244,7 +251,7 @@ static void max3421_init(void) { // Interrupt pin max3421_intr_sem = xSemaphoreCreateBinary(); - xTaskCreate(max3421_intr_task, "max3421 intr", 2048, NULL, configMAX_PRIORITIES-2, NULL); + xTaskCreate(max3421_intr_task, "max3421 intr", 2048, NULL, configMAX_PRIORITIES - 2, NULL); gpio_set_direction(MAX3421_INTR_PIN, GPIO_MODE_INPUT); gpio_set_intr_type(MAX3421_INTR_PIN, GPIO_INTR_NEGEDGE); @@ -267,18 +274,20 @@ void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { gpio_set_level(MAX3421_CS_PIN, active ? 0 : 1); } -bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { +bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes) { (void) rhport; - if (tx_len == 0) { + if (tx_buf == NULL) { // fifo read, transmit rx_buf as dummy tx_buf = rx_buf; - tx_len = rx_len; } + // length in bits + size_t const len_bits = xfer_bytes << 3; + spi_transaction_t xact = { - .length = tx_len << 3, // length in bits - .rxlength = rx_len << 3, // length in bits + .length = len_bits, + .rxlength = rx_buf ? len_bits : 0, .tx_buffer = tx_buf, .rx_buffer = rx_buf }; diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index 631f53fcd..c431389f3 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -95,7 +95,9 @@ TU_ATTR_UNUSED static void power_event_handler(nrfx_power_usb_evt_t event) { //------------- Host using MAX2341E -------------// #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + static void max3421_init(void); + static nrfx_spim_t _spi = NRFX_SPIM_INSTANCE(1); #endif @@ -203,15 +205,15 @@ uint32_t board_button_read(void) { return BUTTON_STATE_ACTIVE == nrf_gpio_pin_read(BUTTON_PIN); } -int board_uart_read(uint8_t *buf, int len) { +int board_uart_read(uint8_t* buf, int len) { (void) buf; (void) len; return 0; // return NRFX_SUCCESS == nrfx_uart_rx(&_uart_id, buf, (size_t) len) ? len : 0; } -int board_uart_write(void const *buf, int len) { - return (NRFX_SUCCESS == nrfx_uarte_tx(&_uart_id, (uint8_t const *) buf, (size_t) len)) ? len : 0; +int board_uart_write(void const* buf, int len) { + return (NRFX_SUCCESS == nrfx_uarte_tx(&_uart_id, (uint8_t const*) buf, (size_t) len)) ? len : 0; } #if CFG_TUSB_OS == OPT_OS_NONE @@ -323,6 +325,7 @@ static void max3421_init(void) { nrfx_gpiote_trigger_enable(MAX3421_INTR_PIN, true); } +// API to enable/disable MAX3421 INTR pin interrupt void tuh_max3421_int_api(uint8_t rhport, bool enabled) { (void) rhport; @@ -335,22 +338,25 @@ void tuh_max3421_int_api(uint8_t rhport, bool enabled) { } } +// API to control MAX3421 SPI CS void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { (void) rhport; nrf_gpio_pin_write(MAX3421_CS_PIN, active ? 0 : 1); } -bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { +// API to transfer data with MAX3421 SPI +// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only +bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes) { (void) rhport; nrfx_spim_xfer_desc_t xfer = { .p_tx_buffer = tx_buf, - .tx_length = tx_len, + .tx_length = tx_buf ? xfer_bytes : 0, .p_rx_buffer = rx_buf, - .rx_length = rx_len, + .rx_length = rx_buf ? xfer_bytes : 0, }; - return (nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS); + return nrfx_spim_xfer(&_spi, &xfer, 0) == NRFX_SUCCESS; } #endif diff --git a/hw/bsp/samd21/family.c b/hw/bsp/samd21/family.c index b9365fc3f..ccb2c99b1 100644 --- a/hw/bsp/samd21/family.c +++ b/hw/bsp/samd21/family.c @@ -72,6 +72,7 @@ static void uart_init(void); #define MAX3421_SERCOM TU_XSTRCAT(SERCOM, MAX3421_SERCOM_ID) static void max3421_init(void); + #endif void board_init(void) { @@ -237,13 +238,13 @@ int board_uart_write(void const * buf, int len) static void uart_init(void) { } -int board_uart_read(uint8_t *buf, int len) { +int board_uart_read(uint8_t* buf, int len) { (void) buf; (void) len; return 0; } -int board_uart_write(void const *buf, int len) { +int board_uart_write(void const* buf, int len) { (void) buf; (void) len; return 0; @@ -261,6 +262,7 @@ void SysTick_Handler(void) { uint32_t board_millis(void) { return system_ticks; } + #endif //--------------------------------------------------------------------+ @@ -278,8 +280,8 @@ static void max3421_init(void) { // Configure GCLK for SERCOM // GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_SERCOM4_CORE | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; - GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_SERCOM0_CORE_Val+MAX3421_SERCOM_ID) | - GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCLK_CLKCTRL_ID_SERCOM0_CORE_Val + MAX3421_SERCOM_ID) | + GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN; while (GCLK->STATUS.bit.SYNCBUSY); Sercom* sercom = MAX3421_SERCOM; @@ -293,7 +295,7 @@ static void max3421_init(void) { // Set up SPI in master mode, MSB first, SPI mode 0 sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_DOPO(MAX3421_TX_PAD) | SERCOM_SPI_CTRLA_DIPO(MAX3421_RX_PAD) | - SERCOM_SPI_CTRLA_MODE(3); + SERCOM_SPI_CTRLA_MODE(3); sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN; while (sercom->SPI.SYNCBUSY.bit.CTRLB == 1); @@ -366,6 +368,7 @@ void EIC_Handler(void) { tuh_int_handler(1, true); } +// API to enable/disable MAX3421 INTR pin interrupt void tuh_max3421_int_api(uint8_t rhport, bool enabled) { (void) rhport; @@ -376,24 +379,26 @@ void tuh_max3421_int_api(uint8_t rhport, bool enabled) { } } +// API to control MAX3421 SPI CS void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { (void) rhport; gpio_set_pin_level(MAX3421_CS_PIN, active ? 0 : 1); } -bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { +// API to transfer data with MAX3421 SPI +// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only +bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes) { (void) rhport; Sercom* sercom = MAX3421_SERCOM; - size_t count = 0; - while (count < tx_len || count < rx_len) { + for (size_t count = 0; count < xfer_bytes; count++) { // Wait for the transmit buffer to be empty while (!sercom->SPI.INTFLAG.bit.DRE); // Write data to be transmitted uint8_t data = 0x00; - if (count < tx_len) { + if (tx_buf) { data = tx_buf[count]; } @@ -404,11 +409,9 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_l // Read received data data = (uint8_t) sercom->SPI.DATA.reg; - if (count < rx_len) { + if (rx_buf) { rx_buf[count] = data; } - - count++; } // wait for bus idle and clear flags diff --git a/hw/bsp/samd51/family.c b/hw/bsp/samd51/family.c index 4d43c7745..bca18e1a2 100644 --- a/hw/bsp/samd51/family.c +++ b/hw/bsp/samd51/family.c @@ -81,6 +81,7 @@ void USB_3_Handler(void) { #define MAX3421_EIC_Handler TU_XSTRCAT3(EIC_, MAX3421_INTR_EIC_ID, _Handler) static void max3421_init(void); + #endif void board_init(void) { @@ -153,13 +154,13 @@ uint32_t board_button_read(void) { return gpio_get_pin_level(BUTTON_PIN) ? 0 : 1; } -int board_uart_read(uint8_t *buf, int len) { +int board_uart_read(uint8_t* buf, int len) { (void) buf; (void) len; return 0; } -int board_uart_write(void const *buf, int len) { +int board_uart_write(void const* buf, int len) { (void) buf; (void) len; return 0; @@ -175,6 +176,7 @@ void SysTick_Handler(void) { uint32_t board_millis(void) { return system_ticks; } + #endif //--------------------------------------------------------------------+ @@ -189,7 +191,7 @@ static void max3421_init(void) { uint32_t const baudrate = 12000000u; struct { - volatile uint32_t *mck_apb; + volatile uint32_t* mck_apb; uint32_t mask; uint8_t gclk_id_core; uint8_t gclk_id_slow; @@ -214,8 +216,10 @@ static void max3421_init(void) { *sercom_clock[MAX3421_SERCOM_ID].mck_apb |= sercom_clock[MAX3421_SERCOM_ID].mask; // Configure GCLK for SERCOM - GCLK->PCHCTRL[sercom_clock[MAX3421_SERCOM_ID].gclk_id_core].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); - GCLK->PCHCTRL[sercom_clock[MAX3421_SERCOM_ID].gclk_id_slow].reg = GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); + GCLK->PCHCTRL[sercom_clock[MAX3421_SERCOM_ID].gclk_id_core].reg = + GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); + GCLK->PCHCTRL[sercom_clock[MAX3421_SERCOM_ID].gclk_id_slow].reg = + GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); // Disable the SPI module sercom->SPI.CTRLA.bit.ENABLE = 0; @@ -226,7 +230,7 @@ static void max3421_init(void) { // Set up SPI in master mode, MSB first, SPI mode 0 sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_DOPO(MAX3421_TX_PAD) | SERCOM_SPI_CTRLA_DIPO(MAX3421_RX_PAD) | - SERCOM_SPI_CTRLA_MODE(3); + SERCOM_SPI_CTRLA_MODE(3); sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN; while (sercom->SPI.SYNCBUSY.bit.CTRLB == 1); @@ -278,9 +282,9 @@ static void max3421_init(void) { while (EIC->SYNCBUSY.bit.ENABLE); // Configure EIC to trigger on falling edge - volatile uint32_t * eic_config; + volatile uint32_t* eic_config; uint8_t sense_shift; - if ( MAX3421_INTR_EIC_ID < 8 ) { + if (MAX3421_INTR_EIC_ID < 8) { eic_config = &EIC->CONFIG[0].reg; sense_shift = MAX3421_INTR_EIC_ID * 4; } else { @@ -312,6 +316,7 @@ void MAX3421_EIC_Handler(void) { tuh_int_handler(1, true); } +// API to enable/disable MAX3421 INTR pin interrupt void tuh_max3421_int_api(uint8_t rhport, bool enabled) { (void) rhport; @@ -323,24 +328,26 @@ void tuh_max3421_int_api(uint8_t rhport, bool enabled) { } } +// API to control MAX3421 SPI CS void tuh_max3421_spi_cs_api(uint8_t rhport, bool active) { (void) rhport; gpio_set_pin_level(MAX3421_CS_PIN, active ? 0 : 1); } -bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_len, uint8_t *rx_buf, size_t rx_len) { +// API to transfer data with MAX3421 SPI +// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only +bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes) { (void) rhport; Sercom* sercom = MAX3421_SERCOM; - size_t count = 0; - while (count < tx_len || count < rx_len) { + for (size_t count = 0; count < xfer_bytes; count++) { // Wait for the transmit buffer to be empty while (!sercom->SPI.INTFLAG.bit.DRE); // Write data to be transmitted uint8_t data = 0x00; - if (count < tx_len) { + if (tx_buf) { data = tx_buf[count]; } @@ -351,11 +358,9 @@ bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const *tx_buf, size_t tx_l // Read received data data = (uint8_t) sercom->SPI.DATA.reg; - if (count < rx_len) { + if (rx_buf) { rx_buf[count] = data; } - - count++; } // wait for bus idle and clear flags diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 77912a4c9..787c1e511 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -210,16 +210,21 @@ static max3421_data_t _hcd_data; // API: SPI transfer with MAX3421E, must be implemented by application //--------------------------------------------------------------------+ -void tuh_max3421_spi_cs_api(uint8_t rhport, bool active); -bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const * tx_buf, size_t tx_len, uint8_t * rx_buf, size_t rx_len); -void tuh_max3421_int_api(uint8_t rhport, bool enabled); +// API to control MAX3421 SPI CS +extern void tuh_max3421_spi_cs_api(uint8_t rhport, bool active); -static void handle_connect_irq(uint8_t rhport, bool in_isr); -static inline void hirq_write(uint8_t rhport, uint8_t data, bool in_isr); +// API to transfer data with MAX3421 SPI +// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only +extern bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes); + +// API to enable/disable MAX3421 INTR pin interrupt +extern void tuh_max3421_int_api(uint8_t rhport, bool enabled); //--------------------------------------------------------------------+ // SPI Helper //--------------------------------------------------------------------+ +static void handle_connect_irq(uint8_t rhport, bool in_isr); +static inline void hirq_write(uint8_t rhport, uint8_t data, bool in_isr); static void max3421_spi_lock(uint8_t rhport, bool in_isr) { // disable interrupt and mutex lock (for pre-emptive RTOS) if not in_isr @@ -249,9 +254,9 @@ static void fifo_write(uint8_t rhport, uint8_t reg, uint8_t const * buffer, uint max3421_spi_lock(rhport, in_isr); - tuh_max3421_spi_xfer_api(rhport, ®, 1, &hirq, 1); + tuh_max3421_spi_xfer_api(rhport, ®, &hirq, 1); _hcd_data.hirq = hirq; - tuh_max3421_spi_xfer_api(rhport, buffer, len, NULL, 0); + tuh_max3421_spi_xfer_api(rhport, buffer, NULL, len); max3421_spi_unlock(rhport, in_isr); @@ -263,9 +268,9 @@ static void fifo_read(uint8_t rhport, uint8_t * buffer, uint16_t len, bool in_is max3421_spi_lock(rhport, in_isr); - tuh_max3421_spi_xfer_api(rhport, ®, 1, &hirq, 1); + tuh_max3421_spi_xfer_api(rhport, ®, &hirq, 1); _hcd_data.hirq = hirq; - tuh_max3421_spi_xfer_api(rhport, NULL, 0, buffer, len); + tuh_max3421_spi_xfer_api(rhport, NULL, buffer, len); max3421_spi_unlock(rhport, in_isr); } @@ -276,7 +281,7 @@ static void reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr) { max3421_spi_lock(rhport, in_isr); - tuh_max3421_spi_xfer_api(rhport, tx_buf, 2, rx_buf, 2); + tuh_max3421_spi_xfer_api(rhport, tx_buf, rx_buf, 2); max3421_spi_unlock(rhport, in_isr); @@ -290,7 +295,7 @@ static uint8_t reg_read(uint8_t rhport, uint8_t reg, bool in_isr) { max3421_spi_lock(rhport, in_isr); - bool ret = tuh_max3421_spi_xfer_api(rhport, tx_buf, 2, rx_buf, 2); + bool ret = tuh_max3421_spi_xfer_api(rhport, tx_buf, rx_buf, 2); max3421_spi_unlock(rhport, in_isr); From cfb683f48178966a7386538c1082e5aa6ebf53f4 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 5 Oct 2023 17:01:41 +0700 Subject: [PATCH 65/71] tested with nrf52840 and esp32s2 --- hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake | 4 ++-- hw/bsp/nrf/boards/feather_nrf52840_express/board.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake b/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake index ce6da8b43..726438d05 100644 --- a/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake +++ b/hw/bsp/nrf/boards/feather_nrf52840_express/board.cmake @@ -1,6 +1,6 @@ set(MCU_VARIANT nrf52840) -#set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld) -set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52840_xxaa.ld) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/nrf52840_s140_v6.ld) +#set(LD_FILE_GNU ${NRFX_DIR}/mdk/nrf52840_xxaa.ld) # enable max3421 host driver for this board set(MAX3421_HOST 1) diff --git a/hw/bsp/nrf/boards/feather_nrf52840_express/board.h b/hw/bsp/nrf/boards/feather_nrf52840_express/board.h index 76100a14a..3d59516d8 100644 --- a/hw/bsp/nrf/boards/feather_nrf52840_express/board.h +++ b/hw/bsp/nrf/boards/feather_nrf52840_express/board.h @@ -49,8 +49,8 @@ #define MAX3421_SCK_PIN 14 #define MAX3421_MOSI_PIN 13 #define MAX3421_MISO_PIN 15 -#define MAX3421_CS_PIN 27 -#define MAX3421_INTR_PIN 26 +#define MAX3421_CS_PIN 27 // D10 +#define MAX3421_INTR_PIN 26 // D9 #ifdef __cplusplus } From 8b2cb63da88c0f790fee8d514971153569993b05 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 10 Oct 2023 18:22:20 +0200 Subject: [PATCH 66/71] Fix naming nBytesPerSample. --- src/class/audio/audio_device.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 46fd6dfa9..5d3772a9d 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -631,9 +631,9 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t // Decoding according to 2.3.1.5 Audio Streams // Helper function -static inline void * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesToCopy, void * dst, const void * dst_end, void * src, uint8_t const n_ff_used) +static inline void * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesPerSample, void * dst, const void * dst_end, void * src, uint8_t const n_ff_used) { - // Due to one FIFO contains 2 channels, data always aligned to (nBytesToCopy * 2) + // Due to one FIFO contains 2 channels, data always aligned to (nBytesPerSample * 2) uint16_t * dst16 = dst; uint16_t * src16 = src; const uint16_t * dst_end16 = dst_end; @@ -641,7 +641,7 @@ static inline void * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nB uint32_t * src32 = src; const uint32_t * dst_end32 = dst_end; - if (nBytesToCopy == 1) + if (nBytesPerSample == 1) { while(dst16 < dst_end16) { @@ -650,7 +650,7 @@ static inline void * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nB } return src16; } - else if (nBytesToCopy == 2) + else if (nBytesPerSample == 2) { while(dst32 < dst_end32) { @@ -659,7 +659,7 @@ static inline void * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nB } return src32; } - else if (nBytesToCopy == 3) + else if (nBytesPerSample == 3) { while(dst16 < dst_end16) { @@ -670,7 +670,7 @@ static inline void * audiod_interleaved_copy_bytes_fast_decode(uint16_t const nB } return src16; } - else // nBytesToCopy == 4 + else // nBytesPerSample == 4 { while(dst32 < dst_end32) { @@ -926,9 +926,9 @@ range [-1, +1) * */ // Helper function -static inline void * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesToCopy, void * src, const void * src_end, void * dst, uint8_t const n_ff_used) +static inline void * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesPerSample, void * src, const void * src_end, void * dst, uint8_t const n_ff_used) { - // Due to one FIFO contains 2 channels, data always aligned to (nBytesToCopy * 2) + // Due to one FIFO contains 2 channels, data always aligned to (nBytesPerSample * 2) uint16_t * dst16 = dst; uint16_t * src16 = src; const uint16_t * src_end16 = src_end; @@ -936,7 +936,7 @@ static inline void * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nB uint32_t * src32 = src; const uint32_t * src_end32 = src_end; - if (nBytesToCopy == 1) + if (nBytesPerSample == 1) { while(src16 < src_end16) { @@ -945,7 +945,7 @@ static inline void * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nB } return dst16; } - else if (nBytesToCopy == 2) + else if (nBytesPerSample == 2) { while(src32 < src_end32) { @@ -954,7 +954,7 @@ static inline void * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nB } return dst32; } - else if (nBytesToCopy == 3) + else if (nBytesPerSample == 3) { while(src16 < src_end16) { @@ -965,7 +965,7 @@ static inline void * audiod_interleaved_copy_bytes_fast_encode(uint16_t const nB } return dst16; } - else // nBytesToCopy == 4 + else // nBytesPerSample == 4 { while(src32 < src_end32) { From 2ba760a1c16dc096da9f96f20cf2443e3a1d8416 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 10 Oct 2023 18:24:47 +0200 Subject: [PATCH 67/71] Enhance audio_4_channel_mic example, plot 4 different waves for each channel. --- .../device/audio_4_channel_mic/src/main.c | 43 +++++++++++-------- .../audio_4_channel_mic/src/tusb_config.h | 3 +- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/examples/device/audio_4_channel_mic/src/main.c b/examples/device/audio_4_channel_mic/src/main.c index 94ac86d84..3b21b4ac6 100644 --- a/examples/device/audio_4_channel_mic/src/main.c +++ b/examples/device/audio_4_channel_mic/src/main.c @@ -34,17 +34,16 @@ #include #include #include +#include "arm_math.h" #include "bsp/board_api.h" #include "tusb.h" +#include "tusb_config.h" //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ - -#ifndef AUDIO_SAMPLE_RATE -#define AUDIO_SAMPLE_RATE 48000 -#endif +#define AUDIO_SAMPLE_RATE CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE /* Blink pattern * - 250 ms : device not mounted @@ -70,7 +69,7 @@ uint8_t clkValid; audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state -// Audio test data +// Audio test data, each buffer contains 2 channels, buffer[0] for CH0-1, buffer[1] for CH1-2 uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ/2]; // Ensure half word aligned void led_blinking_task(void); @@ -400,7 +399,8 @@ bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, u (void) ep_in; (void) cur_alt_setting; - for (uint8_t cnt=0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++) + // Write buffer[0] (CH0-1) and buffer[1] (CH1-2) into FIFO + for (uint8_t cnt=0; cnt < 2; cnt++) { tud_audio_write_support_ff(cnt, i2s_dummy_buffer[cnt], AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX); } @@ -416,22 +416,27 @@ bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uin (void) ep_in; (void) cur_alt_setting; - uint16_t dataVal; - // Generate dummy data - for (uint16_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++) + uint16_t * p_buff = i2s_dummy_buffer[0]; + uint16_t dataVal = 1; + for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) { - uint16_t * p_buff = i2s_dummy_buffer[cnt]; // 2 bytes per sample - dataVal = 1; - for (uint16_t cnt2 = 0; cnt2 < AUDIO_SAMPLE_RATE/1000; cnt2++) - { - for (uint8_t cnt3 = 0; cnt3 < CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX; cnt3++) - { - *p_buff++ = dataVal; - } - dataVal++; - } + // CH0 saw wave + *p_buff++ = dataVal; + // CH1 inverted saw wave + *p_buff++ = 60 + AUDIO_SAMPLE_RATE/1000 - dataVal; + dataVal++; } + p_buff = i2s_dummy_buffer[1]; + for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) + { + // CH3 square wave + *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 120:170; + // CH4 sinus wave + q15_t t = 0x7FFF * cnt / (AUDIO_SAMPLE_RATE/1000); + *p_buff++ = arm_sin_q15(t) / 1300 + 200; + } + return true; } diff --git a/examples/device/audio_4_channel_mic/src/tusb_config.h b/examples/device/audio_4_channel_mic/src/tusb_config.h index 5cf6d07c3..291ac4f79 100644 --- a/examples/device/audio_4_channel_mic/src/tusb_config.h +++ b/examples/device/audio_4_channel_mic/src/tusb_config.h @@ -103,6 +103,7 @@ extern "C" { //-------------------------------------------------------------------- // Have a look into audio_device.h for all configurations +#define CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE 48000 #define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_MIC_FOUR_CH_DESC_LEN @@ -112,7 +113,7 @@ extern "C" { #define CFG_TUD_AUDIO_ENABLE_EP_IN 1 #define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX 2 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 4 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup -#define CFG_TUD_AUDIO_EP_SZ_IN (48 + 1) * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX // 48 Samples (48 kHz) x 2 Bytes/Sample x CFG_TUD_AUDIO_N_CHANNELS_TX Channels - the Windows driver always needs an extra sample per channel of space more, otherwise it complains... found by trial and error +#define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN From 20699e30dd7847a7177d91dc76791248a788f3dc Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 10 Oct 2023 18:25:14 +0200 Subject: [PATCH 68/71] Enhance plot script. --- .../device/audio_4_channel_mic/src/plot_audio_samples.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/device/audio_4_channel_mic/src/plot_audio_samples.py b/examples/device/audio_4_channel_mic/src/plot_audio_samples.py index 8312b4e28..a3a2b2fd4 100644 --- a/examples/device/audio_4_channel_mic/src/plot_audio_samples.py +++ b/examples/device/audio_4_channel_mic/src/plot_audio_samples.py @@ -10,7 +10,7 @@ if __name__ == '__main__': # print(sd.query_devices()) fs = 48000 # Sample rate - duration = 100e-3 # Duration of recording + duration = 20e-3 # Duration of recording if platform.system() == 'Windows': # WDM-KS is needed since there are more than one MicNode device APIs (at least in Windows) @@ -25,9 +25,14 @@ if __name__ == '__main__': sd.wait() # Wait until recording is finished print('Done!') + time = np.arange(0, duration, 1 / fs) # time vector + # strip starting zero + myrecording = myrecording[100:] + time = time[100:] plt.plot(time, myrecording) plt.xlabel('Time [s]') plt.ylabel('Amplitude') plt.title('MicNode 4 Channel') + plt.legend(['CH-1', 'CH-2', 'CH-3','CH-4']) plt.show() From 504d29cf7ae9f40a56c73a2e666564b9b4ab9efd Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 10 Oct 2023 18:25:42 +0200 Subject: [PATCH 69/71] Update make & cmake file. --- examples/device/audio_4_channel_mic/CMakeLists.txt | 7 +++++++ examples/device/audio_4_channel_mic/Makefile | 11 ++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/examples/device/audio_4_channel_mic/CMakeLists.txt b/examples/device/audio_4_channel_mic/CMakeLists.txt index f61e1b640..ae6bf0142 100644 --- a/examples/device/audio_4_channel_mic/CMakeLists.txt +++ b/examples/device/audio_4_channel_mic/CMakeLists.txt @@ -23,9 +23,16 @@ target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) +# CMSIS sources +target_sources(${PROJECT} PUBLIC + ${TOP}/lib/CMSIS_5/CMSIS/DSP/Source/CommonTables/arm_common_tables.c + ${TOP}/lib/CMSIS_5/CMSIS/DSP/Source/FastMathFunctions/arm_sin_q15.c + ) + # Example include target_include_directories(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src + ${TOP}/lib/CMSIS_5/CMSIS/DSP/Include ) # Configure compilation flags and libraries for the example without RTOS. diff --git a/examples/device/audio_4_channel_mic/Makefile b/examples/device/audio_4_channel_mic/Makefile index 2a3d854fb..97e4118c0 100644 --- a/examples/device/audio_4_channel_mic/Makefile +++ b/examples/device/audio_4_channel_mic/Makefile @@ -3,9 +3,18 @@ include ../../make.mk INC += \ src \ $(TOP)/hw \ + $(TOP)/lib/CMSIS_5/CMSIS/DSP/Include \ # Example source -EXAMPLE_SOURCE += $(wildcard src/*.c) +EXAMPLE_SOURCE += \ + src/main.c \ + src/usb_descriptors.c \ + +# CMSIS sources +SRC_C += \ + lib/CMSIS_5/CMSIS/DSP/Source/CommonTables/arm_common_tables.c \ + lib/CMSIS_5/CMSIS/DSP/Source/FastMathFunctions/arm_sin_q15.c \ + SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) include ../../rules.mk From e2852da668ae5f8e2398ac0a4c2a93d5f50f2618 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 10 Oct 2023 18:35:24 +0200 Subject: [PATCH 70/71] Update deps. --- tools/get_deps.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/get_deps.py b/tools/get_deps.py index 1fac291a3..8eea3e6de 100644 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -166,8 +166,9 @@ deps_optional = { 'ch32v307'], 'lib/CMSIS_5': ['https://github.com/ARM-software/CMSIS_5.git', '20285262657d1b482d132d20d755c8c330d55c1f', - 'imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf ra saml2x' - 'stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 ' + 'imxrt kinetis_k32l2 kinetis_kl lpc11 lpc13 lpc15 lpc17 lpc18 lpc40' + 'lpc43 lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf ra saml2x rp2040' + 'stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4' 'stm32h7 stm32l0 stm32l1 stm32l4 stm32l5 stm32u5 stm32wb'], 'lib/sct_neopixel': ['https://github.com/gsteiert/sct_neopixel.git', 'e73e04ca63495672d955f9268e003cffe168fcd8', From c8430f5f85d587a996bc0301a47be12cc70cedb7 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 10 Oct 2023 19:08:25 +0200 Subject: [PATCH 71/71] Refactor to get rid of CMSIS DSP lib. --- .../device/audio_4_channel_mic/CMakeLists.txt | 12 ++-- examples/device/audio_4_channel_mic/Makefile | 6 -- examples/device/audio_4_channel_mic/skip.txt | 1 + .../device/audio_4_channel_mic/src/main.c | 55 +++++++++++-------- tools/get_deps.py | 5 +- 5 files changed, 40 insertions(+), 39 deletions(-) diff --git a/examples/device/audio_4_channel_mic/CMakeLists.txt b/examples/device/audio_4_channel_mic/CMakeLists.txt index ae6bf0142..0f5d36193 100644 --- a/examples/device/audio_4_channel_mic/CMakeLists.txt +++ b/examples/device/audio_4_channel_mic/CMakeLists.txt @@ -23,18 +23,16 @@ target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c ) -# CMSIS sources -target_sources(${PROJECT} PUBLIC - ${TOP}/lib/CMSIS_5/CMSIS/DSP/Source/CommonTables/arm_common_tables.c - ${TOP}/lib/CMSIS_5/CMSIS/DSP/Source/FastMathFunctions/arm_sin_q15.c - ) - # Example include target_include_directories(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src - ${TOP}/lib/CMSIS_5/CMSIS/DSP/Include ) +# Add libm for GCC +if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_libraries(${PROJECT} PUBLIC m) +endif() + # Configure compilation flags and libraries for the example without RTOS. # See the corresponding function in hw/bsp/FAMILY/family.cmake for details. family_configure_device_example(${PROJECT} noos) diff --git a/examples/device/audio_4_channel_mic/Makefile b/examples/device/audio_4_channel_mic/Makefile index 97e4118c0..8ee6a01ec 100644 --- a/examples/device/audio_4_channel_mic/Makefile +++ b/examples/device/audio_4_channel_mic/Makefile @@ -3,18 +3,12 @@ include ../../make.mk INC += \ src \ $(TOP)/hw \ - $(TOP)/lib/CMSIS_5/CMSIS/DSP/Include \ # Example source EXAMPLE_SOURCE += \ src/main.c \ src/usb_descriptors.c \ -# CMSIS sources -SRC_C += \ - lib/CMSIS_5/CMSIS/DSP/Source/CommonTables/arm_common_tables.c \ - lib/CMSIS_5/CMSIS/DSP/Source/FastMathFunctions/arm_sin_q15.c \ - SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) include ../../rules.mk diff --git a/examples/device/audio_4_channel_mic/skip.txt b/examples/device/audio_4_channel_mic/skip.txt index 1ee86a485..3c42a96d9 100644 --- a/examples/device/audio_4_channel_mic/skip.txt +++ b/examples/device/audio_4_channel_mic/skip.txt @@ -1,3 +1,4 @@ mcu:SAMD11 mcu:SAME5X mcu:SAMG +family:broadcom_64bit diff --git a/examples/device/audio_4_channel_mic/src/main.c b/examples/device/audio_4_channel_mic/src/main.c index 3b21b4ac6..4bcbdb692 100644 --- a/examples/device/audio_4_channel_mic/src/main.c +++ b/examples/device/audio_4_channel_mic/src/main.c @@ -34,7 +34,7 @@ #include #include #include -#include "arm_math.h" +#include #include "bsp/board_api.h" #include "tusb.h" @@ -96,6 +96,27 @@ int main(void) sampleFreqRng.subrange[0].bMax = AUDIO_SAMPLE_RATE; sampleFreqRng.subrange[0].bRes = 0; + // Generate dummy data + uint16_t * p_buff = i2s_dummy_buffer[0]; + uint16_t dataVal = 1; + for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) + { + // CH0 saw wave + *p_buff++ = dataVal; + // CH1 inverted saw wave + *p_buff++ = 60 + AUDIO_SAMPLE_RATE/1000 - dataVal; + dataVal++; + } + p_buff = i2s_dummy_buffer[1]; + for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) + { + // CH3 square wave + *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 120:170; + // CH4 sinus wave + float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000); + *p_buff++ = (uint16_t)(sinf(t) * 25) + 200; + } + while (1) { tud_task(); // tinyusb device task @@ -399,7 +420,16 @@ bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, u (void) ep_in; (void) cur_alt_setting; - // Write buffer[0] (CH0-1) and buffer[1] (CH1-2) into FIFO + + // In read world application data flow is driven by I2S clock, + // both tud_audio_tx_done_pre_load_cb() & tud_audio_tx_done_post_load_cb() are hardly used. + // For example in your I2S receive callback: + // void I2S_Rx_Callback(int channel, const void* data, uint16_t samples) + // { + // tud_audio_write_support_ff(channel, data, samples * N_BYTES_PER_SAMPLE * N_CHANNEL_PER_FIFO); + // } + + // Write I2S buffer into FIFO for (uint8_t cnt=0; cnt < 2; cnt++) { tud_audio_write_support_ff(cnt, i2s_dummy_buffer[cnt], AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX); @@ -416,27 +446,6 @@ bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uin (void) ep_in; (void) cur_alt_setting; - // Generate dummy data - uint16_t * p_buff = i2s_dummy_buffer[0]; - uint16_t dataVal = 1; - for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) - { - // CH0 saw wave - *p_buff++ = dataVal; - // CH1 inverted saw wave - *p_buff++ = 60 + AUDIO_SAMPLE_RATE/1000 - dataVal; - dataVal++; - } - p_buff = i2s_dummy_buffer[1]; - for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) - { - // CH3 square wave - *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 120:170; - // CH4 sinus wave - q15_t t = 0x7FFF * cnt / (AUDIO_SAMPLE_RATE/1000); - *p_buff++ = arm_sin_q15(t) / 1300 + 200; - } - return true; } diff --git a/tools/get_deps.py b/tools/get_deps.py index 8eea3e6de..1fac291a3 100644 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -166,9 +166,8 @@ deps_optional = { 'ch32v307'], 'lib/CMSIS_5': ['https://github.com/ARM-software/CMSIS_5.git', '20285262657d1b482d132d20d755c8c330d55c1f', - 'imxrt kinetis_k32l2 kinetis_kl lpc11 lpc13 lpc15 lpc17 lpc18 lpc40' - 'lpc43 lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf ra saml2x rp2040' - 'stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4' + 'imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf ra saml2x' + 'stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 ' 'stm32h7 stm32l0 stm32l1 stm32l4 stm32l5 stm32u5 stm32wb'], 'lib/sct_neopixel': ['https://github.com/gsteiert/sct_neopixel.git', 'e73e04ca63495672d955f9268e003cffe168fcd8',