From edc52814e7afa97db75c5e8f559f859cd954fa8f Mon Sep 17 00:00:00 2001 From: tobozo Date: Tue, 9 Aug 2022 18:25:19 +0200 Subject: [PATCH] ESP32-S2 Support --- examples/USB_Test/USB_Test.ino | 22 ++- examples/USB_Test/usbkbd.h | 6 +- library.properties | 5 +- src/ESP32-USB-Soft-Host.h | 12 ++ src/ESP32-USBSoftHost.hpp | 112 +++++++++++-- src/log.txt | 290 +++++++++++++++++++++++++++++++++ src/usb_host.c | 206 +++++++++++++++-------- src/usb_host.h | 66 ++------ 8 files changed, 574 insertions(+), 145 deletions(-) create mode 100644 src/ESP32-USB-Soft-Host.h create mode 100644 src/log.txt diff --git a/examples/USB_Test/USB_Test.ino b/examples/USB_Test/USB_Test.ino index 12ac440..8a69d36 100644 --- a/examples/USB_Test/USB_Test.ino +++ b/examples/USB_Test/USB_Test.ino @@ -1,4 +1,4 @@ - +#define DEBUG_ALL #include #include "usbkbd.h" // KeyboardReportParser @@ -56,11 +56,23 @@ #define DM_P0 8 #define DP_P1 -1 #define DM_P1 -1 + #define DP_P2 -1 + #define DM_P2 -1 + #define DP_P3 -1 + #define DM_P3 -1 +#elif CONFIG_IDF_TARGET_ESP32S2 || defined CONFIG_IDF_TARGET_ESP32S2 + #define LOAD_TINYUSB + #define PROFILE_NAME "ESP32 S2 Dev module" + // [OK] 20/19 (USB RS/TS) + #define DP_P0 20 // ok + #define DM_P0 19 // ok + #define DP_P1 -1 #define DM_P1 -1 #define DP_P2 -1 #define DM_P2 -1 #define DP_P3 -1 #define DM_P3 -1 + #else // default pins tested on ESP32-Wroom #define PROFILE_NAME "Default Wroom" @@ -75,7 +87,6 @@ #endif - static void my_USB_DetectCB( uint8_t usbNum, void * dev ) { sDevDesc *device = (sDevDesc*)dev; @@ -119,14 +130,11 @@ usb_pins_config_t USB_Pins_Config = void setup() { - Serial.begin(115200); - delay(200); + delay(5000); Serial.printf("USB Soft Host Test for %s\n", PROFILE_NAME ); - delay(1000); - + Serial.printf("TIMER_BASE_CLK: %d, TIMER_DIVIDER:%d, TIMER_SCALE: %d\n", TIMER_BASE_CLK, TIMER_DIVIDER, TIMER_SCALE ); USH.init( USB_Pins_Config, my_USB_DetectCB, my_USB_PrintCB ); - } void loop() diff --git a/examples/USB_Test/usbkbd.h b/examples/USB_Test/usbkbd.h index 43b1b69..4b7ea8b 100644 --- a/examples/USB_Test/usbkbd.h +++ b/examples/USB_Test/usbkbd.h @@ -99,13 +99,13 @@ class KeyboardReportParser { switch(key) { case UHS_HID_BOOT_KEY_NUM_LOCK: - bmNumLock = ~bmNumLock; + bmNumLock = !bmNumLock; break; case UHS_HID_BOOT_KEY_CAPS_LOCK: - bmCapsLock = ~bmCapsLock; + bmCapsLock = !bmCapsLock; break; case UHS_HID_BOOT_KEY_SCROLL_LOCK: - bmScrollLock = ~bmScrollLock; + bmScrollLock = !bmScrollLock; break; } return 0; diff --git a/library.properties b/library.properties index a4f0ef3..326c86d 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,10 @@ name=ESP32-USB-Soft-Host -version=0.1.1 +version=0.1.2 author=tobozo maintainer=tobozo sentence="An Arduino wrapper to @sdima1357's usb_soft_host esp-idf example" paragraph="ESP32-USB-Soft-Host is a pure software USB host through general IO pins. It can connect up to 4 USB-LS HID (keyboard mouse joystick) devices simultaneously." -category=Data Processing +category=Device Control +includes=ESP32-USB-Soft-Host.h url=https://github.com/tobozo/ESP32-USB-Soft-Host/ architectures=esp32 diff --git a/src/ESP32-USB-Soft-Host.h b/src/ESP32-USB-Soft-Host.h new file mode 100644 index 0000000..77b3e12 --- /dev/null +++ b/src/ESP32-USB-Soft-Host.h @@ -0,0 +1,12 @@ +#pragma once + +#ifdef __cplusplus + + #include "ESP32-USBSoftHost.hpp" + +#else + + #error ESP32-USB-Soft-Host requires a C++ compiler, please change file extension to .cc or .cpp + +#endif + diff --git a/src/ESP32-USBSoftHost.hpp b/src/ESP32-USBSoftHost.hpp index 0af6f1f..f201f2d 100644 --- a/src/ESP32-USBSoftHost.hpp +++ b/src/ESP32-USBSoftHost.hpp @@ -4,6 +4,8 @@ #ifndef BLINK_GPIO #if CONFIG_IDF_TARGET_ESP32C3 || defined ESP32C3 #define BLINK_GPIO 18 + #elif CONFIG_IDF_TARGET_ESP32S2 || defined ESP32S2 + #define BLINK_GPIO 2 //19 // 9 // 2 #else #define BLINK_GPIO 22 #endif @@ -15,6 +17,7 @@ extern "C" { #include "usb_host.h" } + static xQueueHandle usb_msg_queue = NULL; struct USBMessage @@ -81,6 +84,54 @@ static void Default_USB_DataCB(uint8_t usbNum, uint8_t byte_depth, uint8_t* data } +#if !defined USE_NATIVE_GROUP_TIMERS + + typedef struct + { + int type; // the type of timer's event + int timer_group; + int timer_idx; + uint64_t timer_counter_value; + } timer_event_t; + static xQueueHandle timer_queue = NULL; + + void IRAM_ATTR timer_group0_isr(void *para) + { + // this is mainly a group-timer layer for esp-idf 3.x + // most of this is handled by the SDK since esp-idf 4.x + int timer_idx = (int) para; + uint32_t intr_status = TIMERG0.int_st_timers.val;// Retrieve the interrupt status and the counter value from the timer that reported the interrupt + TIMERG0.hw_timer[timer_idx].update = 1; + uint64_t timer_counter_value = ((uint64_t) TIMERG0.hw_timer[timer_idx].cnt_high) << 32 | TIMERG0.hw_timer[timer_idx].cnt_low; + timer_event_t evt; // Prepare basic event data that will be then sent back to the main program task + evt.timer_group = 0; + evt.timer_idx = timer_idx; + evt.timer_counter_value = timer_counter_value; + usb_process();// process USB signal + if ((intr_status & BIT(timer_idx)) && timer_idx == TIMER_0) { // Clear the interrupt and update the alarm time for the timer with without reload + evt.type = 1; // no reload + TIMERG0.int_clr_timers.t0 = 1; + timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE); + TIMERG0.hw_timer[timer_idx].alarm_high = (uint32_t) (timer_counter_value >> 32); + TIMERG0.hw_timer[timer_idx].alarm_low = (uint32_t) timer_counter_value; + } + TIMERG0.hw_timer[timer_idx].config.alarm_en = TIMER_ALARM_EN; // After the alarm has been triggered we need enable it again, so it is triggered the next time + xQueueSendFromISR(timer_queue, &evt, NULL); // Now just send the event data back to the main program task + + } + +#else + + void IRAM_ATTR timer_group0_isr(void *para) + { + timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0); + //taskENTER_CRITICAL(); + usb_process(); + //taskEXIT_CRITICAL(); + timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_0); + } + +#endif class USB_SOFT_HOST @@ -116,14 +167,19 @@ class USB_SOFT_HOST bool USB_SOFT_HOST::init( usb_pins_config_t pconf, ondetectcb_t onDetectCB, printcb_t onDataCB, ontick_t onTickCB ) { + Serial.println("Attaching onDetectCB"); setOndetectCb( onDetectCB ); + Serial.println("Attaching onDataCB"); setPrintCb( onDataCB ); + Serial.println("Attaching onUSBMessageDecode"); setUSBMessageCb( onUSBMessageDecode ); - //setMessageReceiver( + Serial.println("Attaching onTickCB"); USB_SOFT_HOST::setTaskTicker( onTickCB ); if( _init( pconf ) ) { + Serial.println("Attaching Timer Task"); xTaskCreatePinnedToCore(USB_SOFT_HOST::TimerTask, "USB Soft Host Timer Task", 8192, NULL, priority, NULL, core); - log_w("USB Soft Host Group timer task is now running on core #%d with priority %d", core, priority); + //xTaskCreate(USB_SOFT_HOST::TimerTask, "USB Soft Host Timer Task", 8192, NULL, priority, NULL); + Serial.printf("USB Soft Host Group timer task is now running on core #%d with priority %d\n", core, priority); return true; } return false; @@ -135,21 +191,21 @@ bool USB_SOFT_HOST::_init( usb_pins_config_t pconf ) { if( inited ) return false; - timer_config_t config; - config.divider = TIMER_DIVIDER; - config.counter_dir = TIMER_COUNT_UP; - config.counter_en = TIMER_PAUSE; - config.alarm_en = TIMER_ALARM_EN; - config.auto_reload = (timer_autoreload_t) 1; // fix for ¬invalid conversion from 'int' to 'timer_autoreload_t'¬ thanks rudi ;-) - #if !defined USE_NATIVE_GROUP_TIMERS + Serial.println("Using custom group timer"); timer_queue = xQueueCreate( 10, sizeof(timer_event_t) ); #endif - setDelay(4); + Serial.println("Creating message queue"); usb_msg_queue = xQueueCreate( 10, sizeof(struct USBMessage) ); + Serial.println("Setting USB Delay"); + + setDelay(4); + + Serial.println("Setting up pins"); + initStates( (gpio_num_t)pconf.dp0, (gpio_num_t)pconf.dm0, (gpio_num_t)pconf.dp1, (gpio_num_t)pconf.dm1, @@ -157,14 +213,48 @@ bool USB_SOFT_HOST::_init( usb_pins_config_t pconf ) (gpio_num_t)pconf.dp3, (gpio_num_t)pconf.dm3 ); + Serial.printf("Seleting SCL (blink) Pin #%d\n", BLINK_GPIO); + gpio_pad_select_gpio((gpio_num_t)BLINK_GPIO); - //gpio_set_direction((gpio_num_t)BLINK_GPIO, GPIO_MODE_OUTPUT); + gpio_set_direction((gpio_num_t)BLINK_GPIO, GPIO_MODE_OUTPUT); + + Serial.println("Creating timer config"); + + #if defined ESP32 || defined ESP32S2 + timer_config_t config; + config.divider = TIMER_DIVIDER; + config.counter_dir = TIMER_COUNT_UP; + config.counter_en = TIMER_PAUSE; + config.alarm_en = TIMER_ALARM_EN; + config.intr_type = TIMER_INTR_MAX; + config.auto_reload = (timer_autoreload_t) 1; // fix for ¬invalid conversion from 'int' to 'timer_autoreload_t'¬ thanks rudi ;-) + #elif defined ESP32C3 + timer_config_t config = + { + .clk_src = TIMER_SRC_CLK_XTAL, // TIMER_SRC_CLK_DEFAULT ? + .alarm_en = TIMER_ALARM_EN,//enable timer alarm + .counter_en = TIMER_PAUSE,//starts counting counter once timer_init called + .intr_type = TIMER_INTR_MAX, + .counter_dir = TIMER_COUNT_UP,//counts from 0 to counter value + .auto_reload = TIMER_AUTORELOAD_EN,// reloads counter automatically + .divider = TIMER_DIVIDER + }; + //#elif defined ESP32S2 + #else + #error "Invalid board" + #endif + + + Serial.println("Init timer"); timer_init(TIMER_GROUP_0, TIMER_0, &config); timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0x00000000ULL); timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, (double)TIMER_INTERVAL0_SEC * TIMER_SCALE); + Serial.println("Enable interrupt"); timer_enable_intr(TIMER_GROUP_0, TIMER_0); + Serial.println("Register ISR"); timer_isr_register(TIMER_GROUP_0, TIMER_0, timer_group0_isr, (void *) TIMER_0, ESP_INTR_FLAG_IRAM, NULL); + Serial.println("Start timer"); timer_start(TIMER_GROUP_0, TIMER_0); inited = true; diff --git a/src/log.txt b/src/log.txt new file mode 100644 index 0000000..e5f0f05 --- /dev/null +++ b/src/log.txt @@ -0,0 +1,290 @@ +M5Stack Core ESP32 + +12:41:28.386 -> USB Soft Host Test for M5Stack Gray 12:43:13.187 -> USB Soft Host Test for ESP32 S2 Dev module +12:41:28.386 -> TIMER_BASE_CLK: 80000000, TIMER_DIVIDER:2, TIMER_SCALE: 40000000 12:43:13.187 -> TIMER_BASE_CLK: 80000000, TIMER_DIVIDER:2, TIMER_SCALE: 40000000 +12:41:29.414 -> Attaching onDetectCB 12:43:14.181 -> Using core0 +12:41:29.414 -> Attaching onDataCB 12:43:14.181 -> Attaching onDetectCB +12:41:29.414 -> Attaching onUSBMessageDecode 12:43:14.181 -> Attaching onDataCB +12:41:29.414 -> Attaching onTickCB 12:43:14.181 -> Attaching onUSBMessageDecode +12:41:29.414 -> Creating message queue 12:43:14.181 -> Attaching onTickCB +12:41:29.414 -> Setting USB Delay 12:43:14.181 -> Creating message queue +12:41:29.414 -> Setting delay to 4 ticks 12:43:14.181 -> Setting USB Delay +12:41:29.414 -> Free iram before alloc: 196540 12:43:14.181 -> Setting delay to 4 ticks +12:41:29.414 -> Malloc MAX_DELAY_CODE_SIZE=640 12:43:14.181 -> Free iram before alloc: 221736 +12:41:29.414 -> Making xtensa Opcodes for ESP32/ESP32S2 12:43:14.181 -> Malloc MAX_DELAY_CODE_SIZE=640 +12:41:29.447 -> moving opecodes to executable memory segment 12:43:14.214 -> Making xtensa Opcodes for ESP32/ESP32S2 +12:41:29.447 -> Free iram after alloc and before realloc: 196540 12:43:14.214 -> moving opecodes to executable memory segment +12:41:29.447 -> Free iram after realloc: 195884 12:43:14.214 -> Free iram after alloc and before realloc: 221080 +12:41:29.447 -> Setting up pins 12:43:14.214 -> Free iram after realloc: 221080 +12:41:29.447 -> USB#0 (pins 16 17) is OK! 12:43:14.214 -> Setting up pins +12:41:29.447 -> READ_BOTH_PINS = 0000 12:43:14.214 -> USB#0 (pins 19 20) is OK! +12:41:29.447 -> READ_BOTH_PINS = 0000 12:43:14.214 -> READ_BOTH_PINS = 0000 +12:41:29.447 -> READ_BOTH_PINS = 0000 12:43:14.214 -> READ_BOTH_PINS = 0000 +12:41:29.447 -> READ_BOTH_PINS = 0000 12:43:14.214 -> READ_BOTH_PINS = 0000 +12:41:29.447 -> cpu freq = 240 MHz 12:43:14.214 -> READ_BOTH_PINS = 0000 +12:41:29.447 -> TIME_MULT = 51 12:43:14.214 -> cpu freq = 240 MHz +12:41:29.447 -> D= 0 Setting delay to 0 ticks 12:43:14.214 -> TIME_MULT = 51 +12:41:29.447 -> Free iram before alloc: 195884 12:43:14.248 -> D= 0 Setting delay to 0 ticks +12:41:29.447 -> Realloc MAX_DELAY_CODE_SIZE=640 12:43:14.248 -> Free iram before alloc: 221080 +12:41:29.447 -> Making xtensa Opcodes for ESP32/ESP32S2 12:43:14.248 -> Realloc MAX_DELAY_CODE_SIZE=640 +12:41:29.447 -> moving opecodes to executable memory segment 12:43:14.248 -> Making xtensa Opcodes for ESP32/ESP32S2 +12:41:29.447 -> Free iram after alloc and before realloc: 196540 12:43:14.248 -> moving opecodes to executable memory segment +12:41:29.480 -> Free iram after realloc: 195884 12:43:14.248 -> Free iram after alloc and before realloc: 221080 +12:41:29.480 -> 4800 bits in 1252.000000 uSec 3.833866 MHz 6 ticks in 1.565000 uS 12:43:14.248 -> Free iram after realloc: 221080 +12:41:29.480 -> D= 127 Setting delay to 127 ticks 12:43:14.248 -> Guru Meditation Error: Core 0 panic'ed (Cache disabled but cached memory region accessed). +12:41:29.480 -> Free iram before alloc: 195884 12:43:14.248 -> MMU entry fault error occurred while accessing the address 0x403c5810 (invalid mmu entry) +12:41:29.480 -> Realloc MAX_DELAY_CODE_SIZE=640 12:43:14.383 -> +12:41:29.480 -> Making xtensa Opcodes for ESP32/ESP32S2 12:43:14.383 -> Core 0 register dump: +12:41:29.513 -> moving opecodes to executable memory segment 12:43:14.383 -> PC : 0x40024340 PS : 0x00060f34 A0 : 0x800829c0 A1 : 0x3ffff000 +12:41:29.513 -> Free iram after alloc and before realloc: 196540 12:43:14.383 -> A2 : 0x3f004064 A3 : 0x00000000 A4 : 0x3f404000 A5 : 0x3ffc2e48 +12:41:29.513 -> Free iram after realloc: 195884 12:43:14.383 -> A6 : 0x3ffc1a48 A7 : 0x3ffc3084 A8 : 0x80081b54 A9 : 0x0e2 +12:41:29.513 -> 4800 bits in 3804.000000 uSec 1.261830 MHz 6 ticks in 4.755000 uS +12:41:29.513 -> D= 63 Setting delay to 63 ticks +12:41:29.513 -> Free iram before alloc: 195884 +12:41:29.513 -> Realloc MAX_DELAY_CODE_SIZE=640 +12:41:29.513 -> Making xtensa Opcodes for ESP32/ESP32S2 +12:41:29.513 -> moving opecodes to executable memory segment +12:41:29.513 -> Free iram after alloc and before realloc: 196540 +12:41:29.513 -> Free iram after realloc: 195884 +12:41:29.513 -> 4800 bits in 2508.000000 uSec 1.913876 MHz 6 ticks in 3.135000 uS +12:41:29.546 -> D= 95 Setting delay to 95 ticks +12:41:29.546 -> Free iram before alloc: 195884 +12:41:29.546 -> Realloc MAX_DELAY_CODE_SIZE=640 +12:41:29.546 -> Making xtensa Opcodes for ESP32/ESP32S2 +12:41:29.546 -> moving opecodes to executable memory segment +12:41:29.546 -> Free iram after alloc and before realloc: 196540 +12:41:29.579 -> Free iram after realloc: 195884 +12:41:29.579 -> 4800 bits in 3156.000000 uSec 1.520913 MHz 6 ticks in 3.945000 uS +12:41:29.579 -> D= 111 Setting delay to 111 ticks +12:41:29.579 -> Free iram before alloc: 195884 +12:41:29.579 -> Realloc MAX_DELAY_CODE_SIZE=640 +12:41:29.579 -> Making xtensa Opcodes for ESP32/ESP32S2 +12:41:29.579 -> moving opecodes to executable memory segment +12:41:29.579 -> Free iram after alloc and before realloc: 196540 +12:41:29.579 -> Free iram after realloc: 195884 +12:41:29.579 -> 4800 bits in 3484.000000 uSec 1.377727 MHz 6 ticks in 4.355000 uS +12:41:29.579 -> D= 103 Setting delay to 103 ticks +12:41:29.579 -> Free iram before alloc: 195884 +12:41:29.659 -> Realloc MAX_DELAY_CODE_SIZE=640 +12:41:29.659 -> Making xtensa Opcodes for ESP32/ESP32S2 +12:41:29.659 -> moving opecodes to executable memory segment +12:41:29.659 -> Free iram after alloc and before realloc: 196540 +12:41:29.659 -> Free iram after realloc: 195884 +12:41:29.659 -> 4800 bits in 3316.000000 uSec 1.447527 MHz 6 ticks in 4.145000 uS +12:41:29.659 -> D= 99 Setting delay to 99 ticks +12:41:29.659 -> Free iram before alloc: 195884 +12:41:29.659 -> Realloc MAX_DELAY_CODE_SIZE=640 +12:41:29.659 -> Making xtensa Opcodes for ESP32/ESP32S2 +12:41:29.659 -> moving opecodes to executable memory segment +12:41:29.659 -> Free iram after alloc and before realloc: 196540 +12:41:29.659 -> Free iram after realloc: 195884 +12:41:29.659 -> 4800 bits in 3236.000000 uSec 1.483313 MHz 6 ticks in 4.045000 uS +12:41:29.659 -> D= 97 Setting delay to 97 ticks +12:41:29.659 -> Free iram before alloc: 195884 +12:41:29.659 -> Realloc MAX_DELAY_CODE_SIZE=640 +12:41:29.659 -> Making xtensa Opcodes for ESP32/ESP32S2 +12:41:29.659 -> moving opecodes to executable memory segment +12:41:29.678 -> Free iram after alloc and before realloc: 196540 +12:41:29.678 -> Free iram after realloc: 195884 +12:41:29.678 -> 4800 bits in 3196.000000 uSec 1.501877 MHz 6 ticks in 3.995000 uS +12:41:29.678 -> D= 98 Setting delay to 98 ticks +12:41:29.678 -> Free iram before alloc: 195884 +12:41:29.712 -> Realloc MAX_DELAY_CODE_SIZE=640 +12:41:29.712 -> Making xtensa Opcodes for ESP32/ESP32S2 +12:41:29.712 -> moving opecodes to executable memory segment +12:41:29.712 -> Free iram after alloc and before realloc: 196540 +12:41:29.712 -> Free iram after realloc: 195884 +12:41:29.712 -> 4800 bits in 3217.000000 uSec 1.492073 MHz 6 ticks in 4.021250 uS +12:41:29.712 -> D= 97 Setting delay to 97 ticks +12:41:29.712 -> Free iram before alloc: 195884 +12:41:29.712 -> Realloc MAX_DELAY_CODE_SIZE=640 +12:41:29.712 -> Making xtensa Opcodes for ESP32/ESP32S2 +12:41:29.712 -> moving opecodes to executable memory segment +12:41:29.712 -> Free iram after alloc and before realloc: 196540 +12:41:29.712 -> Free iram after realloc: 195884 +12:41:29.745 -> 4800 bits in 3196.000000 uSec 1.501877 MHz 6 ticks in 3.995000 uS +12:41:29.745 -> Setting delay to 99 ticks +12:41:29.745 -> Free iram before alloc: 195884 +12:41:29.745 -> Realloc MAX_DELAY_CODE_SIZE=640 +12:41:29.745 -> Making xtensa Opcodes for ESP32/ESP32S2 +12:41:29.745 -> moving opecodes to executable memory segment +12:41:29.778 -> Free iram after alloc and before realloc: 196540 +12:41:29.778 -> Free iram after realloc: 195884 +12:41:29.778 -> TRANSMIT_TIME_DELAY = 99 time = 3.995000 error = -0.125003% +12:41:29.778 -> Diff not in [1-7] range: 0 +12:41:29.778 -> USB#1 is disabled by user configuration +12:41:29.778 -> Diff not in [1-7] range: 0 +12:41:29.778 -> USB#2 is disabled by user configuration +12:41:29.778 -> Diff not in [1-7] range: 0 +12:41:29.778 -> USB#3 is disabled by user configuration +12:41:29.778 -> Seleting SCL (blink) Pin #22 +12:41:29.778 -> Creating timer config +12:41:29.778 -> Init timer +12:41:29.778 -> Enable interrupt +12:41:29.778 -> Register ISR +12:41:29.778 -> Start timer +12:41:29.778 -> Attaching Timer Task +12:41:29.778 -> USB Soft Host Group timer task is now running on core #1 with priority 5 + + + + +13:39:58.995 -> USB Soft Host Test for ESP32 S2 Dev module +13:39:58.995 -> TIMER_BASE_CLK: 80000000, TIMER_DIVIDER:2, TIMER_SCALE: 40000000 +13:39:59.992 -> Testing capabilities allocator... +13:39:59.992 -> Free 8bit-capable memory (start): 226860K, 32-bit capable memory 226860K +13:40:00.026 -> Allocating 10K of 8-bit capable RAM +13:40:00.026 -> --> 0x3ffc72c8 +13:40:00.026 -> Free 8bit-capable memory (both reduced): 216604K, 32-bit capable memory 216604K +13:40:00.026 -> This platform has no 32-bit only capable RAM, jumping to next test +13:40:00.026 -> Allocating impossible caps +13:40:00.026 -> --> 0x0 +13:40:00.026 -> This platform has no IRAM-only so changeover will never occur, jumping to next test +13:40:00.059 -> Test if allocating executable code still gives IRAM, even with dedicated IRAM region depleted +13:40:00.059 -> --> 0x400372cc +13:40:00.059 -> Done. +13:40:00.059 -> heap_caps metadata test +13:40:00.059 -> Heap summary for capabilities 0x00000004: +13:40:00.059 -> At 0x3ffc33c8 len 232504 free 221112 allocated 8436 min_free 210852 +13:40:00.059 -> largest_free_block 212980 alloc_blocks 33 free_blocks 2 total_blocks 35 +13:40:00.059 -> At 0x3fffc000 len 14864 free 0 allocated 11836 min_free 0 +13:40:00.092 -> largest_free_block 0 alloc_blocks 38 free_blocks 0 total_blocks 38 +13:40:00.092 -> At 0x3ff9e000 len 8176 free 5748 allocated 0 min_free 5748 +13:40:00.092 -> largest_free_block 5620 alloc_blocks 0 free_blocks 1 total_blocks 1 +13:40:00.092 -> Totals: +13:40:00.092 -> free 226860 allocated 20272 min_free 216600 largest_free_block 212980 +13:40:00.092 -> After allocating 212980 bytes: +13:40:00.092 -> Heap summary for capabilities 0x00000004: +13:40:00.125 -> At 0x3ffc33c8 len 232504 free 8116 allocated 221416 min_free 8116 +13:40:00.125 -> largest_free_block 4596 alloc_blocks 34 free_blocks 2 total_blocks 36 +13:40:00.125 -> At 0x3fffc000 len 14864 free 0 allocated 11836 min_free 0 +13:40:00.125 -> largest_free_block 0 alloc_blocks 38 free_blocks 0 total_blocks 38 +13:40:00.125 -> At 0x3ff9e000 len 8176 free 5748 allocated 0 min_free 5748 +13:40:00.158 -> largest_free_block 5620 alloc_blocks 0 free_blocks 1 total_blocks 1 +13:40:00.158 -> Totals: +13:40:00.158 -> free 13864 allocated 233252 min_free 13864 largest_free_block 5620 +13:40:00.158 -> +13:40:00.158 -> +13:40:00.158 -> After test, heap status: +13:40:00.158 -> Heap summary for capabilities 0x00000004: +13:40:00.158 -> At 0x3ffc33c8 len 232504 free 221112 allocated 8436 min_free 8116 +13:40:00.158 -> largest_free_block 212980 alloc_blocks 33 free_blocks 2 total_blocks 35 +13:40:00.191 -> At 0x3fffc000 len 14864 free 0 allocated 11836 min_free 0 +13:40:00.191 -> largest_free_block 0 alloc_blocks 38 free_blocks 0 total_blocks 38 +13:40:00.191 -> At 0x3ff9e000 len 8176 free 5748 allocated 0 min_free 5748 +13:40:00.191 -> largest_free_block 5620 alloc_blocks 0 free_blocks 1 total_blocks 1 +13:40:00.191 -> Totals: +13:40:00.191 -> free 226860 allocated 20272 min_free 13864 largest_free_block 212980 +13:40:00.191 -> heap_caps_malloc was called but failed to allocate 134217728 bytes with 0x1000 capabilities. +13:40:00.191 -> heap_caps_realloc was called but failed to allocate 134217728 bytes with 0x1000 capabilities. +13:40:00.191 -> heap_caps_aligned_alloc was called but failed to allocate 134217728 bytes with 0x1000 capabilities. +13:40:00.224 -> heap_caps_malloc was called but failed to allocate 64 bytes with 0x80000000 capabilities. +13:40:00.224 -> heap_caps_realloc was called but failed to allocate 64 bytes with 0x80000000 capabilities. +13:40:00.224 -> heap_caps_aligned_alloc was called but failed to allocate 64 bytes with 0x80000000 capabilities. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/usb_host.c b/src/usb_host.c index b3b8780..2bc06ad 100644 --- a/src/usb_host.c +++ b/src/usb_host.c @@ -33,6 +33,9 @@ Changes by tobozo (march 2021): - Arduino IDE compliance (mostly code regression to esp-idf 3.x) - Added callbacks (data and device detection) + Changes by tobozo (aug 2022): + - Quick & dirty cpuDelay() to enable ESP32-S2 support when CONFIG_ESP_SYSTEM_MEMPROT_FEATURE is enabled (default on Arduino IDE) + \*/ @@ -40,23 +43,24 @@ // Arduino IDE complains about volatile at init, but we don't care #pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" +#pragma GCC diagnostic ignored "-Wunused-variable" -#define T_START 0b00000001 -#define T_ACK 0b01001011 -#define T_NACK 0b01011010 -#define T_SOF 0b10100101 -#define T_SETUP 0b10110100 -#define T_DATA0 0b11000011 -#define T_DATA1 0b11010010 -#define T_DATA2 0b11100001 -#define T_OUT 0b10000111 -#define T_IN 0b10010110 +#define T_START 0b00000001 +#define T_ACK 0b01001011 +#define T_NACK 0b01011010 +#define T_SOF 0b10100101 +#define T_SETUP 0b10110100 +#define T_DATA0 0b11000011 +#define T_DATA1 0b11010010 +#define T_DATA2 0b11100001 +#define T_OUT 0b10000111 +#define T_IN 0b10010110 -#define T_ERR 0b00111100 -#define T_PRE 0b00111100 -#define T_NYET 0b01101001 -#define T_STALL 0b01111000 +#define T_ERR 0b00111100 +#define T_PRE 0b00111100 +#define T_NYET 0b01101001 +#define T_STALL 0b01111000 // local non std #define T_NEED_ACK 0b01111011 @@ -74,8 +78,6 @@ #define SMALL_NO_DATA 36 - - int TRANSMIT_TIME_DELAY = 110; //delay each bit transmit int TIME_MULT = 25; //received time factor delta clocks* TIME_MULT/TIME_SCALE int TM_OUT = 64; //receive time out no activity on bus @@ -88,12 +90,12 @@ int TM_OUT = 64; //receive time out no activity on bus #define TOUT (TM_OUT) #endif -static uint32_t _getCycleCount32() +uint32_t _getCycleCount32() { uint32_t ccount = cpu_hal_get_cycle_count(); return ccount; } -static uint8_t _getCycleCount8d8(void) +uint8_t _getCycleCount8d8(void) { uint32_t ccount = cpu_hal_get_cycle_count(); return ccount>>3; @@ -103,7 +105,7 @@ static uint8_t _getCycleCount8d8(void) #define SE_J { *snd[1][0] = (1 << DM_PIN);*snd[1][1] = (1 << DP_PIN); } #define SE_0 { *snd[2][0] = (1 << DM_PIN);*snd[2][1] = (1 << DP_PIN); } -#if CONFIG_IDF_TARGET_ESP32 +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 #define SET_I { PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[DP_PIN]); PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[DM_PIN]); GPIO.enable_w1tc = (1 << DP_PIN) | (1 << DM_PIN); } #define SET_O { GPIO.enable_w1ts = (1 << DP_PIN) | (1 << DM_PIN); PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[DP_PIN]); PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[DM_PIN]); } #define READ_BOTH_PINS (((GPIO.in&RD_MASK)<<8)>>RD_SHIFT) @@ -114,7 +116,7 @@ static uint8_t _getCycleCount8d8(void) {&GPIO.out_w1tc,&GPIO.out_w1tc}, {&GPIO.out_w1tc,&GPIO.out_w1tc} } ; -#else +#else // ESP32C3 #define SET_I { PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[DP_PIN]); PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[DM_PIN]); gpio_ll_output_disable(&GPIO,DM_PIN); gpio_ll_output_disable(&GPIO,DP_PIN);} #define SET_O { GPIO.enable_w1ts.val = (1 << DP_PIN) | (1 << DM_PIN); PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[DP_PIN]); PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[DM_PIN]); } #define READ_BOTH_PINS (((GPIO.in.val&RD_MASK)<<8)>>RD_SHIFT) @@ -127,7 +129,7 @@ static uint8_t _getCycleCount8d8(void) } ; #endif -//must be setup ech time with setPins +//must be setup each time with setPins uint32_t DP_PIN; uint32_t DM_PIN; @@ -137,7 +139,7 @@ uint16_t M_ONE; uint16_t P_ONE; uint32_t RD_MASK; uint32_t RD_SHIFT; -//end must be setup ech time with setPins +//end must be setup each time with setPins // temporary used insize lowlevel volatile uint8_t received_NRZI_buffer_bytesCnt; @@ -157,38 +159,72 @@ uint8_t decoded_receive_buffer[DEF_BUFF_SIZE]; void (*delay_pntA)() = NULL; -#define cpuDelay(x) {(*delay_pntA)();} -#if CONFIG_IDF_TARGET_ESP32 - #define MAX_DELAY_CODE_SIZE 0x280 - #define SDELAYMALLOC(X) malloc(X) - #define SDELAYREALLOC(X,Y,Z) heap_caps_realloc(X,Y,Z) - #define SDELAYRMASK MALLOC_CAP_EXEC - void makeOpcodes( uint8_t* ptr, uint8_t ticks ) - { - //put head of delay procedure - *ptr++ = 0x36; - *ptr++ = 0x41; - *ptr++ = 0; - for(int k=0;k 0 ) { + while( cycles_count-->1 ) NOP(); + } + } + + void makeOpcodes( uint8_t* ptr, uint8_t ticks ) + { + // TODO: detect CONFIG_ESP_SYSTEM_MEMPROT_FEATURE and create opcodes + } + + + //#define WR_SIMULTA + #define MAX_DELAY_CODE_SIZE 0x280 + #define SDELAYMALLOC(X) heap_caps_malloc(X,MALLOC_CAP_32BIT); + #define SDELAYREALLOC(X,Y,Z) heap_caps_realloc(X,Y,Z) + #define SDELAYRMASK MALLOC_CAP_EXEC + #endif + + #else // ESP32-C3 + #define cpuDelay(x) {(*delay_pntA)();} #define MAX_DELAY_CODE_SIZE 0x210 - #define SDELAYMALLOC(X) heap_caps_aligned_alloc(X,MAX_DELAY_CODE_SIZE, MALLOC_CAP_8BIT); + #define SDELAYMALLOC(X) malloc(X) #define SDELAYREALLOC(X,Y,Z) heap_caps_realloc(X,Y,Z) - #define SDELAYRMASK MALLOC_CAP_32BIT | MALLOC_CAP_EXEC + #define SDELAYRMASK MALLOC_CAP_32BIT|MALLOC_CAP_EXEC void makeOpcodes( uint8_t* ptr, uint8_t ticks ) { + printf("Making RISCV Opcodes for ESP32C3\n"); //put head of delay procedure for(int k=0;k ESP System Setting -> Memory protectiom-> Disable.\n memory prot must be disabled!!!\n delay_pntA = %p,\nHalting...\n",delay_pntA); while(1) { vTaskDelay(1); } @@ -338,9 +400,6 @@ void parseImmed(sUsbContStruct * pcurrent) static int sIntfCount = 0; static int hidCount = 0; int pos = 0; - #define STDCLASS 0x00 - #define HIDCLASS 0x03 - #define HUBCLASS 0x09 /* bDeviceClass, bInterfaceClass */ pcurrent->epCount = 0; @@ -660,10 +719,10 @@ void sendOnly() SET_O; #ifdef WR_SIMULTA uint32_t out_base = GPIO.out; - sndA[0] = (out_base | DP) &~DM; - sndA[1] = (out_base | DM) &~DP; - sndA[2] = (out_base )&~(DP | DM); - sndA[3] = out_base | (DM | DP); + sndA[0] = (out_base | DP_PIN_M) &~DM_PIN_M; + sndA[1] = (out_base | DM_PIN_M) &~DP_PIN_M; + sndA[2] = (out_base )&~(DP_PIN_M | DM_PIN_M); + sndA[3] = out_base | (DM_PIN_M | DP_PIN_M); #endif for(k=0;k7||diff==0) { + printf("Diff not in [1-7] range: %d\n", diff ); + return 0; + } + + if( dp<8 || dp>31) { + printf("Dp not in [8-31] range: [%d]\n", dp ); + return 0; + } + if( dm<8 || dm>31) { + printf("Dm not in [8-31] range: [%d]\n", dp ); return 0; } - if( dp<8 || dp>31) return 0; - if( dm<8 || dm>31) return 0; return 1; } @@ -1428,7 +1495,7 @@ void initStates(int DP0,int DM0,int DP1,int DM1,int DP2,int DM2,int DP3,int DM3) TIME_MULT = (int)(TIME_SCALE/(out_config.freq_mhz/8/1.5)+0.5); printf("TIME_MULT = %d \n",TIME_MULT); - int TRANSMIT_TIME_DELAY_OPT = 0; + int TRANSMIT_TIME_DELAY_OPT = 0; TRANSMIT_TIME_DELAY = TRANSMIT_TIME_DELAY_OPT; printf("D=%4d ",TRANSMIT_TIME_DELAY); setDelay(TRANSMIT_TIME_DELAY); @@ -1451,7 +1518,7 @@ void initStates(int DP0,int DM0,int DP1,int DM1,int DP2,int DM2,int DP3,int DM3) } TRANSMIT_TIME_DELAY = TRANSMIT_TIME_DELAY_OPT+DELAY_CORR; setDelay(TRANSMIT_TIME_DELAY); - printf("TRANSMIT_TIME_DELAY = %d time = %f error = %f%% \n",TRANSMIT_TIME_DELAY,cS_opt,(cS_opt-OPT_TIME)/OPT_TIME*100); + printf("TRANSMIT_TIME_DELAY = %d time = %f error = %f%% \n", TRANSMIT_TIME_DELAY, cS_opt, (cS_opt-OPT_TIME)/OPT_TIME*100 ); } } else { if( current->DP == -1 && current->DM == -1 ) { @@ -1486,7 +1553,7 @@ uint8_t usbGetFlags(int _usb_num) void usb_process() { - #if CONFIG_IDF_TARGET_ESP32C3 || defined ESP32C3 + #if CONFIG_IDF_TARGET_ESP32C3 || defined ESP32C3 //|| defined ESP32S2 || defined CONFIG_IDF_TARGET_ESP32 cpu_ll_enable_cycle_count(); #endif for(int k=0;kepCount,pcurrent->selfNum); #endif diff --git a/src/usb_host.h b/src/usb_host.h index ce6cded..dbca30a 100644 --- a/src/usb_host.h +++ b/src/usb_host.h @@ -20,14 +20,26 @@ #warning "Using software group timers" #endif +#if defined CONFIG_ESP_SYSTEM_MEMPROT_FEATURE && !defined CONFIG_IDF_TARGET_ESP32S2 + #error "memory prot must be disabled!!!" +#endif + + #define TIMER_DIVIDER 2 // Hardware timer clock divider #define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // convert counter value to seconds #define TIMER_INTERVAL0_SEC (0.001) // sample test interval for the first timer // non configured device - must be zero -#define ZERO_USB_ADDRESS 0 +#define ZERO_USB_ADDRESS 0 // any number less 127, but no zero -#define ASSIGNED_USB_ADDRESS 3 +#define ASSIGNED_USB_ADDRESS 3 +// usb ports in this hub +#define NUM_USB 4 + +#define STDCLASS 0x00 +#define HIDCLASS 0x03 +#define HUBCLASS 0x09 /* bDeviceClass, bInterfaceClass */ + void IRAM_ATTR printState(); void IRAM_ATTR usb_process(); @@ -40,7 +52,7 @@ void set_ondetect_cb( ondetectcb_t onDetectCB ); typedef void(*onledblinkcb_t)(int on_off); void set_onled_blink_cb( onledblinkcb_t cb ); -#define NUM_USB 4 + void initStates( int DP0,int DM0,int DP1,int DM1,int DP2,int DM2,int DP3,int DM3); void setDelay(uint8_t ticks); @@ -131,52 +143,4 @@ typedef struct } sStrDesc; - - -#if !defined USE_NATIVE_GROUP_TIMERS - typedef struct - { - int type; // the type of timer's event - int timer_group; - int timer_idx; - uint64_t timer_counter_value; - } timer_event_t; -#endif - -static xQueueHandle timer_queue = NULL; - -static void IRAM_ATTR timer_group0_isr(void *para) -{ - #if defined USE_NATIVE_GROUP_TIMERS - timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0); - //taskENTER_CRITICAL(); - usb_process(); - //taskEXIT_CRITICAL(); - timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_0); - #else - // this is mainly a group-timer layer for esp-idf 3.x - // most of this is handled by the SDK since esp-idf 4.x - int timer_idx = (int) para; - uint32_t intr_status = TIMERG0.int_st_timers.val;// Retrieve the interrupt status and the counter value from the timer that reported the interrupt - TIMERG0.hw_timer[timer_idx].update = 1; - uint64_t timer_counter_value = ((uint64_t) TIMERG0.hw_timer[timer_idx].cnt_high) << 32 | TIMERG0.hw_timer[timer_idx].cnt_low; - timer_event_t evt; // Prepare basic event data that will be then sent back to the main program task - evt.timer_group = 0; - evt.timer_idx = timer_idx; - evt.timer_counter_value = timer_counter_value; - usb_process();// process USB signal - if ((intr_status & BIT(timer_idx)) && timer_idx == TIMER_0) { // Clear the interrupt and update the alarm time for the timer with without reload - evt.type = 1; // no reload - TIMERG0.int_clr_timers.t0 = 1; - timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE); - TIMERG0.hw_timer[timer_idx].alarm_high = (uint32_t) (timer_counter_value >> 32); - TIMERG0.hw_timer[timer_idx].alarm_low = (uint32_t) timer_counter_value; - } - TIMERG0.hw_timer[timer_idx].config.alarm_en = TIMER_ALARM_EN; // After the alarm has been triggered we need enable it again, so it is triggered the next time - xQueueSendFromISR(timer_queue, &evt, NULL); // Now just send the event data back to the main program task - #endif -} - - - #endif