From 8c2ee3435eeb77202bd70255f38965db4df2618b Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Mon, 19 Aug 2024 14:52:37 +0300 Subject: [PATCH 01/38] fix(build): Changes required to build against IDF v5.3 --- configs/builds.json | 3 +-- tools/config.sh | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/configs/builds.json b/configs/builds.json index e34813cfa..9b7c57e11 100644 --- a/configs/builds.json +++ b/configs/builds.json @@ -143,8 +143,7 @@ ["qio","80m","opi_ram"], ["dio","80m","qio_ram"], ["dio","80m","opi_ram"], - ["opi","80m","opi_ram"], - ["opi","80m","qio_ram"] + ["opi","80m","opi_ram"] ] } ] diff --git a/tools/config.sh b/tools/config.sh index b05a879b2..27de8a913 100755 --- a/tools/config.sh +++ b/tools/config.sh @@ -6,11 +6,11 @@ if [ -z $IDF_PATH ]; then fi if [ -z $IDF_BRANCH ]; then - IDF_BRANCH="release/v5.1" + IDF_BRANCH="release/v5.3" fi if [ -z $AR_PR_TARGET_BRANCH ]; then - AR_PR_TARGET_BRANCH="master" + AR_PR_TARGET_BRANCH="release/v3.1.x" fi if [ -z $IDF_TARGET ]; then From dda397c697825a22d7de3d1aad3acbcde3c08fa7 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Mon, 19 Aug 2024 15:49:11 +0300 Subject: [PATCH 02/38] Use unified Xtensa toolchain --- tools/gen_tools_json.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gen_tools_json.py b/tools/gen_tools_json.py index f0fc67579..392eed508 100644 --- a/tools/gen_tools_json.py +++ b/tools/gen_tools_json.py @@ -107,7 +107,7 @@ def replace_if_xz(system): out_path = args.out_path; # settings - arduino_tools = ["xtensa-esp32-elf","xtensa-esp32s2-elf","xtensa-esp32s3-elf","xtensa-esp-elf-gdb","riscv32-esp-elf","riscv32-esp-elf-gdb","openocd-esp32"] + arduino_tools = ["xtensa-esp-elf","xtensa-esp-elf-gdb","riscv32-esp-elf","riscv32-esp-elf-gdb","openocd-esp32"] # code start farray = {"packages":[{"platforms":[{"toolsDependencies":[]}],"tools":[]}]} From 807bddb55760af5a1ada0c735d561a4c925ba702 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 20 Aug 2024 13:04:45 +0300 Subject: [PATCH 03/38] add(build): Add initial ESP32-P4 skeleton Chip is not selected by default and has only one memory and bootloader configuration. This is the minimum required to issue `build.sh -t esp32p4` which will currently fail, because Arduino support is not yet ready --- configs/builds.json | 10 ++++++++++ configs/defconfig.esp32p4 | 0 2 files changed, 10 insertions(+) create mode 100644 configs/defconfig.esp32p4 diff --git a/configs/builds.json b/configs/builds.json index 9b7c57e11..bbdea49e0 100644 --- a/configs/builds.json +++ b/configs/builds.json @@ -44,6 +44,16 @@ } ], "targets":[ + { + "target": "esp32p4", + "skip": 1, + "features":[], + "idf_libs":["qio","80m"], + "bootloaders":[ + ["qio","80m"] + ], + "mem_variants":[] + }, { "target": "esp32c2", "skip": 1, diff --git a/configs/defconfig.esp32p4 b/configs/defconfig.esp32p4 new file mode 100644 index 000000000..e69de29bb From fd5570812bb1cddb2979317f662a5cc8a0504e54 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Tue, 24 Sep 2024 11:30:43 -0300 Subject: [PATCH 04/38] feat(esp32p4): Build libs for ESP32-P4 (#221) * feat(esp32p4): Build libs for ESP32-P4 * Add target to workflows * Enable in builds * Remove bluedroid patch * Add P4 to libspi * Add P4 mem variants --- .github/workflows/cron.yml | 2 +- .github/workflows/push.yml | 2 +- configs/builds.json | 12 +++++++---- main/idf_component.yml | 2 +- patches/esp32c6_provisioning_bluedroid.diff | 12 ----------- patches/mmu_map.diff | 24 --------------------- tools/install-esp-idf.sh | 2 -- 7 files changed, 11 insertions(+), 45 deletions(-) delete mode 100644 patches/esp32c6_provisioning_bluedroid.diff delete mode 100644 patches/mmu_map.diff diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index f2053b3ad..ed2522f54 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -36,4 +36,4 @@ jobs: targets: "esp32,esp32s2,esp32s3,esp32c3,esp32c6,esp32h2" - idf_branch: "release/v5.3" lib_builder_branch: "release/v5.3" - targets: "esp32,esp32s2,esp32s3,esp32c3,esp32c6,esp32h2" + targets: "esp32,esp32s2,esp32s3,esp32c3,esp32c6,esp32h2,esp32p4" diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 649c84c81..95610c403 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - target: [esp32, esp32s2, esp32s3, esp32c2, esp32c3, esp32c6, esp32h2] + target: [esp32, esp32s2, esp32s3, esp32c2, esp32c3, esp32c6, esp32h2, esp32p4] fail-fast: false steps: - uses: actions/checkout@v4 diff --git a/configs/builds.json b/configs/builds.json index bbdea49e0..e4b3ec7c0 100644 --- a/configs/builds.json +++ b/configs/builds.json @@ -4,7 +4,7 @@ "file":"libspi_flash.a", "src":"build/esp-idf/spi_flash/libspi_flash.a", "out":"lib/libspi_flash.a", - "targets":["esp32","esp32c2","esp32c3","esp32s2","esp32s3","esp32c6","esp32h2"] + "targets":["esp32","esp32c2","esp32c3","esp32s2","esp32s3","esp32c6","esp32h2","esp32p4"] }, { "file":"libesp_psram.a", @@ -46,13 +46,17 @@ "targets":[ { "target": "esp32p4", - "skip": 1, "features":[], "idf_libs":["qio","80m"], "bootloaders":[ - ["qio","80m"] + ["qio","80m"], + ["dio","80m"], + ["qio","40m"], + ["dio","40m"] ], - "mem_variants":[] + "mem_variants":[ + ["dio","80m"] + ] }, { "target": "esp32c2", diff --git a/main/idf_component.yml b/main/idf_component.yml index 011906d27..beed56ed9 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -1,6 +1,6 @@ dependencies: # Required IDF version - idf: ">=5.1" + idf: ">=5.3" espressif/esp32-camera: version: "master" git: https://github.com/espressif/esp32-camera.git diff --git a/patches/esp32c6_provisioning_bluedroid.diff b/patches/esp32c6_provisioning_bluedroid.diff deleted file mode 100644 index 98371b8aa..000000000 --- a/patches/esp32c6_provisioning_bluedroid.diff +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/components/protocomm/src/simple_ble/simple_ble.c b/components/protocomm/src/simple_ble/simple_ble.c -index 8a4ae0f3d9..cd6421c6e5 100644 ---- a/components/protocomm/src/simple_ble/simple_ble.c -+++ b/components/protocomm/src/simple_ble/simple_ble.c -@@ -225,7 +225,7 @@ esp_err_t simple_ble_start(simple_ble_cfg_t *cfg) - #ifdef CONFIG_BTDM_CTRL_MODE_BTDM - ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM); --#elif defined CONFIG_BTDM_CTRL_MODE_BLE_ONLY || CONFIG_BT_CTRL_MODE_EFF -+#elif defined CONFIG_BTDM_CTRL_MODE_BLE_ONLY || CONFIG_BT_CTRL_MODE_EFF || CONFIG_IDF_TARGET_ESP32C6 - ret = esp_bt_controller_enable(ESP_BT_MODE_BLE); - #else - ESP_LOGE(TAG, "Configuration mismatch. Select BLE Only or BTDM mode from menuconfig"); diff --git a/patches/mmu_map.diff b/patches/mmu_map.diff deleted file mode 100644 index 3bf56005a..000000000 --- a/patches/mmu_map.diff +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/components/esp_mm/esp_mmu_map.c b/components/esp_mm/esp_mmu_map.c -index b7d927f8fe..6a8c4635f0 100644 ---- a/components/esp_mm/esp_mmu_map.c -+++ b/components/esp_mm/esp_mmu_map.c -@@ -315,6 +315,19 @@ esp_err_t esp_mmu_map_reserve_block_with_caps(size_t size, mmu_mem_caps_t caps, - s_mmu_ctx.mem_regions[found_region_id].max_slot_size -= aligned_size; - ESP_EARLY_LOGV(TAG, "found laddr is 0x%x", laddr); - -+ mem_block_t *mem_block = NULL; -+ mem_region_t *region = &s_mmu_ctx.mem_regions[found_region_id]; -+ TAILQ_FOREACH(mem_block, ®ion->mem_block_head, entries) { -+ if (mem_block == TAILQ_FIRST(®ion->mem_block_head) || mem_block == TAILQ_LAST(®ion->mem_block_head, mem_block_head_)) { -+ TAILQ_REMOVE(®ion->mem_block_head, mem_block, entries); -+ } else { -+ // probably the reservation of MMU region should be disallowed for this case - already some MMU mappings exist? -+ // assert/abort -+ ESP_EARLY_LOGE(TAG, "already some MMU mappings exist?"); -+ abort(); -+ } -+ } -+ - uint32_t vaddr = 0; - if (caps & MMU_MEM_CAP_EXEC) { - vaddr = mmu_ll_laddr_to_vaddr(laddr, MMU_VADDR_INSTRUCTION); diff --git a/tools/install-esp-idf.sh b/tools/install-esp-idf.sh index bd3d07985..0519ae67a 100755 --- a/tools/install-esp-idf.sh +++ b/tools/install-esp-idf.sh @@ -40,9 +40,7 @@ if [ ! -x $idf_was_installed ] || [ ! -x $commit_predefined ]; then # Temporarily patch the ESP32-S2 I2C LL driver to keep the clock source cd $IDF_PATH patch -p1 -N -i $AR_PATCHES/esp32s2_i2c_ll_master_init.diff - patch -p1 -N -i $AR_PATCHES/mmu_map.diff patch -p1 -N -i $AR_PATCHES/lwip_max_tcp_pcb.diff - patch -p1 -N -i $AR_PATCHES/esp32c6_provisioning_bluedroid.diff cd - fi From ce5121f7c243ed43f26370defc53fe332bd0fc67 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Tue, 24 Sep 2024 18:54:29 -0300 Subject: [PATCH 05/38] Update SDK in JSON even if version did not change (#223) --- tools/add_sdk_json.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/add_sdk_json.py b/tools/add_sdk_json.py index d2deb4a87..7b12289bb 100644 --- a/tools/add_sdk_json.py +++ b/tools/add_sdk_json.py @@ -66,7 +66,7 @@ def add_system(systems, host, url, filename, sha, size): dep_skip = False for dep in farray['packages'][0]['platforms'][0]['toolsDependencies']: if dep['name'] == tool_name: - if dep['version'] == tool_version: + if dep['version'] == tool_version and not tool_name.startswith('esp32-arduino-libs'): print('Skipping {0}. Same version {1}'.format(tool_name, tool_version)) dep_skip = True break From 6c219b1fb09bfc7a215a60050841f5cf21d207af Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Thu, 26 Sep 2024 11:00:44 +0300 Subject: [PATCH 06/38] Do not build matter for ESP32-P4 --- main/idf_component.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/idf_component.yml b/main/idf_component.yml index f8d65222d..38cc98fd5 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -26,7 +26,7 @@ dependencies: version: "^1.3.0" require: public rules: - - if: "target not in [esp32c2, esp32h2]" + - if: "target not in [esp32c2, esp32h2, esp32p4]" # esp-sr: "^1.3.1" # esp32-camera: "^2.0.4" From 956d601397357c9269526e0845bfe5eaef925153 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Mon, 30 Sep 2024 23:41:31 +0300 Subject: [PATCH 07/38] Update ESP-DL configuration --- main/idf_component.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/idf_component.yml b/main/idf_component.yml index 38cc98fd5..f6fd17088 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -15,9 +15,10 @@ dependencies: espressif/esp-dl: version: "master" git: https://github.com/espressif/esp-dl.git + path: esp-dl require: public rules: - - if: "target in [esp32s3, esp32s2, esp32]" + - if: "target in [esp32s3, esp32s2, esp32, esp32p4]" espressif/esp-sr: version: ">=1.4.2" rules: From d1253b5a8fb6e86de40b81abf8ff4eb48a291a6c Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 1 Oct 2024 00:20:51 +0300 Subject: [PATCH 08/38] Add additional DL models and use extra components only when needed --- build.sh | 10 +++++----- main/idf_component.yml | 23 ++++++++++++++++++++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/build.sh b/build.sh index 9bceda087..74751f54b 100755 --- a/build.sh +++ b/build.sh @@ -169,7 +169,7 @@ if [ "$BUILD_TYPE" != "all" ]; then echo "idf.py -DIDF_TARGET=\"$target\" -DSDKCONFIG_DEFAULTS=\"$configs\" $BUILD_TYPE" rm -rf build sdkconfig - idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$configs" $BUILD_TYPE + COMPONENTS_SUBSET=full idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$configs" $BUILD_TYPE if [ $? -ne 0 ]; then exit 1; fi done exit 0 @@ -223,11 +223,11 @@ for target_json in `jq -c '.targets[]' configs/builds.json`; do echo "* Build IDF-Libs: $idf_libs_configs" rm -rf build sdkconfig - idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$idf_libs_configs" idf-libs + COMPONENTS_SUBSET=full idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$idf_libs_configs" idf-libs if [ $? -ne 0 ]; then exit 1; fi if [ "$target" == "esp32s3" ]; then - idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$idf_libs_configs" srmodels_bin + COMPONENTS_SUBSET=full idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$idf_libs_configs" srmodels_bin if [ $? -ne 0 ]; then exit 1; fi AR_SDK="$AR_TOOLS/esp32-arduino-libs/$target" # sr model.bin @@ -248,7 +248,7 @@ for target_json in `jq -c '.targets[]' configs/builds.json`; do echo "* Build BootLoader: $bootloader_configs" rm -rf build sdkconfig - idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$bootloader_configs" copy-bootloader + COMPONENTS_SUBSET=none idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$bootloader_configs" copy-bootloader if [ $? -ne 0 ]; then exit 1; fi done @@ -261,7 +261,7 @@ for target_json in `jq -c '.targets[]' configs/builds.json`; do echo "* Build Memory Variant: $mem_configs" rm -rf build sdkconfig - idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$mem_configs" mem-variant + COMPONENTS_SUBSET=none idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$mem_configs" mem-variant if [ $? -ne 0 ]; then exit 1; fi done done diff --git a/main/idf_component.yml b/main/idf_component.yml index f6fd17088..4dece70c4 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -7,27 +7,48 @@ dependencies: require: public rules: - if: "target in [esp32, esp32s2, esp32s3]" + - if: "$COMPONENTS_SUBSET in [full, all]" espressif/esp-tflite-micro: version: ">=1.2.0" require: public rules: - if: "target not in [esp32c2]" + - if: "$COMPONENTS_SUBSET in [full, all]" espressif/esp-dl: version: "master" git: https://github.com/espressif/esp-dl.git path: esp-dl require: public rules: - - if: "target in [esp32s3, esp32s2, esp32, esp32p4]" + - if: "target in [esp32s3, esp32, esp32p4]" + - if: "$COMPONENTS_SUBSET in [full, all]" + espressif/human_face_detect: + version: "master" + git: https://github.com/espressif/esp-dl.git + path: models/human_face_detect + require: public + rules: + - if: "target in [esp32s3, esp32, esp32p4]" + - if: "$COMPONENTS_SUBSET in [full, all]" + espressif/pedestrian_detect: + version: "master" + git: https://github.com/espressif/esp-dl.git + path: models/pedestrian_detect + require: public + rules: + - if: "target in [esp32s3, esp32, esp32p4]" + - if: "$COMPONENTS_SUBSET in [full, all]" espressif/esp-sr: version: ">=1.4.2" rules: - if: "target in [esp32s3]" + - if: "$COMPONENTS_SUBSET in [full, all]" espressif/esp_matter: version: "^1.3.0" require: public rules: - if: "target not in [esp32c2, esp32h2, esp32p4]" + - if: "$COMPONENTS_SUBSET in [full, all]" # esp-sr: "^1.3.1" # esp32-camera: "^2.0.4" From cab451af61bfc7bc6e6a48b176a9017b3df7e9e4 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 1 Oct 2024 00:33:06 +0300 Subject: [PATCH 09/38] Use extra DL models only on S3 and P4 --- main/idf_component.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main/idf_component.yml b/main/idf_component.yml index 35e8d5c6c..6aebe4d94 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -15,7 +15,7 @@ dependencies: - if: "target not in [esp32c2]" - if: "$COMPONENTS_SUBSET in [full, all]" espressif/esp-dl: - version: "af7808ba09448ce82c704455975d4cf1e4305fd7" + version: "master" git: https://github.com/espressif/esp-dl.git path: esp-dl require: public @@ -28,7 +28,7 @@ dependencies: path: models/human_face_detect require: public rules: - - if: "target in [esp32s3, esp32, esp32p4]" + - if: "target in [esp32s3, esp32p4]" - if: "$COMPONENTS_SUBSET in [full, all]" espressif/pedestrian_detect: version: "master" @@ -36,7 +36,7 @@ dependencies: path: models/pedestrian_detect require: public rules: - - if: "target in [esp32s3, esp32, esp32p4]" + - if: "target in [esp32s3, esp32p4]" - if: "$COMPONENTS_SUBSET in [full, all]" espressif/esp-sr: version: ">=1.4.2" From e3d2928c813b9a47af2a5669ee4653bdfd2c9ba1 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 1 Oct 2024 00:58:07 +0300 Subject: [PATCH 10/38] Switch to the new ESP-DL only for ESP32-P4 --- main/idf_component.yml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/main/idf_component.yml b/main/idf_component.yml index 6aebe4d94..0a934f88b 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -14,29 +14,41 @@ dependencies: rules: - if: "target not in [esp32c2]" - if: "$COMPONENTS_SUBSET in [full, all]" + # ESP-DL for ESP32, ESP32S2 and ESP32-S3 espressif/esp-dl: + version: "master" + version: "af7808ba09448ce82c704455975d4cf1e4305fd7" + git: https://github.com/espressif/esp-dl.git + require: public + rules: + - if: "target in [esp32s3, esp32s2, esp32]" + - if: "$COMPONENTS_SUBSET in [full, all]" + # ESP-DL for ESP32-P4 + espressif/esp-dl2: version: "master" git: https://github.com/espressif/esp-dl.git path: esp-dl require: public rules: - - if: "target in [esp32s3, esp32, esp32p4]" + - if: "target in [esp32p4]" - if: "$COMPONENTS_SUBSET in [full, all]" + # ESP-DL Face Detection for ESP32-P4 espressif/human_face_detect: version: "master" git: https://github.com/espressif/esp-dl.git path: models/human_face_detect require: public rules: - - if: "target in [esp32s3, esp32p4]" + - if: "target in [esp32p4]" - if: "$COMPONENTS_SUBSET in [full, all]" + # ESP-DL Pedestrian Detection for ESP32-P4 espressif/pedestrian_detect: version: "master" git: https://github.com/espressif/esp-dl.git path: models/pedestrian_detect require: public rules: - - if: "target in [esp32s3, esp32p4]" + - if: "target in [esp32p4]" - if: "$COMPONENTS_SUBSET in [full, all]" espressif/esp-sr: version: ">=1.4.2" From 8bc7ec59ec1a9d4b8ee191f930bc79891cfeb99d Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 1 Oct 2024 01:12:45 +0300 Subject: [PATCH 11/38] Rename old DL component and revert the name of the new --- main/idf_component.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/main/idf_component.yml b/main/idf_component.yml index 0a934f88b..441408500 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -15,8 +15,7 @@ dependencies: - if: "target not in [esp32c2]" - if: "$COMPONENTS_SUBSET in [full, all]" # ESP-DL for ESP32, ESP32S2 and ESP32-S3 - espressif/esp-dl: - version: "master" + espressif/esp-dl-old: version: "af7808ba09448ce82c704455975d4cf1e4305fd7" git: https://github.com/espressif/esp-dl.git require: public @@ -24,7 +23,7 @@ dependencies: - if: "target in [esp32s3, esp32s2, esp32]" - if: "$COMPONENTS_SUBSET in [full, all]" # ESP-DL for ESP32-P4 - espressif/esp-dl2: + espressif/esp-dl: version: "master" git: https://github.com/espressif/esp-dl.git path: esp-dl From ac25609d73a55781ea78b558eb1f76b4930f8297 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Wed, 2 Oct 2024 14:54:56 +0300 Subject: [PATCH 12/38] Enable TinyUSB build for ESP32P4 --- components/arduino_tinyusb/Kconfig.projbuild | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/arduino_tinyusb/Kconfig.projbuild b/components/arduino_tinyusb/Kconfig.projbuild index 1db30506f..e8dcf06b7 100755 --- a/components/arduino_tinyusb/Kconfig.projbuild +++ b/components/arduino_tinyusb/Kconfig.projbuild @@ -4,7 +4,7 @@ menu "Arduino TinyUSB" config TINYUSB_ENABLED bool "Enable TinyUSB driver" default y - depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4 select FREERTOS_SUPPORT_STATIC_ALLOCATION select FREERTOS_USE_AUTHENTIC_INCLUDE_PATHS help From 0232d0a9a2e8cbe97c22153ddaad74a1e4973350 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 3 Oct 2024 13:43:46 +0300 Subject: [PATCH 13/38] Add support for HighSpeed USB in arduino_tinyusb --- components/arduino_tinyusb/Kconfig.projbuild | 26 ++++++++++++------- .../arduino_tinyusb/include/tusb_config.h | 7 +++++ .../arduino_tinyusb/patches/dcd_dwc2.patch | 12 ++++----- components/arduino_tinyusb/src/dcd_dwc2.c | 12 ++++----- 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/components/arduino_tinyusb/Kconfig.projbuild b/components/arduino_tinyusb/Kconfig.projbuild index e8dcf06b7..65d9c37be 100755 --- a/components/arduino_tinyusb/Kconfig.projbuild +++ b/components/arduino_tinyusb/Kconfig.projbuild @@ -28,14 +28,16 @@ menu "Arduino TinyUSB" config TINYUSB_CDC_RX_BUFSIZE int "CDC FIFO size of RX" - default 64 + default 64 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + default 512 if IDF_TARGET_ESP32P4 depends on TINYUSB_CDC_ENABLED help CDC FIFO size of RX config TINYUSB_CDC_TX_BUFSIZE int "CDC FIFO size of TX" - default 64 + default 64 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + default 512 if IDF_TARGET_ESP32P4 depends on TINYUSB_CDC_ENABLED help CDC FIFO size of TX @@ -86,7 +88,8 @@ menu "Arduino TinyUSB" config TINYUSB_HID_BUFSIZE int "HID Buffer size" - default 64 + default 64 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + default 512 if IDF_TARGET_ESP32P4 depends on TINYUSB_HID_ENABLED help HID Buffer size. Should be sufficient to hold ID (if any) + Data @@ -111,14 +114,16 @@ menu "Arduino TinyUSB" config TINYUSB_MIDI_RX_BUFSIZE int "MIDI FIFO size of RX" - default 64 + default 64 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + default 512 if IDF_TARGET_ESP32P4 depends on TINYUSB_MIDI_ENABLED help MIDI FIFO size of RX config TINYUSB_MIDI_TX_BUFSIZE int "MIDI FIFO size of TX" - default 64 + default 64 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + default 512 if IDF_TARGET_ESP32P4 depends on TINYUSB_MIDI_ENABLED help MIDI FIFO size of TX @@ -143,8 +148,9 @@ menu "Arduino TinyUSB" config TINYUSB_VIDEO_STREAMING_BUFSIZE int "VIDEO streaming endpoint size" - range 0 64 - default 64 + range 0 512 + default 64 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + default 512 if IDF_TARGET_ESP32P4 depends on TINYUSB_VIDEO_ENABLED help VIDEO streaming endpoint size @@ -219,14 +225,16 @@ menu "Arduino TinyUSB" config TINYUSB_VENDOR_RX_BUFSIZE int "VENDOR FIFO size of RX" - default 64 + default 64 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + default 512 if IDF_TARGET_ESP32P4 depends on TINYUSB_VENDOR_ENABLED help VENDOR FIFO size of RX config TINYUSB_VENDOR_TX_BUFSIZE int "VENDOR FIFO size of TX" - default 64 + default 64 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + default 512 if IDF_TARGET_ESP32P4 depends on TINYUSB_VENDOR_ENABLED help VENDOR FIFO size of TX diff --git a/components/arduino_tinyusb/include/tusb_config.h b/components/arduino_tinyusb/include/tusb_config.h index 90dd7f797..458c78cf1 100755 --- a/components/arduino_tinyusb/include/tusb_config.h +++ b/components/arduino_tinyusb/include/tusb_config.h @@ -100,11 +100,18 @@ extern "C" { # define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) #endif +#if CONFIG_IDF_TARGET_ESP32P4 +#define CFG_TUD_MAX_SPEED OPT_MODE_HIGH_SPEED +#else +#define CFG_TUD_MAX_SPEED OPT_MODE_FULL_SPEED +#endif + /* */ /* DRIVER CONFIGURATION */ /* */ #define CFG_TUD_MAINTASK_SIZE 4096 +#define CFG_TUD_ENDOINT_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #define CFG_TUD_ENDOINT0_SIZE 64 // Enabled Drivers diff --git a/components/arduino_tinyusb/patches/dcd_dwc2.patch b/components/arduino_tinyusb/patches/dcd_dwc2.patch index a57df7ef6..7aef99c33 100644 --- a/components/arduino_tinyusb/patches/dcd_dwc2.patch +++ b/components/arduino_tinyusb/patches/dcd_dwc2.patch @@ -4,7 +4,7 @@ //-------------------------------------------------------------------- // Endpoint //-------------------------------------------------------------------- -+#if defined(TUP_USBIP_DWC2_ESP32) ++#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +// Keep count of how many FIFOs are in use +static uint8_t _allocated_fifos = 1; //FIFO0 is always in use + @@ -23,7 +23,7 @@ } else { - dwc2->epin[epnum].diepctl = dxepctl | (epnum << DIEPCTL_TXFNUM_Pos); + uint8_t fifo_num = epnum; -+#if defined(TUP_USBIP_DWC2_ESP32) ++#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + // Special Case for EP5, which is used by CDC but not actually called by the driver + // we can give it a fake FIFO + if (epnum == 5) { @@ -41,7 +41,7 @@ xfer_status[n][TUSB_DIR_IN].max_size = 0; } -+#if defined(TUP_USBIP_DWC2_ESP32) ++#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + _allocated_fifos = 1; +#endif + @@ -52,7 +52,7 @@ if (int_status & GINTSTS_USBRST) { // USBRST is start of reset. dwc2->gintsts = GINTSTS_USBRST; -+#if defined(TUP_USBIP_DWC2_ESP32) ++#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + _allocated_fifos = 1; +#endif bus_reset(rhport); @@ -65,7 +65,7 @@ - dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); + //dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); + dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); -+#if defined(TUP_USBIP_DWC2_ESP32) ++#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + _allocated_fifos = 1; +#endif } @@ -75,7 +75,7 @@ if (otg_int & GOTGINT_SEDET) { dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); -+#if defined(TUP_USBIP_DWC2_ESP32) ++#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + _allocated_fifos = 1; +#endif } diff --git a/components/arduino_tinyusb/src/dcd_dwc2.c b/components/arduino_tinyusb/src/dcd_dwc2.c index 8bcc98166..fa81e5e29 100644 --- a/components/arduino_tinyusb/src/dcd_dwc2.c +++ b/components/arduino_tinyusb/src/dcd_dwc2.c @@ -316,7 +316,7 @@ static void dfifo_write_packet(uint8_t rhport, uint8_t fifo_num, uint8_t const* //-------------------------------------------------------------------- // Endpoint //-------------------------------------------------------------------- -#if defined(TUP_USBIP_DWC2_ESP32) +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) // Keep count of how many FIFOs are in use static uint8_t _allocated_fifos = 1; //FIFO0 is always in use @@ -347,7 +347,7 @@ static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoin dwc2->daintmsk |= TU_BIT(DAINTMSK_OEPM_Pos + epnum); } else { uint8_t fifo_num = epnum; -#if defined(TUP_USBIP_DWC2_ESP32) +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) // Special Case for EP5, which is used by CDC but not actually called by the driver // we can give it a fake FIFO if (epnum == 5) { @@ -871,7 +871,7 @@ void dcd_edpt_close_all(uint8_t rhport) { xfer_status[n][TUSB_DIR_IN].max_size = 0; } -#if defined(TUP_USBIP_DWC2_ESP32) +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) _allocated_fifos = 1; #endif @@ -1229,7 +1229,7 @@ void dcd_int_handler(uint8_t rhport) { if (int_status & GINTSTS_USBRST) { // USBRST is start of reset. dwc2->gintsts = GINTSTS_USBRST; -#if defined(TUP_USBIP_DWC2_ESP32) +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) _allocated_fifos = 1; #endif bus_reset(rhport); @@ -1265,7 +1265,7 @@ void dcd_int_handler(uint8_t rhport) { dwc2->gintsts = GINTSTS_USBSUSP; //dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); -#if defined(TUP_USBIP_DWC2_ESP32) +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) _allocated_fifos = 1; #endif } @@ -1284,7 +1284,7 @@ void dcd_int_handler(uint8_t rhport) { if (otg_int & GOTGINT_SEDET) { dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); -#if defined(TUP_USBIP_DWC2_ESP32) +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) _allocated_fifos = 1; #endif } From 11b9bf96654be4d26e81c84cfa924a4dc7a014f0 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 10 Oct 2024 12:52:28 +0300 Subject: [PATCH 14/38] Update tinyusb dcd_dwc2 --- .../arduino_tinyusb/patches/dcd_dwc2.patch | 27 +- components/arduino_tinyusb/src/dcd_dwc2.c | 314 ++++++++---------- 2 files changed, 161 insertions(+), 180 deletions(-) diff --git a/components/arduino_tinyusb/patches/dcd_dwc2.patch b/components/arduino_tinyusb/patches/dcd_dwc2.patch index 7aef99c33..e93f9629b 100644 --- a/components/arduino_tinyusb/patches/dcd_dwc2.patch +++ b/components/arduino_tinyusb/patches/dcd_dwc2.patch @@ -17,11 +17,12 @@ static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); -@@ -336,7 +346,18 @@ - dwc2->epout[epnum].doepctl = dxepctl; - dwc2->daintmsk |= TU_BIT(DAINTMSK_OEPM_Pos + epnum); - } else { -- dwc2->epin[epnum].diepctl = dxepctl | (epnum << DIEPCTL_TXFNUM_Pos); +@@ -332,7 +342,19 @@ + (p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DOEPCTL_SD0PID_SEVNFRM : 0) | + (xfer->max_size << DOEPCTL_MPSIZ_Pos); + if (dir == TUSB_DIR_IN) { +- epctl |= (epnum << DIEPCTL_TXFNUM_Pos); ++ //epctl |= (epnum << DIEPCTL_TXFNUM_Pos); + uint8_t fifo_num = epnum; +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + // Special Case for EP5, which is used by CDC but not actually called by the driver @@ -33,12 +34,12 @@ + } + //TU_ASSERT(fifo_num != 0); +#endif -+ dwc2->epin[epnum].diepctl = dxepctl | (fifo_num << DIEPCTL_TXFNUM_Pos); - dwc2->daintmsk |= TU_BIT(DAINTMSK_IEPM_Pos + epnum); ++ epctl |= (fifo_num << DIEPCTL_TXFNUM_Pos); } - } -@@ -850,6 +871,10 @@ - xfer_status[n][TUSB_DIR_IN].max_size = 0; + + dwc2_dep_t* dep = &dwc2->ep[1 - dir][epnum]; +@@ -840,6 +862,10 @@ + } } +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) @@ -48,7 +49,7 @@ dfifo_flush_tx(dwc2, 0x10); // all tx fifo dfifo_flush_rx(dwc2); -@@ -1204,6 +1229,9 @@ +@@ -1186,6 +1212,9 @@ if (int_status & GINTSTS_USBRST) { // USBRST is start of reset. dwc2->gintsts = GINTSTS_USBRST; @@ -58,7 +59,7 @@ bus_reset(rhport); } -@@ -1235,7 +1263,11 @@ +@@ -1217,7 +1246,11 @@ if (int_status & GINTSTS_USBSUSP) { dwc2->gintsts = GINTSTS_USBSUSP; @@ -71,7 +72,7 @@ } if (int_status & GINTSTS_WKUINT) { -@@ -1252,6 +1284,9 @@ +@@ -1234,6 +1267,9 @@ if (otg_int & GOTGINT_SEDET) { dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); diff --git a/components/arduino_tinyusb/src/dcd_dwc2.c b/components/arduino_tinyusb/src/dcd_dwc2.c index fa81e5e29..fcc8d1f8c 100644 --- a/components/arduino_tinyusb/src/dcd_dwc2.c +++ b/components/arduino_tinyusb/src/dcd_dwc2.c @@ -337,15 +337,12 @@ static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoin xfer->interval = p_endpoint_desc->bInterval; // USBAEP, EPTYP, SD0PID_SEVNFRM, MPSIZ are the same for IN and OUT endpoints. - uint32_t const dxepctl = (1 << DOEPCTL_USBAEP_Pos) | - (p_endpoint_desc->bmAttributes.xfer << DOEPCTL_EPTYP_Pos) | - (p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DOEPCTL_SD0PID_SEVNFRM : 0) | - (xfer->max_size << DOEPCTL_MPSIZ_Pos); - - if (dir == TUSB_DIR_OUT) { - dwc2->epout[epnum].doepctl = dxepctl; - dwc2->daintmsk |= TU_BIT(DAINTMSK_OEPM_Pos + epnum); - } else { + uint32_t epctl = (1 << DOEPCTL_USBAEP_Pos) | + (p_endpoint_desc->bmAttributes.xfer << DOEPCTL_EPTYP_Pos) | + (p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DOEPCTL_SD0PID_SEVNFRM : 0) | + (xfer->max_size << DOEPCTL_MPSIZ_Pos); + if (dir == TUSB_DIR_IN) { + //epctl |= (epnum << DIEPCTL_TXFNUM_Pos); uint8_t fifo_num = epnum; #if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) // Special Case for EP5, which is used by CDC but not actually called by the driver @@ -357,44 +354,44 @@ static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoin } //TU_ASSERT(fifo_num != 0); #endif - dwc2->epin[epnum].diepctl = dxepctl | (fifo_num << DIEPCTL_TXFNUM_Pos); - dwc2->daintmsk |= TU_BIT(DAINTMSK_IEPM_Pos + epnum); + epctl |= (fifo_num << DIEPCTL_TXFNUM_Pos); } + + dwc2_dep_t* dep = &dwc2->ep[1 - dir][epnum]; + dep->ctl = epctl; + dwc2->daintmsk |= TU_BIT(epnum + DAINT_SHIFT(dir)); } static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { (void) rhport; dwc2_regs_t* dwc2 = DWC2_REG(rhport); - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + const uint8_t epnum = tu_edpt_number(ep_addr); + const uint8_t dir = tu_edpt_dir(ep_addr); + dwc2_dep_t* dep = &dwc2->ep[1 - dir][epnum]; if (dir == TUSB_DIR_IN) { - dwc2_epin_t* epin = dwc2->epin; - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(epin[epnum].diepctl & DIEPCTL_EPENA)) { - epin[epnum].diepctl |= DIEPCTL_SNAK | (stall ? DIEPCTL_STALL : 0); + if ((epnum == 0) || !(dep->diepctl & DIEPCTL_EPENA)) { + dep->diepctl |= DIEPCTL_SNAK | (stall ? DIEPCTL_STALL : 0); } else { // Stop transmitting packets and NAK IN xfers. - epin[epnum].diepctl |= DIEPCTL_SNAK; - while ((epin[epnum].diepint & DIEPINT_INEPNE) == 0) {} + dep->diepctl |= DIEPCTL_SNAK; + while ((dep->diepint & DIEPINT_INEPNE) == 0) {} // Disable the endpoint. - epin[epnum].diepctl |= DIEPCTL_EPDIS | (stall ? DIEPCTL_STALL : 0); - while ((epin[epnum].diepint & DIEPINT_EPDISD_Msk) == 0) {} + dep->diepctl |= DIEPCTL_EPDIS | (stall ? DIEPCTL_STALL : 0); + while ((dep->diepint & DIEPINT_EPDISD_Msk) == 0) {} - epin[epnum].diepint = DIEPINT_EPDISD; + dep->diepint = DIEPINT_EPDISD; } // Flush the FIFO, and wait until we have confirmed it cleared. dfifo_flush_tx(dwc2, epnum); } else { - dwc2_epout_t* epout = dwc2->epout; - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(epout[epnum].doepctl & DOEPCTL_EPENA)) { - epout[epnum].doepctl |= stall ? DOEPCTL_STALL : 0; + if ((epnum == 0) || !(dep->doepctl & DOEPCTL_EPENA)) { + dep->doepctl |= stall ? DOEPCTL_STALL : 0; } else { // Asserting GONAK is required to STALL an OUT endpoint. // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt @@ -403,11 +400,11 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { dwc2->dctl |= DCTL_SGONAK; while ((dwc2->gintsts & GINTSTS_BOUTNAKEFF_Msk) == 0) {} - // Ditto here- disable the endpoint. - epout[epnum].doepctl |= DOEPCTL_EPDIS | (stall ? DOEPCTL_STALL : 0); - while ((epout[epnum].doepint & DOEPINT_EPDISD_Msk) == 0) {} + // Ditto here disable the endpoint. + dep->doepctl |= DOEPCTL_EPDIS | (stall ? DOEPCTL_STALL : 0); + while ((dep->doepint & DOEPINT_EPDISD_Msk) == 0) {} - epout[epnum].doepint = DOEPINT_EPDISD; + dep->doepint = DOEPINT_EPDISD; // Allow other OUT endpoints to keep receiving. dwc2->dctl |= DCTL_CGONAK; @@ -423,12 +420,8 @@ static void bus_reset(uint8_t rhport) { tu_memclr(xfer_status, sizeof(xfer_status)); _sof_en = false; - _allocated_ep_in_count = 1; - // clear device address - dwc2->dcfg &= ~DCFG_DAD_Msk; - // 1. NAK for all OUT endpoints for (uint8_t n = 0; n < ep_count; n++) { dwc2->epout[n].doepctl |= DOEPCTL_SNAK; @@ -444,14 +437,18 @@ static void bus_reset(uint8_t rhport) { dfifo_flush_tx(dwc2, 0x10); // all tx fifo dfifo_flush_rx(dwc2); - // 3. Set up interrupt mask + // 3. Set up interrupt mask for EP0 dwc2->daintmsk = TU_BIT(DAINTMSK_OEPM_Pos) | TU_BIT(DAINTMSK_IEPM_Pos); dwc2->doepmsk = DOEPMSK_STUPM | DOEPMSK_XFRCM; dwc2->diepmsk = DIEPMSK_TOM | DIEPMSK_XFRCM; + // 4. Set up DFIFO dfifo_init(rhport); - // Fixed control EP0 size to 64 bytes + // 5. Reset device address + dwc2->dcfg &= ~DCFG_DAD_Msk; + + // Fixed both control EP0 size to 64 bytes dwc2->epin[0].diepctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos); dwc2->epout[0].doepctl &= ~(0x03 << DOEPCTL_MPSIZ_Pos); @@ -482,33 +479,33 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c } // IN and OUT endpoint xfers are interrupt-driven, we just schedule them here. - if (dir == TUSB_DIR_IN) { - dwc2_epin_t* epin = dwc2->epin; + const uint8_t is_epout = 1 - dir; + dwc2_dep_t* dep = &dwc2->ep[is_epout][epnum]; + if (dir == TUSB_DIR_IN) { // A full IN transfer (multiple packets, possibly) triggers XFRC. - epin[epnum].dieptsiz = (num_packets << DIEPTSIZ_PKTCNT_Pos) | + dep->dieptsiz = (num_packets << DIEPTSIZ_PKTCNT_Pos) | ((total_bytes << DIEPTSIZ_XFRSIZ_Pos) & DIEPTSIZ_XFRSIZ_Msk); if(dma_enabled(dwc2)) { - epin[epnum].diepdma = (uintptr_t)xfer->buffer; + dep->diepdma = (uintptr_t)xfer->buffer; // For ISO endpoint set correct odd/even bit for next frame. - if ((epin[epnum].diepctl & DIEPCTL_EPTYP) == DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1) { + if ((dep->diepctl & DIEPCTL_EPTYP) == DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1) { // Take odd/even bit from frame counter. uint32_t const odd_frame_now = (dwc2->dsts & (1u << DSTS_FNSOF_Pos)); - epin[epnum].diepctl |= (odd_frame_now ? DIEPCTL_SD0PID_SEVNFRM_Msk : DIEPCTL_SODDFRM_Msk); + dep->diepctl |= (odd_frame_now ? DIEPCTL_SD0PID_SEVNFRM_Msk : DIEPCTL_SODDFRM_Msk); } - epin[epnum].diepctl |= DIEPCTL_EPENA | DIEPCTL_CNAK; + dep->diepctl |= DIEPCTL_EPENA | DIEPCTL_CNAK; } else { - - epin[epnum].diepctl |= DIEPCTL_EPENA | DIEPCTL_CNAK; + dep->diepctl |= DIEPCTL_EPENA | DIEPCTL_CNAK; // For ISO endpoint set correct odd/even bit for next frame. - if ((epin[epnum].diepctl & DIEPCTL_EPTYP) == DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1) { + if ((dep->diepctl & DIEPCTL_EPTYP) == DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1) { // Take odd/even bit from frame counter. uint32_t const odd_frame_now = (dwc2->dsts & (1u << DSTS_FNSOF_Pos)); - epin[epnum].diepctl |= (odd_frame_now ? DIEPCTL_SD0PID_SEVNFRM_Msk : DIEPCTL_SODDFRM_Msk); + dep->diepctl |= (odd_frame_now ? DIEPCTL_SD0PID_SEVNFRM_Msk : DIEPCTL_SODDFRM_Msk); } // Enable fifo empty interrupt only if there are something to put in the fifo. if (total_bytes != 0) { @@ -516,25 +513,23 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c } } } else { - dwc2_epout_t* epout = dwc2->epout; - // A full OUT transfer (multiple packets, possibly) triggers XFRC. - epout[epnum].doeptsiz &= ~(DOEPTSIZ_PKTCNT_Msk | DOEPTSIZ_XFRSIZ); - epout[epnum].doeptsiz |= (num_packets << DOEPTSIZ_PKTCNT_Pos) | + dep->doeptsiz &= ~(DOEPTSIZ_PKTCNT_Msk | DOEPTSIZ_XFRSIZ); + dep->doeptsiz |= (num_packets << DOEPTSIZ_PKTCNT_Pos) | ((total_bytes << DOEPTSIZ_XFRSIZ_Pos) & DOEPTSIZ_XFRSIZ_Msk); - if ((epout[epnum].doepctl & DOEPCTL_EPTYP) == DOEPCTL_EPTYP_0 && + if ((dep->doepctl & DOEPCTL_EPTYP) == DOEPCTL_EPTYP_0 && XFER_CTL_BASE(epnum, dir)->interval == 1) { // Take odd/even bit from frame counter. uint32_t const odd_frame_now = (dwc2->dsts & (1u << DSTS_FNSOF_Pos)); - epout[epnum].doepctl |= (odd_frame_now ? DOEPCTL_SD0PID_SEVNFRM_Msk : DOEPCTL_SODDFRM_Msk); + dep->doepctl |= (odd_frame_now ? DOEPCTL_SD0PID_SEVNFRM_Msk : DOEPCTL_SODDFRM_Msk); } if(dma_enabled(dwc2)) { - epout[epnum].doepdma = (uintptr_t)xfer->buffer; + dep->doepdma = (uintptr_t)xfer->buffer; } - epout[epnum].doepctl |= DOEPCTL_EPENA | DOEPCTL_CNAK; + dep->doepctl |= DOEPCTL_EPENA | DOEPCTL_CNAK; } } @@ -658,7 +653,7 @@ static void phy_hs_init(dwc2_regs_t* dwc2) { static bool check_dwc2(dwc2_regs_t* dwc2) { #if CFG_TUSB_DEBUG >= DWC2_DEBUG // print guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4 - // Run 'dwc2_info.py render-md' and check dwc2_info.md for bit-field value and comparison with other ports + // Run 'python dwc2_info.py' and check dwc2_info.md for bit-field value and comparison with other ports volatile uint32_t const* p = (volatile uint32_t const*) &dwc2->guid; TU_LOG1("guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4\r\n"); for (size_t i = 0; i < 5; i++) { @@ -858,17 +853,13 @@ void dcd_edpt_close_all(uint8_t rhport) { dwc2->daintmsk = (1 << DAINTMSK_OEPM_Pos) | (1 << DAINTMSK_IEPM_Pos); for (uint8_t n = 1; n < ep_count; n++) { - // disable OUT endpoint - if (dwc2->epout[n].doepctl & DOEPCTL_EPENA) { - dwc2->epout[n].doepctl |= DOEPCTL_SNAK | DOEPCTL_EPDIS; - } - xfer_status[n][TUSB_DIR_OUT].max_size = 0; - - // disable IN endpoint - if (dwc2->epin[n].diepctl & DIEPCTL_EPENA) { - dwc2->epin[n].diepctl |= DIEPCTL_SNAK | DIEPCTL_EPDIS; + for (uint8_t d = 0; d < 2; d++) { + dwc2_dep_t* dep = &dwc2->ep[d][n]; + if (dep->ctl & EPCTL_EPENA) { + dep->ctl |= EPCTL_SNAK | EPCTL_EPDIS; + } + xfer_status[n][1-d].max_size = 0; } - xfer_status[n][TUSB_DIR_IN].max_size = 0; } #if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) @@ -942,7 +933,9 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t uint16_t const short_packet_size = total_bytes % xfer->max_size; // Zero-size packet is special case. - if (short_packet_size > 0 || (total_bytes == 0)) num_packets++; + if (short_packet_size > 0 || (total_bytes == 0)) { + num_packets++; + } // Schedule packets to be sent within interrupt edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); @@ -962,50 +955,32 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { - (void) rhport; - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + dwc2_dep_t* dep = &dwc2->ep[1 - dir][epnum]; // Clear stall and reset data toggle - if (dir == TUSB_DIR_IN) { - dwc2->epin[epnum].diepctl &= ~DIEPCTL_STALL; - dwc2->epin[epnum].diepctl |= DIEPCTL_SD0PID_SEVNFRM; - } else { - dwc2->epout[epnum].doepctl &= ~DOEPCTL_STALL; - dwc2->epout[epnum].doepctl |= DOEPCTL_SD0PID_SEVNFRM; - } + dep->ctl &= ~EPCTL_STALL;; + dep->ctl |= EPCTL_SD0PID_SEVNFRM; } //-------------------------------------------------------------------- // Interrupt Handler //-------------------------------------------------------------------- +// Process shared receive FIFO, this interrupt is only used in Slave mode static void handle_rxflvl_irq(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); volatile uint32_t const* rx_fifo = dwc2->fifo[0]; // Pop control word off FIFO - uint32_t const ctl_word = dwc2->grxstsp; - uint8_t const pktsts = (ctl_word & GRXSTSP_PKTSTS_Msk) >> GRXSTSP_PKTSTS_Pos; - uint8_t const epnum = (ctl_word & GRXSTSP_EPNUM_Msk) >> GRXSTSP_EPNUM_Pos; - uint16_t const bcnt = (ctl_word & GRXSTSP_BCNT_Msk) >> GRXSTSP_BCNT_Pos; - + uint32_t const grxstsp = dwc2->grxstsp; + uint8_t const pktsts = (grxstsp & GRXSTSP_PKTSTS_Msk) >> GRXSTSP_PKTSTS_Pos; + uint8_t const epnum = (grxstsp & GRXSTSP_EPNUM_Msk) >> GRXSTSP_EPNUM_Pos; + uint16_t const bcnt = (grxstsp & GRXSTSP_BCNT_Msk) >> GRXSTSP_BCNT_Pos; dwc2_epout_t* epout = &dwc2->epout[epnum]; -//#if CFG_TUSB_DEBUG >= DWC2_DEBUG -// const char * pktsts_str[] = -// { -// "ASSERT", "Global NAK (ISR)", "Out Data Received", "Out Transfer Complete (ISR)", -// "Setup Complete (ISR)", "ASSERT", "Setup Data Received" -// }; -// TU_LOG_LOCATION(); -// TU_LOG(DWC2_DEBUG, " EP %02X, Byte Count %u, %s\r\n", epnum, bcnt, pktsts_str[pktsts]); -// TU_LOG(DWC2_DEBUG, " daint = %08lX, doepint = %04X\r\n", (unsigned long) dwc2->daint, (unsigned int) epout->doepint); -//#endif - switch (pktsts) { // Global OUT NAK: do nothing case GRXSTS_PKTSTS_GLOBALOUTNAK: @@ -1013,15 +988,14 @@ static void handle_rxflvl_irq(uint8_t rhport) { case GRXSTS_PKTSTS_SETUPRX: // Setup packet received - - // We can receive up to three setup packets in succession, but - // only the last one is valid. + // We can receive up to three setup packets in succession, but only the last one is valid. _setup_packet[0] = (*rx_fifo); _setup_packet[1] = (*rx_fifo); break; case GRXSTS_PKTSTS_SETUPDONE: - // Setup packet done (Interrupt) + // Setup packet done: + // After popping this out, dwc2 asserts a DOEPINT_SETUP interrupt which is handled by handle_epout_irq() epout->doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); break; @@ -1049,20 +1023,16 @@ static void handle_rxflvl_irq(uint8_t rhport) { ep0_pending[TUSB_DIR_OUT] = 0; } } - } break; + } - // Out packet done (Interrupt) case GRXSTS_PKTSTS_OUTDONE: - // Occurred on STM32L47 with dwc2 version 3.10a but not found on other version like 2.80a or 3.30a - // May (or not) be 3.10a specific feature/bug or depending on MCU configuration - // XFRC complete is additionally generated when - // - setup packet is received - // - complete the data stage of control write is complete - // It will be handled in handle_epout_irq() + /* Out packet done + After this entry is popped from the receive FIFO, dwc2 asserts a Transfer Completed interrupt on + the specified OUT endpoint which will be handled by handle_epout_irq() */ break; - default: // Invalid + default: TU_BREAKPOINT(); break; } @@ -1074,80 +1044,70 @@ static void handle_epout_irq(uint8_t rhport) { // DAINT for a given EP clears when DOEPINTx is cleared. // OEPINT will be cleared when DAINT's out bits are cleared. - for (uint8_t n = 0; n < ep_count; n++) { - if (dwc2->daint & TU_BIT(DAINT_OEPINT_Pos + n)) { - dwc2_epout_t* epout = &dwc2->epout[n]; + for (uint8_t epnum = 0; epnum < ep_count; epnum++) { + if (dwc2->daint & TU_BIT(DAINT_OEPINT_Pos + epnum)) { + dwc2_epout_t* epout = &dwc2->epout[epnum]; + const uint32_t doepint = epout->doepint; + TU_ASSERT((epout->doepint & DOEPINT_AHBERR) == 0, ); - uint32_t const doepint = epout->doepint; + // Setup and/or STPKTRX/STSPHSRX (from 3.00a) can be set along with XFRC, and also set independently. + if (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a) { + if (doepint & DOEPINT_STSPHSRX) { + // Status phase received for control write: In token received from Host + epout->doepint = DOEPINT_STSPHSRX; + } - TU_ASSERT((epout->doepint & DOEPINT_AHBERR) == 0, ); + if (doepint & DOEPINT_STPKTRX) { + // New setup packet received, but wait for Setup done, since we can receive up to 3 setup consecutively + epout->doepint = DOEPINT_STPKTRX; + } + } + + if (doepint & DOEPINT_SETUP) { + epout->doepint = DOEPINT_SETUP; + + if(dma_enabled(dwc2)) { + dma_setup_prepare(rhport); + } + + dcd_event_setup_received(rhport, (uint8_t*) _setup_packet, true); + } // OUT XFER complete - if (epout->doepint & DOEPINT_XFRC) { + if (doepint & DOEPINT_XFRC) { epout->doepint = DOEPINT_XFRC; - xfer_ctl_t* xfer = XFER_CTL_BASE(n, TUSB_DIR_OUT); + // only handle data skip if it is setup or status related + // Normal OUT transfer complete + if (!(doepint & (DOEPINT_SETUP | DOEPINT_STPKTRX | DOEPINT_STSPHSRX))) { + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - if(dma_enabled(dwc2)) { - if (doepint & DOEPINT_STUP) { - // STPKTRX is only available for version from 3_00a - if ((doepint & DOEPINT_STPKTRX) && (dwc2->gsnpsid > DWC2_CORE_REV_3_00a)) { - epout->doepint = DOEPINT_STPKTRX; - } - } else if (doepint & DOEPINT_OTEPSPR) { - epout->doepint = DOEPINT_OTEPSPR; - } else { - if ((doepint & DOEPINT_STPKTRX) && (dwc2->gsnpsid > DWC2_CORE_REV_3_00a)) { - epout->doepint = DOEPINT_STPKTRX; + if(dma_enabled(dwc2)) { + if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) { + // EP0 can only handle one packet Schedule another packet to be received. + edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); } else { - // EP0 can only handle one packet - if ((n == 0) && ep0_pending[TUSB_DIR_OUT]) { - // Schedule another packet to be received. - edpt_schedule_packets(rhport, n, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); - } else { - // Fix packet length - uint16_t remain = (epout->doeptsiz & DOEPTSIZ_XFRSIZ_Msk) >> DOEPTSIZ_XFRSIZ_Pos; - xfer->total_len -= remain; - // this is ZLP, so prepare EP0 for next setup - if(n == 0 && xfer->total_len == 0) { - dma_setup_prepare(rhport); - } - - dcd_event_xfer_complete(rhport, n, xfer->total_len, XFER_RESULT_SUCCESS, true); + // Fix packet length + uint16_t remain = (epout->doeptsiz & DOEPTSIZ_XFRSIZ_Msk) >> DOEPTSIZ_XFRSIZ_Pos; + xfer->total_len -= remain; + // this is ZLP, so prepare EP0 for next setup + if(epnum == 0 && xfer->total_len == 0) { + dma_setup_prepare(rhport); } + + dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); } - } - } else { - if ((doepint & DOEPINT_STPKTRX) && (dwc2->gsnpsid == DWC2_CORE_REV_3_10a)) { - epout->doepint = DOEPINT_STPKTRX; } else { - if ((doepint & DOEPINT_OTEPSPR) && (dwc2->gsnpsid == DWC2_CORE_REV_3_10a)) { - epout->doepint = DOEPINT_OTEPSPR; - } - // EP0 can only handle one packet - if ((n == 0) && ep0_pending[TUSB_DIR_OUT]) { + if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) { // Schedule another packet to be received. - edpt_schedule_packets(rhport, n, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); + edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); } else { - dcd_event_xfer_complete(rhport, n, xfer->total_len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); } } } } - - // SETUP packet Setup Phase done. - if (doepint & DOEPINT_STUP) { - epout->doepint = DOEPINT_STUP; - if ((doepint & DOEPINT_STPKTRX) && (dwc2->gsnpsid > DWC2_CORE_REV_3_00a)) { - epout->doepint = DOEPINT_STPKTRX; - } - if(dma_enabled(dwc2) && (dwc2->gsnpsid > DWC2_CORE_REV_3_00a)) { - dma_setup_prepare(rhport); - } - - dcd_event_setup_received(rhport, (uint8_t*) _setup_packet, true); - } } } } @@ -1220,6 +1180,29 @@ static void handle_epin_irq(uint8_t rhport) { } } +/* Interrupt Hierarchy + + DxEPMSK.XferComplMsk DxEPINTn.XferCompl + | | + +---------- AND --------+ + | + DAINT.xEPnInt DAINTMSK.xEPnMsk + | | + +---------- AND --------+ + | + GINTSTS.xEPInt GINTMSK.xEPIntMsk + | | + +---------- AND --------+ + | + GAHBCFG.GblIntrMsk + | + IRQn + + Note: when OTG_MULTI_PROC_INTRPT = 1, Device Each endpoint interrupt deachint/deachmsk/diepeachmsk/doepeachmsk + are combined to generate dedicated interrupt line for each endpoint. + */ + + void dcd_int_handler(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); @@ -1307,13 +1290,10 @@ void dcd_int_handler(uint8_t rhport) { // RxFIFO non-empty interrupt handling. if (int_status & GINTSTS_RXFLVL) { // RXFLVL bit is read-only + dwc2->gintmsk &= ~GINTMSK_RXFLVLM; // disable RXFLVL interrupt while reading - // Mask out RXFLVL while reading data from FIFO - dwc2->gintmsk &= ~GINTMSK_RXFLVLM; - - // Loop until all available packets were handled do { - handle_rxflvl_irq(rhport); + handle_rxflvl_irq(rhport); // read all packets } while(dwc2->gintsts & GINTSTS_RXFLVL); dwc2->gintmsk |= GINTMSK_RXFLVLM; From 062283e0878325b88a293fa0e2c16b402d9164e3 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 15 Oct 2024 17:05:38 +0300 Subject: [PATCH 15/38] Add P4 configuration for PSRAM, WDT and ESP-HOSTED --- configs/builds.json | 2 +- configs/defconfig.esp32p4 | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/configs/builds.json b/configs/builds.json index e4b3ec7c0..ddfb8e4f8 100644 --- a/configs/builds.json +++ b/configs/builds.json @@ -46,7 +46,7 @@ "targets":[ { "target": "esp32p4", - "features":[], + "features":["qio_ram"], "idf_libs":["qio","80m"], "bootloaders":[ ["qio","80m"], diff --git a/configs/defconfig.esp32p4 b/configs/defconfig.esp32p4 index e69de29bb..c8266b0c0 100644 --- a/configs/defconfig.esp32p4 +++ b/configs/defconfig.esp32p4 @@ -0,0 +1,12 @@ +CONFIG_SPIRAM=y +# CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 is not set +CONFIG_LWIP_TCP_SACK_OUT=y +CONFIG_SLAVE_IDF_TARGET_ESP32C6=y +CONFIG_ESP_SDIO_BUS_WIDTH=4 +CONFIG_ESP_SDIO_CLOCK_FREQ_KHZ=40000 +CONFIG_ESP_SDIO_PIN_CMD=19 +CONFIG_ESP_SDIO_PIN_CLK=18 +CONFIG_ESP_SDIO_PIN_D0=14 +CONFIG_ESP_SDIO_PIN_D1=15 +CONFIG_ESP_SDIO_PIN_D2=16 +CONFIG_ESP_SDIO_PIN_D3=17 From 177dc97c5ddd6264c2f0012abc3694c236823ca9 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 15 Oct 2024 18:11:20 +0300 Subject: [PATCH 16/38] Update dcd_dwc2.c --- components/arduino_tinyusb/src/dcd_dwc2.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/components/arduino_tinyusb/src/dcd_dwc2.c b/components/arduino_tinyusb/src/dcd_dwc2.c index fcc8d1f8c..e76bdf70e 100644 --- a/components/arduino_tinyusb/src/dcd_dwc2.c +++ b/components/arduino_tinyusb/src/dcd_dwc2.c @@ -672,13 +672,15 @@ static bool check_dwc2(dwc2_regs_t* dwc2) { return true; } -void dcd_init(uint8_t rhport) { +bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { + (void) rhport; + (void) rh_init; // Programming model begins in the last section of the chapter on the USB // peripheral in each Reference Manual. dwc2_regs_t* dwc2 = DWC2_REG(rhport); // Check Synopsys ID register, failed if controller clock/power is not enabled - TU_ASSERT(check_dwc2(dwc2), ); + TU_ASSERT(check_dwc2(dwc2)); dcd_disconnect(rhport); if (phy_hs_supported(dwc2)) { @@ -747,6 +749,8 @@ void dcd_init(uint8_t rhport) { // TU_LOG_HEX(DWC2_DEBUG, dwc2->gahbcfg); dcd_connect(rhport); + + return true; } void dcd_int_enable(uint8_t rhport) { From d7b210ba6d33be20ae52536f85032311f0e9225d Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Wed, 16 Oct 2024 23:56:47 +0300 Subject: [PATCH 17/38] Remove conditional inclusion of builder specified components CCACHE is very fast and it also causes issues with memory variants --- build.sh | 10 +++++----- main/idf_component.yml | 8 -------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/build.sh b/build.sh index 74751f54b..9bceda087 100755 --- a/build.sh +++ b/build.sh @@ -169,7 +169,7 @@ if [ "$BUILD_TYPE" != "all" ]; then echo "idf.py -DIDF_TARGET=\"$target\" -DSDKCONFIG_DEFAULTS=\"$configs\" $BUILD_TYPE" rm -rf build sdkconfig - COMPONENTS_SUBSET=full idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$configs" $BUILD_TYPE + idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$configs" $BUILD_TYPE if [ $? -ne 0 ]; then exit 1; fi done exit 0 @@ -223,11 +223,11 @@ for target_json in `jq -c '.targets[]' configs/builds.json`; do echo "* Build IDF-Libs: $idf_libs_configs" rm -rf build sdkconfig - COMPONENTS_SUBSET=full idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$idf_libs_configs" idf-libs + idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$idf_libs_configs" idf-libs if [ $? -ne 0 ]; then exit 1; fi if [ "$target" == "esp32s3" ]; then - COMPONENTS_SUBSET=full idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$idf_libs_configs" srmodels_bin + idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$idf_libs_configs" srmodels_bin if [ $? -ne 0 ]; then exit 1; fi AR_SDK="$AR_TOOLS/esp32-arduino-libs/$target" # sr model.bin @@ -248,7 +248,7 @@ for target_json in `jq -c '.targets[]' configs/builds.json`; do echo "* Build BootLoader: $bootloader_configs" rm -rf build sdkconfig - COMPONENTS_SUBSET=none idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$bootloader_configs" copy-bootloader + idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$bootloader_configs" copy-bootloader if [ $? -ne 0 ]; then exit 1; fi done @@ -261,7 +261,7 @@ for target_json in `jq -c '.targets[]' configs/builds.json`; do echo "* Build Memory Variant: $mem_configs" rm -rf build sdkconfig - COMPONENTS_SUBSET=none idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$mem_configs" mem-variant + idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$mem_configs" mem-variant if [ $? -ne 0 ]; then exit 1; fi done done diff --git a/main/idf_component.yml b/main/idf_component.yml index 100684fef..a7c6053fe 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -7,13 +7,11 @@ dependencies: require: public rules: - if: "target in [esp32, esp32s2, esp32s3]" - - if: "$COMPONENTS_SUBSET in [full, all]" espressif/esp-tflite-micro: version: ">=1.2.0" require: public rules: - if: "target not in [esp32c2]" - - if: "$COMPONENTS_SUBSET in [full, all]" # ESP-DL for ESP32, ESP32S2 and ESP32-S3 # espressif/esp-dl-old: # version: "af7808ba09448ce82c704455975d4cf1e4305fd7" @@ -21,7 +19,6 @@ dependencies: # require: public # rules: # - if: "target in [esp32s3, esp32s2, esp32]" - # - if: "$COMPONENTS_SUBSET in [full, all]" # ESP-DL for ESP32-P4 espressif/esp-dl: version: "master" @@ -30,7 +27,6 @@ dependencies: require: public rules: - if: "target in [esp32p4]" - - if: "$COMPONENTS_SUBSET in [full, all]" # ESP-DL Face Detection for ESP32-P4 espressif/human_face_detect: version: "master" @@ -39,7 +35,6 @@ dependencies: require: public rules: - if: "target in [esp32p4]" - - if: "$COMPONENTS_SUBSET in [full, all]" # ESP-DL Pedestrian Detection for ESP32-P4 espressif/pedestrian_detect: version: "master" @@ -48,18 +43,15 @@ dependencies: require: public rules: - if: "target in [esp32p4]" - - if: "$COMPONENTS_SUBSET in [full, all]" espressif/esp-sr: version: ">=1.4.2" rules: - if: "target in [esp32s3]" - - if: "$COMPONENTS_SUBSET in [full, all]" espressif/esp_matter: version: "^1.3.0" require: public rules: - if: "target not in [esp32c2, esp32h2, esp32p4]" - - if: "$COMPONENTS_SUBSET in [full, all]" # esp-sr: "^1.3.1" # esp32-camera: "^2.0.4" From 5aeba7c92e5564fa5c8afff253e33b33cdb8a327 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 17 Oct 2024 00:30:51 +0300 Subject: [PATCH 18/38] Do not use ESP-DL on P4 --- main/idf_component.yml | 72 ------------------------------------------ 1 file changed, 72 deletions(-) diff --git a/main/idf_component.yml b/main/idf_component.yml index a7c6053fe..c6bb97f46 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -12,37 +12,6 @@ dependencies: require: public rules: - if: "target not in [esp32c2]" - # ESP-DL for ESP32, ESP32S2 and ESP32-S3 - # espressif/esp-dl-old: - # version: "af7808ba09448ce82c704455975d4cf1e4305fd7" - # git: https://github.com/espressif/esp-dl.git - # require: public - # rules: - # - if: "target in [esp32s3, esp32s2, esp32]" - # ESP-DL for ESP32-P4 - espressif/esp-dl: - version: "master" - git: https://github.com/espressif/esp-dl.git - path: esp-dl - require: public - rules: - - if: "target in [esp32p4]" - # ESP-DL Face Detection for ESP32-P4 - espressif/human_face_detect: - version: "master" - git: https://github.com/espressif/esp-dl.git - path: models/human_face_detect - require: public - rules: - - if: "target in [esp32p4]" - # ESP-DL Pedestrian Detection for ESP32-P4 - espressif/pedestrian_detect: - version: "master" - git: https://github.com/espressif/esp-dl.git - path: models/pedestrian_detect - require: public - rules: - - if: "target in [esp32p4]" espressif/esp-sr: version: ">=1.4.2" rules: @@ -52,44 +21,3 @@ dependencies: require: public rules: - if: "target not in [esp32c2, esp32h2, esp32p4]" - - # esp-sr: "^1.3.1" - # esp32-camera: "^2.0.4" - # esp-dl: - # git: https://github.com/espressif/esp-dl.git - # espressif/esp_rainmaker: - # path: components/esp_rainmaker - # git: https://github.com/espressif/esp-rainmaker.git - - # # Defining a dependency from the registry: - # # https://components.espressif.com/component/example/cmp - # example/cmp: "^3.3.3" # Automatically update minor releases - # - # # Other ways to define dependencies - # - # # For components maintained by Espressif only name can be used. - # # Same as `espressif/cmp` - # component: "~1.0.0" # Automatically update bugfix releases - # - # # Or in a longer form with extra parameters - # component2: - # version: ">=2.0.0" - # - # # For transient dependencies `public` flag can be set. - # # `public` flag doesn't have an effect for the `main` component. - # # All dependencies of `main` are public by default. - # public: true - # - # # For components hosted on non-default registry: - # service_url: "https://componentregistry.company.com" - # - # # For components in git repository: - # test_component: - # path: test_component - # git: ssh://git@gitlab.com/user/components.git - # - # # For test projects during component development - # # components can be used from a local directory - # # with relative or absolute path - # some_local_component: - # path: ../../projects/component From 7b7b3263ba0e7483b6fba8c517d1cd9b919ca396 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 17 Oct 2024 18:25:12 +0300 Subject: [PATCH 19/38] Update P4 PSRAM Speed to 200MHz --- configs/defconfig.esp32p4 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configs/defconfig.esp32p4 b/configs/defconfig.esp32p4 index c8266b0c0..eaa692910 100644 --- a/configs/defconfig.esp32p4 +++ b/configs/defconfig.esp32p4 @@ -1,6 +1,9 @@ +CONFIG_IDF_EXPERIMENTAL_FEATURES=y CONFIG_SPIRAM=y +CONFIG_SPIRAM_SPEED_200M=y # CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 is not set CONFIG_LWIP_TCP_SACK_OUT=y + CONFIG_SLAVE_IDF_TARGET_ESP32C6=y CONFIG_ESP_SDIO_BUS_WIDTH=4 CONFIG_ESP_SDIO_CLOCK_FREQ_KHZ=40000 From 7080df0de982d07166e5c3548001f75d8a6acb3d Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Tue, 22 Oct 2024 07:23:03 -0300 Subject: [PATCH 20/38] Fixes Matter over WiFi to disable OpenThread (#232) * Fixes Matter over WiFi to disable OpenThread * fix flag value * disables Matter Stack WiFi manager * rollback Matter WiFi Manager changes --- configs/defconfig.esp32c6 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configs/defconfig.esp32c6 b/configs/defconfig.esp32c6 index 7770504fc..fc208aecc 100644 --- a/configs/defconfig.esp32c6 +++ b/configs/defconfig.esp32c6 @@ -34,3 +34,6 @@ CONFIG_OPENTHREAD_NETWORK_EXTPANID="dead00beef00cafe" CONFIG_OPENTHREAD_NETWORK_MASTERKEY="00112233445566778899aabbccddeeff" CONFIG_OPENTHREAD_NETWORK_PSKC="104810e2315100afd6bc9215a6bfac53" # end of OpenThread + +# Matter shall use only WiFi +CONFIG_ENABLE_MATTER_OVER_THREAD=n From e5e032491a98452b32b7b39b407d4b3a4b05b71f Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 22 Oct 2024 23:31:02 +0300 Subject: [PATCH 21/38] Add define to signify that prebuilt libs are used --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b0fca085..1268b8e68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,8 @@ add_custom_command( ) add_custom_target(mem-variant DEPENDS "mem_variant") +idf_build_set_property(COMPILE_DEFINITIONS "-DESP32_ARDUINO_LIB_BUILDER" APPEND) + ################## ### ESP Matter ### ################## From 79775815eb35edabc9bf1b2ffa89bc42411e79f9 Mon Sep 17 00:00:00 2001 From: Me No Dev Date: Fri, 25 Oct 2024 13:31:03 +0300 Subject: [PATCH 22/38] Enable FreeRTOS Trace Facility (#234) * Enable FreeRTOS Trace Facility * Enable more statistics --- configs/defconfig.common | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configs/defconfig.common b/configs/defconfig.common index 47310528c..2224d75cc 100644 --- a/configs/defconfig.common +++ b/configs/defconfig.common @@ -44,6 +44,10 @@ CONFIG_FREERTOS_HZ=1000 CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY=y # CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION is not set CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024 +CONFIG_FREERTOS_USE_TRACE_FACILITY=y +CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y +CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y CONFIG_HEAP_POISONING_LIGHT=y CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024 CONFIG_HTTPD_WS_SUPPORT=y From 00ad1452c0118a6fe4061ed61dceedc82eca0c23 Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Thu, 31 Oct 2024 08:12:59 -0300 Subject: [PATCH 23/38] fix(docker): Add docker tag to run scripts in 5.3 branch (#236) * fix(docker): Add docker tag to run scripts in 5.3 branch * Add additional info --- tools/docker/README.md | 10 ++++------ tools/docker/run.ps1 | 5 ++++- tools/docker/run.sh | 4 +++- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/tools/docker/README.md b/tools/docker/README.md index 109665c4a..d6a213129 100644 --- a/tools/docker/README.md +++ b/tools/docker/README.md @@ -24,7 +24,7 @@ Multiple tags of this image are maintained: ## Basic Usage ```bash -docker run --rm -it -e "TERM=xterm-256color" -v :/arduino-esp32 espressif/esp32-arduino-lib-builder:latest +docker run --rm -it -e "TERM=xterm-256color" -v :/arduino-esp32 espressif/esp32-arduino-lib-builder:release-v5.3 ``` The above command explained: @@ -35,18 +35,16 @@ The above command explained: - `-t`: Allocates a pseudo-TTY. - `-e "TERM=xterm-256color"`: Optional. Sets the terminal type to `xterm-256color` to display colors correctly. - `-v :/arduino-esp32`: Optional. Mounts the Arduino Core for ESP32 repository at `/arduino-esp32` inside the container. Replace `` with the path to the repository on the host machine. If not provided, the container will not copy the compiled libraries to the host machine. - - `espressif/esp32-arduino-lib-builder:latest`: The Docker image to use. + - `espressif/esp32-arduino-lib-builder:release-v5.3`: The Docker image to use. After running the above command, you will be inside the container and can build the libraries using the user interface. By default the docker container will run the user interface script. If you want to run a specific command, you can pass it as an argument to the docker run command. For example, to run a terminal inside the container, you can run: ```bash -docker run -it espressif/esp32-arduino-lib-builder:latest /bin/bash +docker run -it espressif/esp32-arduino-lib-builder:release-v5.3 /bin/bash ``` ## Documentation - - -For more information about this image and the detailed usage instructions, please refer to the Arduino Core for ESP32 documentation. +For more information about this image and the detailed usage instructions, please refer to the [Arduino Core for ESP32 documentation](https://docs.espressif.com/projects/arduino-esp32/en/latest/lib_builder.html#docker-image). diff --git a/tools/docker/run.ps1 b/tools/docker/run.ps1 index 4c49ac505..5ecb01a64 100644 --- a/tools/docker/run.ps1 +++ b/tools/docker/run.ps1 @@ -1,5 +1,8 @@ # This is an example of how to run the docker container. # This script is not part of the container, it is meant to be run on the host machine. +# Note that this file will build the release/v5.3 branch. For other branches, change the tag accordingly. +# You can check the available tags at https://hub.docker.com/r/espressif/esp32-arduino-lib-builder/tags +# As this script is unsigned, you may need to run `Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass` before running it. # Usage: .\run.ps1 # Exit on error @@ -58,4 +61,4 @@ if ($env:LIBBUILDER_GIT_SAFE_DIR) { } Write-Output "Running: docker run $($DOCKER_ARGS -join ' ') espressif/esp32-arduino-lib-builder" -docker run @($DOCKER_ARGS) espressif/esp32-arduino-lib-builder +docker run @($DOCKER_ARGS) espressif/esp32-arduino-lib-builder:release-v5.3 diff --git a/tools/docker/run.sh b/tools/docker/run.sh index 59e967363..c7f97a6f5 100755 --- a/tools/docker/run.sh +++ b/tools/docker/run.sh @@ -2,6 +2,8 @@ # This is an example of how to run the docker container. # This script is not part of the container, it is meant to be run on the host machine. +# Note that this file will build the release/v5.3 branch. For other branches, change the tag accordingly. +# You can check the available tags at https://hub.docker.com/r/espressif/esp32-arduino-lib-builder/tags # Usage: ./run.sh if ! [ -x "$(command -v docker)" ]; then @@ -31,4 +33,4 @@ if [ -n "$LIBBUILDER_GIT_SAFE_DIR" ]; then fi echo "Running: docker run ${DOCKER_ARGS[@]} espressif/esp32-arduino-lib-builder" -docker run ${DOCKER_ARGS[@]} espressif/esp32-arduino-lib-builder +docker run ${DOCKER_ARGS[@]} espressif/esp32-arduino-lib-builder:release-v5.3 From 3ff7a1e6cea89adbf2debfaf33d344d45e9845f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Wed, 6 Nov 2024 10:49:37 +0100 Subject: [PATCH 24/38] fix(zigbee): Unlink the zigbee libs (#242) --- tools/copy-libs.sh | 64 ++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/tools/copy-libs.sh b/tools/copy-libs.sh index bbc89e089..cb79ab502 100755 --- a/tools/copy-libs.sh +++ b/tools/copy-libs.sh @@ -56,6 +56,8 @@ AS_FLAGS="" INCLUDES="" DEFINES="" +EXCLUDE_LIBS=";" + LD_FLAGS="" LD_LIBS="" LD_LIB_FILES="" @@ -78,6 +80,17 @@ else TOOLCHAIN="riscv32-esp-elf" fi +# copy zigbee + zboss lib +if [ -d "managed_components/espressif__esp-zigbee-lib/lib/$IDF_TARGET/" ]; then + cp -r "managed_components/espressif__esp-zigbee-lib/lib/$IDF_TARGET"/* "$AR_SDK/lib/" + EXCLUDE_LIBS+="esp_zb_api_ed;" +fi + +if [ -d "managed_components/espressif__esp-zboss-lib/lib/$IDF_TARGET/" ]; then + cp -r "managed_components/espressif__esp-zboss-lib/lib/$IDF_TARGET"/* "$AR_SDK/lib/" + EXCLUDE_LIBS+="zboss_stack.ed;zboss_port.debug;" +fi + #collect includes, defines and c-flags str=`cat build/compile_commands.json | grep arduino-lib-builder-gcc.c | grep command | cut -d':' -f2 | cut -d',' -f1` str="${str:2:${#str}-1}" #remove leading space and quotes @@ -200,12 +213,14 @@ for item; do add_next=1 LD_FLAGS+="$item " elif [ "${item:0:2}" = "-l" ]; then # -l[lib_name] - LD_LIBS+="$item " - exclude_libs=";m;c;gcc;stdc++;" short_name="${item:2}" - if [[ $exclude_libs != *";$short_name;"* && $LD_LIBS_SEARCH != *"lib$short_name.a"* ]]; then - LD_LIBS_SEARCH+="lib$short_name.a " - #echo "lib add: $item" + if [[ $EXCLUDE_LIBS != *";$short_name;"* ]]; then + LD_LIBS+="$item " + exclude_libs=";m;c;gcc;stdc++;" + if [[ $exclude_libs != *";$short_name;"* && $LD_LIBS_SEARCH != *"lib$short_name.a"* ]]; then + LD_LIBS_SEARCH+="lib$short_name.a " + #echo "1. lib add: $item" + fi fi elif [ "$item" = "-o" ]; then add_next=0 @@ -244,30 +259,38 @@ for item; do if [[ $LD_LIB_FILES != *"$item"* ]]; then # do we already have lib with the same name? if [[ $LD_LIBS != *"-l$lname"* ]]; then - # echo "collecting lib '$lname' and file: $item" - LD_LIB_FILES+="$item " - LD_LIBS+="-l$lname " + if [[ $EXCLUDE_LIBS != *";$lname;"* ]]; then + #echo "2. collecting lib '$lname' and file: $item" + LD_LIB_FILES+="$item " + LD_LIBS+="-l$lname " + fi else # echo "!!! need to rename: '$lname'" for i in {2..9}; do n_item="${item:0:${#item}-2}_$i.a" n_name=$lname"_$i" if [ -f "$n_item" ]; then - # echo "renamed add: -l$n_name" - LD_LIBS+="-l$n_name " + if [[ $EXCLUDE_LIBS != *";$lname;"* ]]; then + #echo "3. renamed add: -l$n_name" + LD_LIBS+="-l$n_name " + fi break elif [[ $LD_LIB_FILES != *"$n_item"* && $LD_LIBS != *"-l$n_name"* ]]; then - echo "Renaming '$lname' to '$n_name': $item" - cp -f "$item" "$n_item" - LD_LIB_FILES+="$n_item " - LD_LIBS+="-l$n_name " + if [[ $EXCLUDE_LIBS != *";$lname;"* ]]; then + #echo "4. Renaming '$lname' to '$n_name': $item" + cp -f "$item" "$n_item" + LD_LIB_FILES+="$n_item " + LD_LIBS+="-l$n_name " + fi break fi done fi else - # echo "just add: -l$lname" - LD_LIBS+="-l$lname " + if [[ $EXCLUDE_LIBS != *";$lname;"* ]]; then + #echo "5. just add: -l$lname" + LD_LIBS+="-l$lname " + fi fi else echo "*** Skipping $(basename $item): size too small $lsize" @@ -502,15 +525,6 @@ sed 's/CHIP_ADDRESS_RESOLVE_IMPL_INCLUDE_HEADER/ Date: Wed, 6 Nov 2024 12:32:32 +0100 Subject: [PATCH 25/38] fix(): Move mkdir to top as its already used --- tools/copy-libs.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/copy-libs.sh b/tools/copy-libs.sh index cb79ab502..1c03d55cb 100755 --- a/tools/copy-libs.sh +++ b/tools/copy-libs.sh @@ -39,7 +39,9 @@ fi if [ -e "$AR_SDK/platformio-build.py" ]; then rm -rf "$AR_SDK/platformio-build.py" fi + mkdir -p "$AR_SDK" +mkdir -p "$AR_SDK/lib" function get_actual_path(){ p="$PWD"; cd "$1"; r="$PWD"; cd "$p"; echo "$r"; @@ -450,8 +452,6 @@ echo " join(FRAMEWORK_DIR, \"cores\", board_config.get(\"build.core\"))" echo " ]," >> "$AR_PLATFORMIO_PY" echo "" >> "$AR_PLATFORMIO_PY" -mkdir -p "$AR_SDK/lib" - AR_LIBS="$LD_LIBS" PIO_LIBS="" set -- $LD_LIBS From 1f5245926ad31a075532c1b5ac00b537f36c6678 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 12 Nov 2024 22:31:51 +0200 Subject: [PATCH 26/38] Update TinyUSB DCD Source --- .../arduino_tinyusb/patches/dcd_dwc2.patch | 15 +- components/arduino_tinyusb/src/dcd_dwc2.c | 493 ++++-------------- tools/patch-tinyusb.sh | 4 + 3 files changed, 118 insertions(+), 394 deletions(-) create mode 100755 tools/patch-tinyusb.sh diff --git a/components/arduino_tinyusb/patches/dcd_dwc2.patch b/components/arduino_tinyusb/patches/dcd_dwc2.patch index e93f9629b..9307bd8d0 100644 --- a/components/arduino_tinyusb/patches/dcd_dwc2.patch +++ b/components/arduino_tinyusb/patches/dcd_dwc2.patch @@ -1,6 +1,6 @@ --- a/components/arduino_tinyusb/src/dcd_dwc2.c 2024-10-02 12:17:40.000000000 +0300 +++ b/components/arduino_tinyusb/src/dcd_dwc2.c 2024-10-02 12:19:48.000000000 +0300 -@@ -316,6 +316,16 @@ +@@ -209,6 +209,17 @@ //-------------------------------------------------------------------- // Endpoint //-------------------------------------------------------------------- @@ -14,10 +14,11 @@ + return 0; +} +#endif - ++ static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); -@@ -332,7 +342,19 @@ + uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); +@@ -224,7 +235,19 @@ (p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DOEPCTL_SD0PID_SEVNFRM : 0) | (xfer->max_size << DOEPCTL_MPSIZ_Pos); if (dir == TUSB_DIR_IN) { @@ -38,7 +39,7 @@ } dwc2_dep_t* dep = &dwc2->ep[1 - dir][epnum]; -@@ -840,6 +862,10 @@ +@@ -304,6 +327,10 @@ } } @@ -49,7 +50,7 @@ dfifo_flush_tx(dwc2, 0x10); // all tx fifo dfifo_flush_rx(dwc2); -@@ -1186,6 +1212,9 @@ +@@ -908,6 +935,9 @@ if (int_status & GINTSTS_USBRST) { // USBRST is start of reset. dwc2->gintsts = GINTSTS_USBRST; @@ -59,7 +60,7 @@ bus_reset(rhport); } -@@ -1217,7 +1246,11 @@ +@@ -939,7 +969,11 @@ if (int_status & GINTSTS_USBSUSP) { dwc2->gintsts = GINTSTS_USBSUSP; @@ -72,7 +73,7 @@ } if (int_status & GINTSTS_WKUINT) { -@@ -1234,6 +1267,9 @@ +@@ -956,6 +990,9 @@ if (otg_int & GOTGINT_SEDET) { dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); diff --git a/components/arduino_tinyusb/src/dcd_dwc2.c b/components/arduino_tinyusb/src/dcd_dwc2.c index e76bdf70e..035e335cd 100644 --- a/components/arduino_tinyusb/src/dcd_dwc2.c +++ b/components/arduino_tinyusb/src/dcd_dwc2.c @@ -35,45 +35,7 @@ #define DWC2_DEBUG 2 #include "device/dcd.h" -#include "dwc2_type.h" - -// Following symbols must be defined by port header -// - _dwc2_controller[]: array of controllers -// - DWC2_EP_MAX: largest EP counts of all controllers -// - dwc2_phy_init/dwc2_phy_update: phy init called before and after core reset -// - dwc2_dcd_int_enable/dwc2_dcd_int_disable -// - dwc2_remote_wakeup_delay - -#if defined(TUP_USBIP_DWC2_STM32) - #include "dwc2_stm32.h" -#elif defined(TUP_USBIP_DWC2_ESP32) - #include "dwc2_esp32.h" -#elif TU_CHECK_MCU(OPT_MCU_GD32VF103) - #include "dwc2_gd32.h" -#elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837) - #include "dwc2_bcm.h" -#elif TU_CHECK_MCU(OPT_MCU_EFM32GG) - #include "dwc2_efm32.h" -#elif TU_CHECK_MCU(OPT_MCU_XMC4000) - #include "dwc2_xmc.h" -#else - #error "Unsupported MCUs" -#endif - -enum { - DWC2_CONTROLLER_COUNT = TU_ARRAY_SIZE(_dwc2_controller) -}; - -// DWC2 registers -//#define DWC2_REG(_port) ((dwc2_regs_t*) _dwc2_controller[_port].reg_base) - -TU_ATTR_ALWAYS_INLINE static inline dwc2_regs_t* DWC2_REG(uint8_t rhport) { - if (rhport >= DWC2_CONTROLLER_COUNT) { - // user mis-configured, ignore and use first controller - rhport = 0; - } - return (dwc2_regs_t*) _dwc2_controller[rhport].reg_base; -} +#include "dwc2_common.h" //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM @@ -94,7 +56,7 @@ static xfer_ctl_t xfer_status[DWC2_EP_MAX][2]; // EP0 transfers are limited to 1 packet - larger sizes has to be split static uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type -static uint16_t _dfifo_top; // top free location in FIFO RAM +static uint16_t _dfifo_top; // top free location in DFIFO in words // Number of IN endpoints active static uint8_t _allocated_ep_in_count; @@ -106,20 +68,10 @@ static bool _sof_en; // DMA //-------------------------------------------------------------------- -TU_ATTR_ALWAYS_INLINE static inline bool dma_enabled(const dwc2_regs_t* dwc2) { - #if !CFG_TUD_DWC2_DMA +TU_ATTR_ALWAYS_INLINE static inline bool dma_device_enabled(const dwc2_regs_t* dwc2) { (void) dwc2; - return false; - #else // Internal DMA only - return (dwc2->ghwcfg2_bm.arch == GHWCFG2_ARCH_INTERNAL_DMA); - #endif -} - -TU_ATTR_ALWAYS_INLINE static inline uint16_t dma_cal_epfifo_base(uint8_t rhport) { - // Scatter/Gather DMA mode is not yet supported. Buffer DMA only need 1 words per endpoint direction - const dwc2_controller_t* dwc2_controller = &_dwc2_controller[rhport]; - return dwc2_controller->ep_fifo_size/4 - 2*dwc2_controller->ep_count; + return CFG_TUD_DWC2_DMA && dwc2->ghwcfg2_bm.arch == GHWCFG2_ARCH_INTERNAL_DMA; } static void dma_setup_prepare(uint8_t rhport) { @@ -141,18 +93,8 @@ static void dma_setup_prepare(uint8_t rhport) { // Data FIFO //--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_tx(dwc2_regs_t* dwc2, uint8_t epnum) { - // flush TX fifo and wait for it cleared - dwc2->grstctl = GRSTCTL_TXFFLSH | (epnum << GRSTCTL_TXFNUM_Pos); - while (dwc2->grstctl & GRSTCTL_TXFFLSH_Msk) {} -} -TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_rx(dwc2_regs_t* dwc2) { - // flush RX fifo and wait for it cleared - dwc2->grstctl = GRSTCTL_RXFFLSH; - while (dwc2->grstctl & GRSTCTL_RXFFLSH_Msk) {} -} -/* USB Data FIFO Layout +/* Device Data FIFO scheme The FIFO is split up into - EPInfo: for storing DMA metadata, only required when use DMA. Maximum size is called @@ -167,11 +109,9 @@ TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_rx(dwc2_regs_t* dwc2) { possible since the free space is located between the RX and TX FIFOs. ---------------- ep_fifo_size - | EPInfo | - | for DMA | + | DxEPIDMAn | |-------------|-- gdfifocfg.EPINFOBASE (max is ghwcfg3.dfifo_depth) - | IN FIFO 0 | - | control | + | IN FIFO 0 | control EP |-------------| | IN FIFO 1 | |-------------| @@ -190,13 +130,13 @@ TU_ATTR_ALWAYS_INLINE static inline void dfifo_flush_rx(dwc2_regs_t* dwc2) { - All EP OUT shared a unique OUT FIFO which uses (for Slave or Buffer DMA, Scatt/Gather DMA use different formula): - 13 for setup packets + control words (up to 3 setup packets). - 1 for global NAK (not required/used here). - - Largest-EPsize / 4 + 1. ( FS: 64 bytes, HS: 512 bytes). Recommended is "2 x (Largest-EPsize/4) + 1" + - Largest-EPsize/4 + 1. ( FS: 64 bytes, HS: 512 bytes). Recommended is "2 x (Largest-EPsize/4 + 1)" - 2 for each used OUT endpoint Therefore GRXFSIZ = 13 + 1 + 2 x (Largest-EPsize/4 + 1) + 2 x EPOUTnum */ -TU_ATTR_ALWAYS_INLINE static inline uint16_t calc_grxfsiz(uint16_t largest_ep_size, uint8_t ep_count) { +TU_ATTR_ALWAYS_INLINE static inline uint16_t calc_device_grxfsiz(uint16_t largest_ep_size, uint8_t ep_count) { return 13 + 1 + 2 * ((largest_ep_size / 4) + 1) + 2 * ep_count; } @@ -212,7 +152,7 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { uint16_t fifo_size = tu_div_ceil(packet_size, 4); if (dir == TUSB_DIR_OUT) { // Calculate required size of RX FIFO - uint16_t const new_sz = calc_grxfsiz(4 * fifo_size, ep_count); + uint16_t const new_sz = calc_device_grxfsiz(4 * fifo_size, ep_count); // If size_rx needs to be extended check if there is enough free space if (dwc2->grxfsiz < new_sz) { @@ -227,7 +167,7 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { } // If The TXFELVL is configured as half empty, the fifo must be twice the max_size. - if ((dwc2->gahbcfg & GAHBCFG_TXFELVL) == 0) { + if ((dwc2->gahbcfg & GAHBCFG_TX_FIFO_EPMTY_LVL) == 0) { fifo_size *= 2; } @@ -248,70 +188,23 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { return true; } -static void dfifo_init(uint8_t rhport) { +static void dfifo_device_init(uint8_t rhport) { const dwc2_controller_t* dwc2_controller = &_dwc2_controller[rhport]; dwc2_regs_t* dwc2 = DWC2_REG(rhport); - dwc2->grxfsiz = calc_grxfsiz(CFG_TUD_ENDPOINT0_SIZE, dwc2_controller->ep_count); + dwc2->grxfsiz = calc_device_grxfsiz(CFG_TUD_ENDPOINT0_SIZE, dwc2_controller->ep_count); - if(dma_enabled(dwc2)) { - // DMA use last DFIFO to store metadata - _dfifo_top = dma_cal_epfifo_base(rhport); - }else { - _dfifo_top = dwc2_controller->ep_fifo_size / 4; + // Scatter/Gather DMA mode is not yet supported. Buffer DMA only need 1 words per endpoint direction + const bool is_dma = dma_device_enabled(dwc2); + _dfifo_top = dwc2_controller->ep_fifo_size/4; + if (is_dma) { + _dfifo_top -= 2 * dwc2_controller->ep_count; } + dwc2->gdfifocfg = (_dfifo_top << GDFIFOCFG_EPINFOBASE_SHIFT) | _dfifo_top; // Allocate FIFO for EP0 IN dfifo_alloc(rhport, 0x80, CFG_TUD_ENDPOINT0_SIZE); } -// Read a single data packet from receive FIFO -static void dfifo_read_packet(uint8_t rhport, uint8_t* dst, uint16_t len) { - (void) rhport; - - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - volatile const uint32_t* rx_fifo = dwc2->fifo[0]; - - // Reading full available 32 bit words from fifo - uint16_t full_words = len >> 2; - while (full_words--) { - tu_unaligned_write32(dst, *rx_fifo); - dst += 4; - } - - // Read the remaining 1-3 bytes from fifo - uint8_t const bytes_rem = len & 0x03; - if (bytes_rem != 0) { - uint32_t const tmp = *rx_fifo; - dst[0] = tu_u32_byte0(tmp); - if (bytes_rem > 1) dst[1] = tu_u32_byte1(tmp); - if (bytes_rem > 2) dst[2] = tu_u32_byte2(tmp); - } -} - -// Write a single data packet to EPIN FIFO -static void dfifo_write_packet(uint8_t rhport, uint8_t fifo_num, uint8_t const* src, uint16_t len) { - (void) rhport; - - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - volatile uint32_t* tx_fifo = dwc2->fifo[fifo_num]; - - // Pushing full available 32 bit words to fifo - uint16_t full_words = len >> 2; - while (full_words--) { - *tx_fifo = tu_unaligned_read32(src); - src += 4; - } - - // Write the remaining 1-3 bytes into fifo - uint8_t const bytes_rem = len & 0x03; - if (bytes_rem) { - uint32_t tmp_word = src[0]; - if (bytes_rem > 1) tmp_word |= (src[1] << 8); - if (bytes_rem > 2) tmp_word |= (src[2] << 16); - - *tx_fifo = tmp_word; - } -} //-------------------------------------------------------------------- // Endpoint @@ -326,7 +219,7 @@ static uint8_t get_free_fifo(void) { return 0; } #endif - + static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); @@ -434,6 +327,10 @@ static void bus_reset(uint8_t rhport) { } } +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + _allocated_fifos = 1; +#endif + dfifo_flush_tx(dwc2, 0x10); // all tx fifo dfifo_flush_rx(dwc2); @@ -443,7 +340,7 @@ static void bus_reset(uint8_t rhport) { dwc2->diepmsk = DIEPMSK_TOM | DIEPMSK_XFRCM; // 4. Set up DFIFO - dfifo_init(rhport); + dfifo_device_init(rhport); // 5. Reset device address dwc2->dcfg &= ~DCFG_DAD_Msk; @@ -455,7 +352,7 @@ static void bus_reset(uint8_t rhport) { xfer_status[0][TUSB_DIR_OUT].max_size = 64; xfer_status[0][TUSB_DIR_IN].max_size = 64; - if(dma_enabled(dwc2)) { + if(dma_device_enabled(dwc2)) { dma_setup_prepare(rhport); } else { dwc2->epout[0].doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); @@ -485,9 +382,9 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c if (dir == TUSB_DIR_IN) { // A full IN transfer (multiple packets, possibly) triggers XFRC. dep->dieptsiz = (num_packets << DIEPTSIZ_PKTCNT_Pos) | - ((total_bytes << DIEPTSIZ_XFRSIZ_Pos) & DIEPTSIZ_XFRSIZ_Msk); + ((total_bytes << DIEPTSIZ_XFRSIZ_Pos) & DIEPTSIZ_XFRSIZ_Msk); - if(dma_enabled(dwc2)) { + if(dma_device_enabled(dwc2)) { dep->diepdma = (uintptr_t)xfer->buffer; // For ISO endpoint set correct odd/even bit for next frame. @@ -525,7 +422,7 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c dep->doepctl |= (odd_frame_now ? DOEPCTL_SD0PID_SEVNFRM_Msk : DOEPCTL_SODDFRM_Msk); } - if(dma_enabled(dwc2)) { + if(dma_device_enabled(dwc2)) { dep->doepdma = (uintptr_t)xfer->buffer; } @@ -533,174 +430,41 @@ static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t c } } -/*------------------------------------------------------------------*/ -/* Controller API - *------------------------------------------------------------------*/ - -static void reset_core(dwc2_regs_t* dwc2) { - // reset core - dwc2->grstctl |= GRSTCTL_CSRST; - - // wait for reset bit is cleared - // TODO version 4.20a should wait for RESET DONE mask - while (dwc2->grstctl & GRSTCTL_CSRST) {} - - // wait for AHB master IDLE - while (!(dwc2->grstctl & GRSTCTL_AHBIDL)) {} - - // wait for device mode ? -} - -static bool phy_hs_supported(dwc2_regs_t* dwc2) { - (void) dwc2; - -#if !TUD_OPT_HIGH_SPEED - return false; -#else - return dwc2->ghwcfg2_bm.hs_phy_type != GHWCFG2_HSPHY_NOT_SUPPORTED; -#endif -} - -static void phy_fs_init(dwc2_regs_t* dwc2) { - TU_LOG(DWC2_DEBUG, "Fullspeed PHY init\r\n"); - - // Select FS PHY - dwc2->gusbcfg |= GUSBCFG_PHYSEL; - - // MCU specific PHY init before reset - dwc2_phy_init(dwc2, GHWCFG2_HSPHY_NOT_SUPPORTED); - - // Reset core after selecting PHY - reset_core(dwc2); - - // USB turnaround time is critical for certification where long cables and 5-Hubs are used. - // So if you need the AHB to run at less than 30 MHz, and if USB turnaround time is not critical, - // these bits can be programmed to a larger value. Default is 5 - dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_TRDT_Msk) | (5u << GUSBCFG_TRDT_Pos); - - // MCU specific PHY update post reset - dwc2_phy_update(dwc2, GHWCFG2_HSPHY_NOT_SUPPORTED); - - // set max speed - dwc2->dcfg = (dwc2->dcfg & ~DCFG_DSPD_Msk) | (DCFG_DSPD_FS << DCFG_DSPD_Pos); -} - -static void phy_hs_init(dwc2_regs_t* dwc2) { - uint32_t gusbcfg = dwc2->gusbcfg; - - // De-select FS PHY - gusbcfg &= ~GUSBCFG_PHYSEL; - - if (dwc2->ghwcfg2_bm.hs_phy_type == GHWCFG2_HSPHY_ULPI) { - TU_LOG(DWC2_DEBUG, "Highspeed ULPI PHY init\r\n"); - - // Select ULPI - gusbcfg |= GUSBCFG_ULPI_UTMI_SEL; - - // ULPI 8-bit interface, single data rate - gusbcfg &= ~(GUSBCFG_PHYIF16 | GUSBCFG_DDRSEL); - - // default internal VBUS Indicator and Drive - gusbcfg &= ~(GUSBCFG_ULPIEVBUSD | GUSBCFG_ULPIEVBUSI); - - // Disable FS/LS ULPI - gusbcfg &= ~(GUSBCFG_ULPIFSLS | GUSBCFG_ULPICSM); - } else { - TU_LOG(DWC2_DEBUG, "Highspeed UTMI+ PHY init\r\n"); - - // Select UTMI+ with 8-bit interface - gusbcfg &= ~(GUSBCFG_ULPI_UTMI_SEL | GUSBCFG_PHYIF16); - - // Set 16-bit interface if supported - if (dwc2->ghwcfg4_bm.phy_data_width) { - gusbcfg |= GUSBCFG_PHYIF16; - } - } - - // Apply config - dwc2->gusbcfg = gusbcfg; - - // mcu specific phy init - dwc2_phy_init(dwc2, dwc2->ghwcfg2_bm.hs_phy_type); - - // Reset core after selecting PHY - reset_core(dwc2); - - // Set turn-around, must after core reset otherwise it will be clear - // - 9 if using 8-bit PHY interface - // - 5 if using 16-bit PHY interface - gusbcfg &= ~GUSBCFG_TRDT_Msk; - gusbcfg |= (dwc2->ghwcfg4_bm.phy_data_width ? 5u : 9u) << GUSBCFG_TRDT_Pos; - dwc2->gusbcfg = gusbcfg; - - // MCU specific PHY update post reset - dwc2_phy_update(dwc2, dwc2->ghwcfg2_bm.hs_phy_type); - - // Set max speed - uint32_t dcfg = dwc2->dcfg; - dcfg &= ~DCFG_DSPD_Msk; - dcfg |= DCFG_DSPD_HS << DCFG_DSPD_Pos; - - // XCVRDLY: transceiver delay between xcvr_sel and txvalid during device chirp is required - // when using with some PHYs such as USB334x (USB3341, USB3343, USB3346, USB3347) - if (dwc2->ghwcfg2_bm.hs_phy_type == GHWCFG2_HSPHY_ULPI) { - dcfg |= DCFG_XCVRDLY; - } - - dwc2->dcfg = dcfg; -} - -static bool check_dwc2(dwc2_regs_t* dwc2) { -#if CFG_TUSB_DEBUG >= DWC2_DEBUG - // print guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4 - // Run 'python dwc2_info.py' and check dwc2_info.md for bit-field value and comparison with other ports - volatile uint32_t const* p = (volatile uint32_t const*) &dwc2->guid; - TU_LOG1("guid, gsnpsid, ghwcfg1, ghwcfg2, ghwcfg3, ghwcfg4\r\n"); - for (size_t i = 0; i < 5; i++) { - TU_LOG1("0x%08" PRIX32 ", ", p[i]); - } - TU_LOG1("0x%08" PRIX32 "\r\n", p[5]); -#endif - - // For some reason: GD32VF103 snpsid and all hwcfg register are always zero (skip it) - (void) dwc2; -#if !TU_CHECK_MCU(OPT_MCU_GD32VF103) - uint32_t const gsnpsid = dwc2->gsnpsid & GSNPSID_ID_MASK; - TU_ASSERT(gsnpsid == DWC2_OTG_ID || gsnpsid == DWC2_FS_IOT_ID || gsnpsid == DWC2_HS_IOT_ID); -#endif - - return true; -} - +//-------------------------------------------------------------------- +// Controller API +//-------------------------------------------------------------------- bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rhport; (void) rh_init; - // Programming model begins in the last section of the chapter on the USB - // peripheral in each Reference Manual. dwc2_regs_t* dwc2 = DWC2_REG(rhport); - // Check Synopsys ID register, failed if controller clock/power is not enabled - TU_ASSERT(check_dwc2(dwc2)); - dcd_disconnect(rhport); + // Core Initialization + const bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_DEVICE); + TU_ASSERT(dwc2_core_init(rhport, is_highspeed)); - if (phy_hs_supported(dwc2)) { - phy_hs_init(dwc2); // Highspeed + if (dma_device_enabled(dwc2)) { + // DMA seems to be only settable after a core reset, and not possible to switch on-the-fly + dwc2->gahbcfg |= GAHBCFG_DMAEN | GAHBCFG_HBSTLEN_2; } else { - phy_fs_init(dwc2); // core does not support highspeed or hs phy is not present + dwc2->gintmsk |= GINTSTS_RXFLVL; } - // Restart PHY clock - dwc2->pcgctl &= ~(PCGCTL_STOPPCLK | PCGCTL_GATEHCLK | PCGCTL_PWRCLMP | PCGCTL_RSTPDWNMODULE); + // Device Initialization + dcd_disconnect(rhport); + + // Set device max speed + uint32_t dcfg = dwc2->dcfg & ~DCFG_DSPD_Msk; + if (is_highspeed) { + dcfg |= DCFG_DSPD_HS << DCFG_DSPD_Pos; - /* Set HS/FS Timeout Calibration to 7 (max available value). - * The number of PHY clocks that the application programs in - * this field is added to the high/full speed interpacket timeout - * duration in the core to account for any additional delays - * introduced by the PHY. This can be required, because the delay - * introduced by the PHY in generating the linestate condition - * can vary from one PHY to another. - */ - dwc2->gusbcfg |= (7ul << GUSBCFG_TOCAL_Pos); + // XCVRDLY: transceiver delay between xcvr_sel and txvalid during device chirp is required + // when using with some PHYs such as USB334x (USB3341, USB3343, USB3346, USB3347) + if (dwc2->ghwcfg2_bm.hs_phy_type == GHWCFG2_HSPHY_ULPI) { + dcfg |= DCFG_XCVRDLY; + } + }else { + dcfg |= DCFG_DSPD_FS << DCFG_DSPD_Pos; + } + dwc2->dcfg = dcfg; // Force device mode dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_FHMOD) | GUSBCFG_FDMOD; @@ -708,48 +472,19 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Clear A override, force B Valid dwc2->gotgctl = (dwc2->gotgctl & ~GOTGCTL_AVALOEN) | GOTGCTL_BVALOEN | GOTGCTL_BVALOVAL; - // If USB host misbehaves during status portion of control xfer - // (non zero-length packet), send STALL back and discard. + // If USB host misbehaves during status portion of control xfer (non zero-length packet), send STALL back and discard dwc2->dcfg |= DCFG_NZLSOHSK; - dfifo_flush_tx(dwc2, 0x10); // all tx fifo - dfifo_flush_rx(dwc2); - - // Clear all interrupts - uint32_t int_mask = dwc2->gintsts; - dwc2->gintsts |= int_mask; - int_mask = dwc2->gotgint; - dwc2->gotgint |= int_mask; - - // Required as part of core initialization. - dwc2->gintmsk = GINTMSK_OTGINT | GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM; - - // Configure TX FIFO empty level for interrupt. Default is complete empty - dwc2->gahbcfg |= GAHBCFG_TXFELVL; - - if (dma_enabled(dwc2)) { - const uint16_t epinfo_base = dma_cal_epfifo_base(rhport); - dwc2->gdfifocfg = (epinfo_base << GDFIFOCFG_EPINFOBASE_SHIFT) | epinfo_base; + // Enable required interrupts + dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM; - // DMA seems to be only settable after a core reset - dwc2->gahbcfg |= GAHBCFG_DMAEN | GAHBCFG_HBSTLEN_2; - }else { - dwc2->gintmsk |= GINTMSK_RXFLVLM; - } - - // Enable global interrupt - dwc2->gahbcfg |= GAHBCFG_GINT; - - // make sure we are in device mode -// TU_ASSERT(!(dwc2->gintsts & GINTSTS_CMOD), ); - -// TU_LOG_HEX(DWC2_DEBUG, dwc2->gotgctl); -// TU_LOG_HEX(DWC2_DEBUG, dwc2->gusbcfg); -// TU_LOG_HEX(DWC2_DEBUG, dwc2->dcfg); -// TU_LOG_HEX(DWC2_DEBUG, dwc2->gahbcfg); + // TX FIFO empty level for interrupt is complete empty + uint32_t gahbcfg = dwc2->gahbcfg; + gahbcfg |= GAHBCFG_TX_FIFO_EPMTY_LVL; + gahbcfg |= GAHBCFG_GINT; // Enable global interrupt + dwc2->gahbcfg = gahbcfg; dcd_connect(rhport); - return true; } @@ -866,14 +601,10 @@ void dcd_edpt_close_all(uint8_t rhport) { } } -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) - _allocated_fifos = 1; -#endif - dfifo_flush_tx(dwc2, 0x10); // all tx fifo dfifo_flush_rx(dwc2); - dfifo_init(rhport); // re-init dfifo + dfifo_device_init(rhport); // re-init dfifo } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { @@ -904,11 +635,10 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to // Schedule the first transaction for EP0 transfer edpt_schedule_packets(rhport, epnum, dir, 1, ep0_pending[dir]); } else { - uint16_t num_packets = (total_bytes / xfer->max_size); - uint16_t const short_packet_size = total_bytes % xfer->max_size; - - // Zero-size packet is special case. - if ((short_packet_size > 0) || (total_bytes == 0)) num_packets++; + uint16_t num_packets = tu_div_ceil(total_bytes, xfer->max_size); + if (num_packets == 0) { + num_packets = 1; // zero length packet still count as 1 + } // Schedule packets to be sent within interrupt edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); @@ -952,8 +682,9 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { } void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); edpt_disable(rhport, ep_addr, true); - if((tu_edpt_number(ep_addr) == 0) && dma_enabled(DWC2_REG(rhport))) { + if((tu_edpt_number(ep_addr) == 0) && dma_device_enabled(dwc2)) { dma_setup_prepare(rhport); } } @@ -976,16 +707,15 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { // Process shared receive FIFO, this interrupt is only used in Slave mode static void handle_rxflvl_irq(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); - volatile uint32_t const* rx_fifo = dwc2->fifo[0]; + const volatile uint32_t* rx_fifo = dwc2->fifo[0]; // Pop control word off FIFO - uint32_t const grxstsp = dwc2->grxstsp; - uint8_t const pktsts = (grxstsp & GRXSTSP_PKTSTS_Msk) >> GRXSTSP_PKTSTS_Pos; - uint8_t const epnum = (grxstsp & GRXSTSP_EPNUM_Msk) >> GRXSTSP_EPNUM_Pos; - uint16_t const bcnt = (grxstsp & GRXSTSP_BCNT_Msk) >> GRXSTSP_BCNT_Pos; + const dwc2_grxstsp_t grxstsp_bm = dwc2->grxstsp_bm; + const uint8_t epnum = grxstsp_bm.ep_ch_num; + const uint16_t byte_count = grxstsp_bm.byte_count; dwc2_epout_t* epout = &dwc2->epout[epnum]; - switch (pktsts) { + switch (grxstsp_bm.packet_status) { // Global OUT NAK: do nothing case GRXSTS_PKTSTS_GLOBALOUTNAK: break; @@ -1010,18 +740,18 @@ static void handle_rxflvl_irq(uint8_t rhport) { // Read packet off RxFIFO if (xfer->ff) { // Ring buffer - tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void*) (uintptr_t) rx_fifo, bcnt); + tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void*) (uintptr_t) rx_fifo, byte_count); } else { // Linear buffer - dfifo_read_packet(rhport, xfer->buffer, bcnt); + dfifo_read_packet(dwc2, xfer->buffer, byte_count); // Increment pointer to xfer data - xfer->buffer += bcnt; + xfer->buffer += byte_count; } - // Truncate transfer length in case of short packet - if (bcnt < xfer->max_size) { - xfer->total_len -= (epout->doeptsiz & DOEPTSIZ_XFRSIZ_Msk) >> DOEPTSIZ_XFRSIZ_Pos; + // short packet, minus remaining bytes (xfer_size) + if (byte_count < xfer->max_size) { + xfer->total_len -= epout->doeptsiz_bm.xfer_size; if (epnum == 0) { xfer->total_len -= ep0_pending[TUSB_DIR_OUT]; ep0_pending[TUSB_DIR_OUT] = 0; @@ -1070,7 +800,7 @@ static void handle_epout_irq(uint8_t rhport) { if (doepint & DOEPINT_SETUP) { epout->doepint = DOEPINT_SETUP; - if(dma_enabled(dwc2)) { + if(dma_device_enabled(dwc2)) { dma_setup_prepare(rhport); } @@ -1086,7 +816,7 @@ static void handle_epout_irq(uint8_t rhport) { if (!(doepint & (DOEPINT_SETUP | DOEPINT_STPKTRX | DOEPINT_STSPHSRX))) { xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - if(dma_enabled(dwc2)) { + if(dma_device_enabled(dwc2)) { if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) { // EP0 can only handle one packet Schedule another packet to be received. edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); @@ -1118,8 +848,7 @@ static void handle_epout_irq(uint8_t rhport) { static void handle_epin_irq(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); - uint8_t const ep_count = _dwc2_controller[rhport].ep_count; - dwc2_epin_t* epin = dwc2->epin; + const uint8_t ep_count = _dwc2_controller[rhport].ep_count; // DAINT for a given EP clears when DIEPINTx is cleared. // IEPINT will be cleared when DAINT's out bits are cleared. @@ -1127,16 +856,17 @@ static void handle_epin_irq(uint8_t rhport) { if (dwc2->daint & TU_BIT(DAINT_IEPINT_Pos + n)) { // IN XFER complete (entire xfer). xfer_ctl_t* xfer = XFER_CTL_BASE(n, TUSB_DIR_IN); + dwc2_epin_t* epin = &dwc2->epin[n]; - if (epin[n].diepint & DIEPINT_XFRC) { - epin[n].diepint = DIEPINT_XFRC; + if (epin->diepint & DIEPINT_XFRC) { + epin->diepint = DIEPINT_XFRC; // EP0 can only handle one packet if ((n == 0) && ep0_pending[TUSB_DIR_IN]) { // Schedule another packet to be transmitted. edpt_schedule_packets(rhport, n, TUSB_DIR_IN, 1, ep0_pending[TUSB_DIR_IN]); } else { - if((n == 0) && dma_enabled(dwc2)) { + if((n == 0) && dma_device_enabled(dwc2)) { dma_setup_prepare(rhport); } dcd_event_xfer_complete(rhport, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); @@ -1144,39 +874,38 @@ static void handle_epin_irq(uint8_t rhport) { } // XFER FIFO empty - if ((epin[n].diepint & DIEPINT_TXFE) && (dwc2->diepempmsk & (1 << n))) { + if ((epin->diepint & DIEPINT_TXFE) && (dwc2->diepempmsk & (1 << n))) { // diepint's TXFE bit is read-only, software cannot clear it. // It will only be cleared by hardware when written bytes is more than // - 64 bytes or - // - Half of TX FIFO size (configured by DIEPTXF) - - uint16_t remaining_packets = (epin[n].dieptsiz & DIEPTSIZ_PKTCNT_Msk) >> DIEPTSIZ_PKTCNT_Pos; + // - Half/Empty of TX FIFO size (configured by GAHBCFG.TXFELVL) + const uint16_t remain_packets = epin->dieptsiz_bm.packet_count; // Process every single packet (only whole packets can be written to fifo) - for (uint16_t i = 0; i < remaining_packets; i++) { - uint16_t const remaining_bytes = (epin[n].dieptsiz & DIEPTSIZ_XFRSIZ_Msk) >> DIEPTSIZ_XFRSIZ_Pos; + for (uint16_t i = 0; i < remain_packets; i++) { + const uint16_t remain_bytes = (uint16_t) epin->dieptsiz_bm.xfer_size; // Packet can not be larger than ep max size - uint16_t const packet_size = tu_min16(remaining_bytes, xfer->max_size); + const uint16_t xact_bytes = tu_min16(remain_bytes, xfer->max_size); // It's only possible to write full packets into FIFO. Therefore DTXFSTS register of current // EP has to be checked if the buffer can take another WHOLE packet - if (packet_size > ((epin[n].dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) break; + if (xact_bytes > ((epin->dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) { + break; + } // Push packet to Tx-FIFO if (xfer->ff) { volatile uint32_t* tx_fifo = dwc2->fifo[n]; - tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*) (uintptr_t) tx_fifo, packet_size); + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*) (uintptr_t) tx_fifo, xact_bytes); } else { - dfifo_write_packet(rhport, n, xfer->buffer, packet_size); - - // Increment pointer to xfer data - xfer->buffer += packet_size; + dfifo_write_packet(dwc2, n, xfer->buffer, xact_bytes); + xfer->buffer += xact_bytes; } } // Turn off TXFE if all bytes are written. - if (((epin[n].dieptsiz & DIEPTSIZ_XFRSIZ_Msk) >> DIEPTSIZ_XFRSIZ_Pos) == 0) { + if (epin->dieptsiz_bm.xfer_size == 0) { dwc2->diepempmsk &= ~(1 << n); } } @@ -1186,21 +915,11 @@ static void handle_epin_irq(uint8_t rhport) { /* Interrupt Hierarchy - DxEPMSK.XferComplMsk DxEPINTn.XferCompl - | | - +---------- AND --------+ - | - DAINT.xEPnInt DAINTMSK.xEPnMsk - | | - +---------- AND --------+ - | - GINTSTS.xEPInt GINTMSK.xEPIntMsk - | | - +---------- AND --------+ - | - GAHBCFG.GblIntrMsk - | - IRQn + DxEPINTn + | + DAINT.xEPn + | + GINTSTS: xEPInt Note: when OTG_MULTI_PROC_INTRPT = 1, Device Each endpoint interrupt deachint/deachmsk/diepeachmsk/doepeachmsk are combined to generate dedicated interrupt line for each endpoint. diff --git a/tools/patch-tinyusb.sh b/tools/patch-tinyusb.sh new file mode 100755 index 000000000..eeaa4d43b --- /dev/null +++ b/tools/patch-tinyusb.sh @@ -0,0 +1,4 @@ +#!/bin/bash +mv components/arduino_tinyusb/src/dcd_dwc2.c components/arduino_tinyusb/src/dcd_dwc2.c.prev +cp components/arduino_tinyusb/tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c components/arduino_tinyusb/src/dcd_dwc2.c +patch -p1 -N -i components/arduino_tinyusb/patches/dcd_dwc2.patch From 117ef04ef070086717df16ca17f4800a1452675c Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Wed, 13 Nov 2024 00:15:06 +0200 Subject: [PATCH 27/38] Add missing compile source from TinyUSB --- components/arduino_tinyusb/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/components/arduino_tinyusb/CMakeLists.txt b/components/arduino_tinyusb/CMakeLists.txt index 6a2e35150..a3965728d 100755 --- a/components/arduino_tinyusb/CMakeLists.txt +++ b/components/arduino_tinyusb/CMakeLists.txt @@ -28,6 +28,7 @@ if(CONFIG_TINYUSB_ENABLED) "${COMPONENT_DIR}/src/dcd_dwc2.c" # tusb: #"{COMPONENT_DIR}/tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c" + "{COMPONENT_DIR}/tinyusb/src/portable/synopsys/dwc2/dwc2_common.c" "${COMPONENT_DIR}/tinyusb/src/class/cdc/cdc_device.c" "${COMPONENT_DIR}/tinyusb/src/class/hid/hid_device.c" "${COMPONENT_DIR}/tinyusb/src/class/midi/midi_device.c" From 70f28a9a64bf1d5d7ab9a1d9e4bd4185d531e9f3 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Wed, 13 Nov 2024 00:45:52 +0200 Subject: [PATCH 28/38] Fix path to TinyUSB dwc2_common.c --- components/arduino_tinyusb/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/arduino_tinyusb/CMakeLists.txt b/components/arduino_tinyusb/CMakeLists.txt index a3965728d..fd6f5983d 100755 --- a/components/arduino_tinyusb/CMakeLists.txt +++ b/components/arduino_tinyusb/CMakeLists.txt @@ -27,8 +27,8 @@ if(CONFIG_TINYUSB_ENABLED) # espressif: "${COMPONENT_DIR}/src/dcd_dwc2.c" # tusb: - #"{COMPONENT_DIR}/tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c" - "{COMPONENT_DIR}/tinyusb/src/portable/synopsys/dwc2/dwc2_common.c" + #"${COMPONENT_DIR}/tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c" + "${COMPONENT_DIR}/tinyusb/src/portable/synopsys/dwc2/dwc2_common.c" "${COMPONENT_DIR}/tinyusb/src/class/cdc/cdc_device.c" "${COMPONENT_DIR}/tinyusb/src/class/hid/hid_device.c" "${COMPONENT_DIR}/tinyusb/src/class/midi/midi_device.c" From 8bcf3eba6f6193b3b939489a0a5c935ba85274de Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 19 Nov 2024 00:44:56 +0200 Subject: [PATCH 29/38] Update TinyUSB DCD --- .../arduino_tinyusb/patches/dcd_dwc2.patch | 41 +- components/arduino_tinyusb/src/dcd_dwc2.c | 738 +++++++++--------- 2 files changed, 402 insertions(+), 377 deletions(-) diff --git a/components/arduino_tinyusb/patches/dcd_dwc2.patch b/components/arduino_tinyusb/patches/dcd_dwc2.patch index 9307bd8d0..0c45bb0ae 100644 --- a/components/arduino_tinyusb/patches/dcd_dwc2.patch +++ b/components/arduino_tinyusb/patches/dcd_dwc2.patch @@ -1,6 +1,6 @@ --- a/components/arduino_tinyusb/src/dcd_dwc2.c 2024-10-02 12:17:40.000000000 +0300 +++ b/components/arduino_tinyusb/src/dcd_dwc2.c 2024-10-02 12:19:48.000000000 +0300 -@@ -209,6 +209,17 @@ +@@ -215,6 +215,17 @@ //-------------------------------------------------------------------- // Endpoint //-------------------------------------------------------------------- @@ -17,13 +17,13 @@ + static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); - uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); -@@ -224,7 +235,19 @@ - (p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DOEPCTL_SD0PID_SEVNFRM : 0) | - (xfer->max_size << DOEPCTL_MPSIZ_Pos); + const uint8_t epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); +@@ -238,7 +249,18 @@ + depctl.bm.set_data0_iso_even = 1; + } if (dir == TUSB_DIR_IN) { -- epctl |= (epnum << DIEPCTL_TXFNUM_Pos); -+ //epctl |= (epnum << DIEPCTL_TXFNUM_Pos); +- depctl.bm.tx_fifo_num = epnum; ++ //depctl.bm.tx_fifo_num = epnum; + uint8_t fifo_num = epnum; +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + // Special Case for EP5, which is used by CDC but not actually called by the driver @@ -33,13 +33,12 @@ + } else { + fifo_num = get_free_fifo(); + } -+ //TU_ASSERT(fifo_num != 0); +#endif -+ epctl |= (fifo_num << DIEPCTL_TXFNUM_Pos); ++ depctl.bm.tx_fifo_num = fifo_num; } - dwc2_dep_t* dep = &dwc2->ep[1 - dir][epnum]; -@@ -304,6 +327,10 @@ + dwc2_dep_t* dep = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][epnum]; +@@ -523,6 +545,10 @@ } } @@ -50,35 +49,35 @@ dfifo_flush_tx(dwc2, 0x10); // all tx fifo dfifo_flush_rx(dwc2); -@@ -908,6 +935,9 @@ - if (int_status & GINTSTS_USBRST) { +@@ -959,6 +985,9 @@ + if (gintsts & GINTSTS_USBRST) { // USBRST is start of reset. dwc2->gintsts = GINTSTS_USBRST; +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) -+ _allocated_fifos = 1; ++ allocated_fifos = 1; +#endif - bus_reset(rhport); + handle_bus_reset(rhport); } -@@ -939,7 +969,11 @@ +@@ -970,7 +999,11 @@ - if (int_status & GINTSTS_USBSUSP) { + if (gintsts & GINTSTS_USBSUSP) { dwc2->gintsts = GINTSTS_USBSUSP; - dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); + //dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); + dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) -+ _allocated_fifos = 1; ++ allocated_fifos = 1; +#endif } - if (int_status & GINTSTS_WKUINT) { -@@ -956,6 +990,9 @@ + if (gintsts & GINTSTS_WKUINT) { +@@ -987,6 +1020,9 @@ if (otg_int & GOTGINT_SEDET) { dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) -+ _allocated_fifos = 1; ++ allocated_fifos = 1; +#endif } diff --git a/components/arduino_tinyusb/src/dcd_dwc2.c b/components/arduino_tinyusb/src/dcd_dwc2.c index 035e335cd..da4709a72 100644 --- a/components/arduino_tinyusb/src/dcd_dwc2.c +++ b/components/arduino_tinyusb/src/dcd_dwc2.c @@ -37,6 +37,12 @@ #include "device/dcd.h" #include "dwc2_common.h" +#if TU_CHECK_MCU(OPT_MCU_GD32VF103) + #define DWC2_EP_COUNT(_dwc2) DWC2_EP_MAX +#else + #define DWC2_EP_COUNT(_dwc2) ((_dwc2)->ghwcfg2_bm.num_dev_ep) +#endif + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ @@ -71,7 +77,7 @@ static bool _sof_en; TU_ATTR_ALWAYS_INLINE static inline bool dma_device_enabled(const dwc2_regs_t* dwc2) { (void) dwc2; // Internal DMA only - return CFG_TUD_DWC2_DMA && dwc2->ghwcfg2_bm.arch == GHWCFG2_ARCH_INTERNAL_DMA; + return CFG_TUD_DWC2_DMA_ENABLE && dwc2->ghwcfg2_bm.arch == GHWCFG2_ARCH_INTERNAL_DMA; } static void dma_setup_prepare(uint8_t rhport) { @@ -222,20 +228,28 @@ static uint8_t get_free_fifo(void) { static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); - uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); - uint8_t const dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); + const uint8_t epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); + const uint8_t dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); xfer->max_size = tu_edpt_packet_size(p_endpoint_desc); xfer->interval = p_endpoint_desc->bInterval; - // USBAEP, EPTYP, SD0PID_SEVNFRM, MPSIZ are the same for IN and OUT endpoints. - uint32_t epctl = (1 << DOEPCTL_USBAEP_Pos) | - (p_endpoint_desc->bmAttributes.xfer << DOEPCTL_EPTYP_Pos) | - (p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS ? DOEPCTL_SD0PID_SEVNFRM : 0) | - (xfer->max_size << DOEPCTL_MPSIZ_Pos); + // Endpoint control + union { + uint32_t value; + dwc2_depctl_t bm; + } depctl; + depctl.value = 0; + + depctl.bm.mps = xfer->max_size; + depctl.bm.active = 1; + depctl.bm.type = p_endpoint_desc->bmAttributes.xfer; + if (p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS) { + depctl.bm.set_data0_iso_even = 1; + } if (dir == TUSB_DIR_IN) { - //epctl |= (epnum << DIEPCTL_TXFNUM_Pos); + //depctl.bm.tx_fifo_num = epnum; uint8_t fifo_num = epnum; #if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) // Special Case for EP5, which is used by CDC but not actually called by the driver @@ -245,13 +259,12 @@ static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoin } else { fifo_num = get_free_fifo(); } - //TU_ASSERT(fifo_num != 0); #endif - epctl |= (fifo_num << DIEPCTL_TXFNUM_Pos); + depctl.bm.tx_fifo_num = fifo_num; } - dwc2_dep_t* dep = &dwc2->ep[1 - dir][epnum]; - dep->ctl = epctl; + dwc2_dep_t* dep = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][epnum]; + dep->ctl = depctl.value; dwc2->daintmsk |= TU_BIT(epnum + DAINT_SHIFT(dir)); } @@ -261,7 +274,7 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); const uint8_t epnum = tu_edpt_number(ep_addr); const uint8_t dir = tu_edpt_dir(ep_addr); - dwc2_dep_t* dep = &dwc2->ep[1 - dir][epnum]; + dwc2_dep_t* dep = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][epnum]; if (dir == TUSB_DIR_IN) { // Only disable currently enabled non-control endpoint @@ -305,128 +318,66 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { } } -// Start of Bus Reset -static void bus_reset(uint8_t rhport) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - uint8_t const ep_count = _dwc2_controller[rhport].ep_count; - - tu_memclr(xfer_status, sizeof(xfer_status)); - - _sof_en = false; - _allocated_ep_in_count = 1; - - // 1. NAK for all OUT endpoints - for (uint8_t n = 0; n < ep_count; n++) { - dwc2->epout[n].doepctl |= DOEPCTL_SNAK; - } - - // 2. Disable all IN endpoints - for (uint8_t n = 0; n < ep_count; n++) { - if (dwc2->epin[n].diepctl & DIEPCTL_EPENA) { - dwc2->epin[n].diepctl |= DIEPCTL_SNAK | DIEPCTL_EPDIS; - } - } - -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) - _allocated_fifos = 1; -#endif - - dfifo_flush_tx(dwc2, 0x10); // all tx fifo - dfifo_flush_rx(dwc2); - - // 3. Set up interrupt mask for EP0 - dwc2->daintmsk = TU_BIT(DAINTMSK_OEPM_Pos) | TU_BIT(DAINTMSK_IEPM_Pos); - dwc2->doepmsk = DOEPMSK_STUPM | DOEPMSK_XFRCM; - dwc2->diepmsk = DIEPMSK_TOM | DIEPMSK_XFRCM; - - // 4. Set up DFIFO - dfifo_device_init(rhport); - - // 5. Reset device address - dwc2->dcfg &= ~DCFG_DAD_Msk; - - // Fixed both control EP0 size to 64 bytes - dwc2->epin[0].diepctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos); - dwc2->epout[0].doepctl &= ~(0x03 << DOEPCTL_MPSIZ_Pos); - - xfer_status[0][TUSB_DIR_OUT].max_size = 64; - xfer_status[0][TUSB_DIR_IN].max_size = 64; - - if(dma_device_enabled(dwc2)) { - dma_setup_prepare(rhport); - } else { - dwc2->epout[0].doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); - } - - dwc2->gintmsk |= GINTMSK_OEPINT | GINTMSK_IEPINT; -} - -static void edpt_schedule_packets(uint8_t rhport, uint8_t const epnum, uint8_t const dir, uint16_t const num_packets, - uint16_t total_bytes) { - (void) rhport; - +static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uint8_t dir) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); xfer_ctl_t* const xfer = XFER_CTL_BASE(epnum, dir); + dwc2_dep_t* dep = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][epnum]; - // EP0 is limited to one packet each xfer - // We use multiple transaction of xfer->max_size length to get a whole transfer done + uint16_t num_packets; + uint16_t total_bytes; + + // EP0 is limited to one packet per xfer if (epnum == 0) { total_bytes = tu_min16(ep0_pending[dir], xfer->max_size); ep0_pending[dir] -= total_bytes; + num_packets = 1; + } else { + total_bytes = xfer->total_len; + num_packets = tu_div_ceil(total_bytes, xfer->max_size); + if (num_packets == 0) { + num_packets = 1; // zero length packet still count as 1 + } } - // IN and OUT endpoint xfers are interrupt-driven, we just schedule them here. - const uint8_t is_epout = 1 - dir; - dwc2_dep_t* dep = &dwc2->ep[is_epout][epnum]; - - if (dir == TUSB_DIR_IN) { - // A full IN transfer (multiple packets, possibly) triggers XFRC. - dep->dieptsiz = (num_packets << DIEPTSIZ_PKTCNT_Pos) | - ((total_bytes << DIEPTSIZ_XFRSIZ_Pos) & DIEPTSIZ_XFRSIZ_Msk); - - if(dma_device_enabled(dwc2)) { - dep->diepdma = (uintptr_t)xfer->buffer; - - // For ISO endpoint set correct odd/even bit for next frame. - if ((dep->diepctl & DIEPCTL_EPTYP) == DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1) { - // Take odd/even bit from frame counter. - uint32_t const odd_frame_now = (dwc2->dsts & (1u << DSTS_FNSOF_Pos)); - dep->diepctl |= (odd_frame_now ? DIEPCTL_SD0PID_SEVNFRM_Msk : DIEPCTL_SODDFRM_Msk); - } - - dep->diepctl |= DIEPCTL_EPENA | DIEPCTL_CNAK; + // transfer size: A full OUT transfer (multiple packets, possibly) triggers XFRC. + union { + uint32_t value; + dwc2_ep_tsize_t bm; + } deptsiz; + deptsiz.value = 0; + deptsiz.bm.xfer_size = total_bytes; + deptsiz.bm.packet_count = num_packets; + + dep->tsiz = deptsiz.value; + + // control + union { + dwc2_depctl_t bm; + uint32_t value; + } depctl; + depctl.value = dep->ctl; + + depctl.bm.clear_nak = 1; + depctl.bm.enable = 1; + if (depctl.bm.type == DEPCTL_EPTYPE_ISOCHRONOUS && xfer->interval == 1) { + const uint32_t odd_now = (dwc2->dsts_bm.frame_number & 1u); + if (odd_now) { + depctl.bm.set_data0_iso_even = 1; } else { - dep->diepctl |= DIEPCTL_EPENA | DIEPCTL_CNAK; - - // For ISO endpoint set correct odd/even bit for next frame. - if ((dep->diepctl & DIEPCTL_EPTYP) == DIEPCTL_EPTYP_0 && (XFER_CTL_BASE(epnum, dir))->interval == 1) { - // Take odd/even bit from frame counter. - uint32_t const odd_frame_now = (dwc2->dsts & (1u << DSTS_FNSOF_Pos)); - dep->diepctl |= (odd_frame_now ? DIEPCTL_SD0PID_SEVNFRM_Msk : DIEPCTL_SODDFRM_Msk); - } - // Enable fifo empty interrupt only if there are something to put in the fifo. - if (total_bytes != 0) { - dwc2->diepempmsk |= (1 << epnum); - } - } - } else { - // A full OUT transfer (multiple packets, possibly) triggers XFRC. - dep->doeptsiz &= ~(DOEPTSIZ_PKTCNT_Msk | DOEPTSIZ_XFRSIZ); - dep->doeptsiz |= (num_packets << DOEPTSIZ_PKTCNT_Pos) | - ((total_bytes << DOEPTSIZ_XFRSIZ_Pos) & DOEPTSIZ_XFRSIZ_Msk); - - if ((dep->doepctl & DOEPCTL_EPTYP) == DOEPCTL_EPTYP_0 && - XFER_CTL_BASE(epnum, dir)->interval == 1) { - // Take odd/even bit from frame counter. - uint32_t const odd_frame_now = (dwc2->dsts & (1u << DSTS_FNSOF_Pos)); - dep->doepctl |= (odd_frame_now ? DOEPCTL_SD0PID_SEVNFRM_Msk : DOEPCTL_SODDFRM_Msk); + depctl.bm.set_data1_iso_odd = 1; } + } - if(dma_device_enabled(dwc2)) { - dep->doepdma = (uintptr_t)xfer->buffer; - } + const bool is_dma = dma_device_enabled(dwc2); + if(is_dma) { + dep->diepdma = (uintptr_t) xfer->buffer; + } + + dep->diepctl = depctl.value; // enable endpoint - dep->doepctl |= DOEPCTL_EPENA | DOEPCTL_CNAK; + // Slave: enable tx fifo empty interrupt only if there is data. Note must after depctl enable + if (!is_dma && dir == TUSB_DIR_IN && total_bytes != 0) { + dwc2->diepempmsk |= (1 << epnum); } } @@ -439,18 +390,10 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Core Initialization const bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_DEVICE); - TU_ASSERT(dwc2_core_init(rhport, is_highspeed)); - - if (dma_device_enabled(dwc2)) { - // DMA seems to be only settable after a core reset, and not possible to switch on-the-fly - dwc2->gahbcfg |= GAHBCFG_DMAEN | GAHBCFG_HBSTLEN_2; - } else { - dwc2->gintmsk |= GINTSTS_RXFLVL; - } - - // Device Initialization - dcd_disconnect(rhport); + const bool is_dma = dma_device_enabled(dwc2); + TU_ASSERT(dwc2_core_init(rhport, is_highspeed, is_dma)); + //------------- 7.1 Device Initialization -------------// // Set device max speed uint32_t dcfg = dwc2->dcfg & ~DCFG_DSPD_Msk; if (is_highspeed) { @@ -461,20 +404,21 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { if (dwc2->ghwcfg2_bm.hs_phy_type == GHWCFG2_HSPHY_ULPI) { dcfg |= DCFG_XCVRDLY; } - }else { + } else { dcfg |= DCFG_DSPD_FS << DCFG_DSPD_Pos; } + + dcfg |= DCFG_NZLSOHSK; // send STALL back and discard if host send non-zlp during control status dwc2->dcfg = dcfg; + dcd_disconnect(rhport); + // Force device mode dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_FHMOD) | GUSBCFG_FDMOD; // Clear A override, force B Valid dwc2->gotgctl = (dwc2->gotgctl & ~GOTGCTL_AVALOEN) | GOTGCTL_BVALOEN | GOTGCTL_BVALOVAL; - // If USB host misbehaves during status portion of control xfer (non zero-length packet), send STALL back and discard - dwc2->dcfg |= DCFG_NZLSOHSK; - // Enable required interrupts dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM; @@ -601,6 +545,10 @@ void dcd_edpt_close_all(uint8_t rhport) { } } +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) + _allocated_fifos = 1; +#endif + dfifo_flush_tx(dwc2, 0x10); // all tx fifo dfifo_flush_rx(dwc2); @@ -631,19 +579,11 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to // EP0 can only handle one packet if (epnum == 0) { ep0_pending[dir] = total_bytes; - - // Schedule the first transaction for EP0 transfer - edpt_schedule_packets(rhport, epnum, dir, 1, ep0_pending[dir]); - } else { - uint16_t num_packets = tu_div_ceil(total_bytes, xfer->max_size); - if (num_packets == 0) { - num_packets = 1; // zero length packet still count as 1 - } - - // Schedule packets to be sent within interrupt - edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); } + // Schedule packets to be sent within interrupt + edpt_schedule_packets(rhport, epnum, dir); + return true; } @@ -663,16 +603,9 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t xfer->ff = ff; xfer->total_len = total_bytes; - uint16_t num_packets = (total_bytes / xfer->max_size); - uint16_t const short_packet_size = total_bytes % xfer->max_size; - - // Zero-size packet is special case. - if (short_packet_size > 0 || (total_bytes == 0)) { - num_packets++; - } - // Schedule packets to be sent within interrupt - edpt_schedule_packets(rhport, epnum, dir, num_packets, total_bytes); + // TODO xfer fifo may only available for slave mode + edpt_schedule_packets(rhport, epnum, dir); return true; } @@ -693,7 +626,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - dwc2_dep_t* dep = &dwc2->ep[1 - dir][epnum]; + dwc2_dep_t* dep = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][epnum]; // Clear stall and reset data toggle dep->ctl &= ~EPCTL_STALL;; @@ -704,6 +637,99 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { // Interrupt Handler //-------------------------------------------------------------------- +// 7.4.1 Initialization on USB Reset +static void handle_bus_reset(uint8_t rhport) { + dwc2_regs_t *dwc2 = DWC2_REG(rhport); + const uint8_t ep_count = DWC2_EP_COUNT(dwc2); + + tu_memclr(xfer_status, sizeof(xfer_status)); + + _sof_en = false; + _allocated_ep_in_count = 1; + + // 1. NAK for all OUT endpoints + for (uint8_t n = 0; n < ep_count; n++) { + dwc2->epout[n].doepctl |= DOEPCTL_SNAK; + } + + // Disable all IN endpoints + for (uint8_t n = 0; n < ep_count; n++) { + if (dwc2->epin[n].diepctl & DIEPCTL_EPENA) { + dwc2->epin[n].diepctl |= DIEPCTL_SNAK | DIEPCTL_EPDIS; + } + } + + // 2. Set up interrupt mask for EP0 + dwc2->daintmsk = TU_BIT(DAINTMSK_OEPM_Pos) | TU_BIT(DAINTMSK_IEPM_Pos); + dwc2->doepmsk = DOEPMSK_STUPM | DOEPMSK_XFRCM; + dwc2->diepmsk = DIEPMSK_TOM | DIEPMSK_XFRCM; + + // 4. Set up DFIFO + dfifo_flush_tx(dwc2, 0x10); // all tx fifo + dfifo_flush_rx(dwc2); + dfifo_device_init(rhport); + + // 5. Reset device address + dwc2->dcfg_bm.address = 0; + + // Fixed both control EP0 size to 64 bytes + dwc2->epin[0].ctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos); + dwc2->epout[0].ctl &= ~(0x03 << DOEPCTL_MPSIZ_Pos); + + xfer_status[0][TUSB_DIR_OUT].max_size = 64; + xfer_status[0][TUSB_DIR_IN].max_size = 64; + + if(dma_device_enabled(dwc2)) { + dma_setup_prepare(rhport); + } else { + dwc2->epout[0].doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); + } + + dwc2->gintmsk |= GINTMSK_OEPINT | GINTMSK_IEPINT; +} + +static void handle_enum_done(uint8_t rhport) { + dwc2_regs_t *dwc2 = DWC2_REG(rhport); + tusb_speed_t speed; + switch (dwc2->dsts_bm.enum_speed) { + case DCFG_SPEED_HIGH: + speed = TUSB_SPEED_HIGH; + break; + + case DCFG_SPEED_LOW: + speed = TUSB_SPEED_LOW; + break; + + case DCFG_SPEED_FULL_30_60MHZ: + case DCFG_SPEED_FULL_48MHZ: + default: + speed = TUSB_SPEED_FULL; + break; + } + + // TODO must update GUSBCFG_TRDT according to link speed + dcd_event_bus_reset(rhport, speed, true); +} + +#if 0 +TU_ATTR_ALWAYS_INLINE static inline void print_doepint(uint32_t doepint) { + const char* str[] = { + "XFRC", "DIS", "AHBERR", "SETUP_DONE", + "ORXED", "STATUS_RX", "SETUP_B2B", "RSV7", + "OPERR", "BNA", "RSV10", "ISODROP", + "BBLERR", "NAK", "NYET", "SETUP_RX" + }; + + for(uint32_t i=0; igrxstsp_bm; const uint8_t epnum = grxstsp_bm.ep_ch_num; - const uint16_t byte_count = grxstsp_bm.byte_count; - dwc2_epout_t* epout = &dwc2->epout[epnum]; + + dwc2_dep_t* epout = &dwc2->epout[epnum]; switch (grxstsp_bm.packet_status) { - // Global OUT NAK: do nothing - case GRXSTS_PKTSTS_GLOBALOUTNAK: + case GRXSTS_PKTSTS_GLOBAL_OUT_NAK: + // Global OUT NAK: do nothing break; - case GRXSTS_PKTSTS_SETUPRX: + case GRXSTS_PKTSTS_SETUP_RX: // Setup packet received - // We can receive up to three setup packets in succession, but only the last one is valid. + // We can receive up to three setup packets in succession, but only the last one is valid. _setup_packet[0] = (*rx_fifo); _setup_packet[1] = (*rx_fifo); break; - case GRXSTS_PKTSTS_SETUPDONE: + case GRXSTS_PKTSTS_SETUP_DONE: // Setup packet done: // After popping this out, dwc2 asserts a DOEPINT_SETUP interrupt which is handled by handle_epout_irq() epout->doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); break; - case GRXSTS_PKTSTS_OUTRX: { + case GRXSTS_PKTSTS_RX_DATA: { // Out packet received + const uint16_t byte_count = grxstsp_bm.byte_count; xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - // Read packet off RxFIFO - if (xfer->ff) { - // Ring buffer - tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void*) (uintptr_t) rx_fifo, byte_count); - } else { - // Linear buffer - dfifo_read_packet(dwc2, xfer->buffer, byte_count); - - // Increment pointer to xfer data - xfer->buffer += byte_count; - } + if (byte_count) { + // Read packet off RxFIFO + if (xfer->ff) { + tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void*) (uintptr_t) rx_fifo, byte_count); + } else { + dfifo_read_packet(dwc2, xfer->buffer, byte_count); + xfer->buffer += byte_count; + } - // short packet, minus remaining bytes (xfer_size) - if (byte_count < xfer->max_size) { - xfer->total_len -= epout->doeptsiz_bm.xfer_size; - if (epnum == 0) { - xfer->total_len -= ep0_pending[TUSB_DIR_OUT]; - ep0_pending[TUSB_DIR_OUT] = 0; + // short packet, minus remaining bytes (xfer_size) + if (byte_count < xfer->max_size) { + xfer->total_len -= epout->tsiz_bm.xfer_size; + if (epnum == 0) { + xfer->total_len -= ep0_pending[TUSB_DIR_OUT]; + ep0_pending[TUSB_DIR_OUT] = 0; + } } } break; } - case GRXSTS_PKTSTS_OUTDONE: - /* Out packet done - After this entry is popped from the receive FIFO, dwc2 asserts a Transfer Completed interrupt on - the specified OUT endpoint which will be handled by handle_epout_irq() */ + case GRXSTS_PKTSTS_RX_COMPLETE: + // Out packet done + // After this entry is popped from the receive FIFO, dwc2 asserts a Transfer Completed interrupt on + // the specified OUT endpoint which will be handled by handle_epout_irq() break; - default: - TU_BREAKPOINT(); - break; + default: break; } } -static void handle_epout_irq(uint8_t rhport) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - uint8_t const ep_count = _dwc2_controller[rhport].ep_count; +static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepint_bm) { + if (doepint_bm.setup_phase_done) { + dcd_event_setup_received(rhport, (uint8_t*) _setup_packet, true); + return; + } - // DAINT for a given EP clears when DOEPINTx is cleared. - // OEPINT will be cleared when DAINT's out bits are cleared. - for (uint8_t epnum = 0; epnum < ep_count; epnum++) { - if (dwc2->daint & TU_BIT(DAINT_OEPINT_Pos + epnum)) { - dwc2_epout_t* epout = &dwc2->epout[epnum]; - const uint32_t doepint = epout->doepint; - TU_ASSERT((epout->doepint & DOEPINT_AHBERR) == 0, ); - - // Setup and/or STPKTRX/STSPHSRX (from 3.00a) can be set along with XFRC, and also set independently. - if (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a) { - if (doepint & DOEPINT_STSPHSRX) { - // Status phase received for control write: In token received from Host - epout->doepint = DOEPINT_STSPHSRX; - } + // Normal OUT transfer complete + if (doepint_bm.xfer_complete) { + // only handle data skip if it is setup or status related + // Note: even though (xfer_complete + status_phase_rx) is for buffered DMA only, for STM32L47x (dwc2 v3.00a) they + // can is set when GRXSTS_PKTSTS_SETUP_RX is popped therefore they can bet set before/together with setup_phase_done + if (!doepint_bm.status_phase_rx && !doepint_bm.setup_packet_rx) { + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - if (doepint & DOEPINT_STPKTRX) { - // New setup packet received, but wait for Setup done, since we can receive up to 3 setup consecutively - epout->doepint = DOEPINT_STPKTRX; - } + if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) { + // EP0 can only handle one packet, Schedule another packet to be received. + edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT); + } else { + dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); } + } + } +} - if (doepint & DOEPINT_SETUP) { - epout->doepint = DOEPINT_SETUP; +static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diepint_bm) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + dwc2_dep_t* epin = &dwc2->epin[epnum]; + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); - if(dma_device_enabled(dwc2)) { - dma_setup_prepare(rhport); - } + if (diepint_bm.xfer_complete) { + if ((epnum == 0) && ep0_pending[TUSB_DIR_IN]) { + // EP0 can only handle one packet. Schedule another packet to be transmitted. + edpt_schedule_packets(rhport, epnum, TUSB_DIR_IN); + } else { + dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); + } + } + + // TX FIFO empty bit is read-only. It will only be cleared by hardware when written bytes is more than + // - 64 bytes or + // - Half/Empty of TX FIFO size (configured by GAHBCFG.TXFELVL) + if (diepint_bm.txfifo_empty && (dwc2->diepempmsk & (1 << epnum))) { + const uint16_t remain_packets = epin->tsiz_bm.packet_count; - dcd_event_setup_received(rhport, (uint8_t*) _setup_packet, true); + // Process every single packet (only whole packets can be written to fifo) + for (uint16_t i = 0; i < remain_packets; i++) { + const uint16_t remain_bytes = (uint16_t) epin->tsiz_bm.xfer_size; + const uint16_t xact_bytes = tu_min16(remain_bytes, xfer->max_size); + + // Check if dtxfsts has enough space available + if (xact_bytes > ((epin->dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) { + break; } - // OUT XFER complete - if (doepint & DOEPINT_XFRC) { - epout->doepint = DOEPINT_XFRC; - - // only handle data skip if it is setup or status related - // Normal OUT transfer complete - if (!(doepint & (DOEPINT_SETUP | DOEPINT_STPKTRX | DOEPINT_STSPHSRX))) { - xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - - if(dma_device_enabled(dwc2)) { - if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) { - // EP0 can only handle one packet Schedule another packet to be received. - edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); - } else { - // Fix packet length - uint16_t remain = (epout->doeptsiz & DOEPTSIZ_XFRSIZ_Msk) >> DOEPTSIZ_XFRSIZ_Pos; - xfer->total_len -= remain; - // this is ZLP, so prepare EP0 for next setup - if(epnum == 0 && xfer->total_len == 0) { - dma_setup_prepare(rhport); - } - - dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); - } - } else { - // EP0 can only handle one packet - if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) { - // Schedule another packet to be received. - edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT, 1, ep0_pending[TUSB_DIR_OUT]); - } else { - dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); - } - } - } + // Push packet to Tx-FIFO + if (xfer->ff) { + volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; + tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*)(uintptr_t)tx_fifo, xact_bytes); + } else { + dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); + xfer->buffer += xact_bytes; } } + + // Turn off TXFE if all bytes are written. + if (epin->tsiz_bm.xfer_size == 0) { + dwc2->diepempmsk &= ~(1 << epnum); + } } } +#endif -static void handle_epin_irq(uint8_t rhport) { +#if CFG_TUD_DWC2_DMA_ENABLE +static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepint_bm) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); - const uint8_t ep_count = _dwc2_controller[rhport].ep_count; - // DAINT for a given EP clears when DIEPINTx is cleared. - // IEPINT will be cleared when DAINT's out bits are cleared. - for (uint8_t n = 0; n < ep_count; n++) { - if (dwc2->daint & TU_BIT(DAINT_IEPINT_Pos + n)) { - // IN XFER complete (entire xfer). - xfer_ctl_t* xfer = XFER_CTL_BASE(n, TUSB_DIR_IN); - dwc2_epin_t* epin = &dwc2->epin[n]; - - if (epin->diepint & DIEPINT_XFRC) { - epin->diepint = DIEPINT_XFRC; - - // EP0 can only handle one packet - if ((n == 0) && ep0_pending[TUSB_DIR_IN]) { - // Schedule another packet to be transmitted. - edpt_schedule_packets(rhport, n, TUSB_DIR_IN, 1, ep0_pending[TUSB_DIR_IN]); - } else { - if((n == 0) && dma_device_enabled(dwc2)) { - dma_setup_prepare(rhport); - } - dcd_event_xfer_complete(rhport, n | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); + if (doepint_bm.setup_phase_done) { + dma_setup_prepare(rhport); + dcd_event_setup_received(rhport, (uint8_t*) _setup_packet, true); + return; + } + + // OUT XFER complete + if (doepint_bm.xfer_complete) { + // only handle data skip if it is setup or status related + // Normal OUT transfer complete + if (!doepint_bm.status_phase_rx && !doepint_bm.setup_packet_rx) { + if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) { + // EP0 can only handle one packet Schedule another packet to be received. + edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT); + } else { + dwc2_dep_t* epout = &dwc2->epout[epnum]; + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); + + // determine actual received bytes + const uint16_t remain = epout->tsiz_bm.xfer_size; + xfer->total_len -= remain; + + // this is ZLP, so prepare EP0 for next setup + // TODO use status phase rx + if(epnum == 0 && xfer->total_len == 0) { + dma_setup_prepare(rhport); } + + dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); } + } + } +} - // XFER FIFO empty - if ((epin->diepint & DIEPINT_TXFE) && (dwc2->diepempmsk & (1 << n))) { - // diepint's TXFE bit is read-only, software cannot clear it. - // It will only be cleared by hardware when written bytes is more than - // - 64 bytes or - // - Half/Empty of TX FIFO size (configured by GAHBCFG.TXFELVL) - const uint16_t remain_packets = epin->dieptsiz_bm.packet_count; - - // Process every single packet (only whole packets can be written to fifo) - for (uint16_t i = 0; i < remain_packets; i++) { - const uint16_t remain_bytes = (uint16_t) epin->dieptsiz_bm.xfer_size; - - // Packet can not be larger than ep max size - const uint16_t xact_bytes = tu_min16(remain_bytes, xfer->max_size); - - // It's only possible to write full packets into FIFO. Therefore DTXFSTS register of current - // EP has to be checked if the buffer can take another WHOLE packet - if (xact_bytes > ((epin->dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) { - break; - } +static void handle_epin_dma(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diepint_bm) { + xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); - // Push packet to Tx-FIFO - if (xfer->ff) { - volatile uint32_t* tx_fifo = dwc2->fifo[n]; - tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*) (uintptr_t) tx_fifo, xact_bytes); - } else { - dfifo_write_packet(dwc2, n, xfer->buffer, xact_bytes); - xfer->buffer += xact_bytes; - } - } + if (diepint_bm.xfer_complete) { + if ((epnum == 0) && ep0_pending[TUSB_DIR_IN]) { + // EP0 can only handle one packet. Schedule another packet to be transmitted. + edpt_schedule_packets(rhport, epnum, TUSB_DIR_IN); + } else { + if(epnum == 0) { + dma_setup_prepare(rhport); + } + dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); + } + } +} +#endif - // Turn off TXFE if all bytes are written. - if (epin->dieptsiz_bm.xfer_size == 0) { - dwc2->diepempmsk &= ~(1 << n); +static void handle_ep_irq(uint8_t rhport, uint8_t dir) { + dwc2_regs_t* dwc2 = DWC2_REG(rhport); + const bool is_dma = dma_device_enabled(dwc2); + const uint8_t ep_count = DWC2_EP_COUNT(dwc2); + const uint8_t daint_offset = (dir == TUSB_DIR_IN) ? DAINT_IEPINT_Pos : DAINT_OEPINT_Pos; + dwc2_dep_t* ep_base = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][0]; + + // DAINT for a given EP clears when DEPINTx is cleared. + // EPINT will be cleared when DAINT bits are cleared. + for (uint8_t epnum = 0; epnum < ep_count; epnum++) { + if (dwc2->daint & TU_BIT(daint_offset + epnum)) { + dwc2_dep_t* epout = &ep_base[epnum]; + union { + uint32_t value; + dwc2_diepint_t diepint_bm; + dwc2_doepint_t doepint_bm; + } intr; + intr.value = epout->intr; + + epout->intr = intr.value; // Clear interrupt + + if (is_dma) { + #if CFG_TUD_DWC2_DMA_ENABLE + if (dir == TUSB_DIR_IN) { + handle_epin_dma(rhport, epnum, intr.diepint_bm); + } else { + handle_epout_dma(rhport, epnum, intr.doepint_bm); + } + #endif + } else { + #if CFG_TUD_DWC2_SLAVE_ENABLE + if (dir == TUSB_DIR_IN) { + handle_epin_slave(rhport, epnum, intr.diepint_bm); + } else { + handle_epout_slave(rhport, epnum, intr.doepint_bm); } + #endif } } } } /* Interrupt Hierarchy - - DxEPINTn - | - DAINT.xEPn - | - GINTSTS: xEPInt + DIEPINT DIEPINT + \ / + \ / + DAINT + / \ + / \ + GINTSTS: OEPInt IEPInt | USBReset | EnumDone | USBSusp | WkUpInt | OTGInt | SOF | RXFLVL Note: when OTG_MULTI_PROC_INTRPT = 1, Device Each endpoint interrupt deachint/deachmsk/diepeachmsk/doepeachmsk are combined to generate dedicated interrupt line for each endpoint. */ - - void dcd_int_handler(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); - uint32_t const int_mask = dwc2->gintmsk; - uint32_t const int_status = dwc2->gintsts & int_mask; + const uint32_t gintmask = dwc2->gintmsk; + const uint32_t gintsts = dwc2->gintsts & gintmask; - if (int_status & GINTSTS_USBRST) { + if (gintsts & GINTSTS_USBRST) { // USBRST is start of reset. dwc2->gintsts = GINTSTS_USBRST; #if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) _allocated_fifos = 1; #endif - bus_reset(rhport); + handle_bus_reset(rhport); } - if (int_status & GINTSTS_ENUMDNE) { + if (gintsts & GINTSTS_ENUMDNE) { // ENUMDNE is the end of reset where speed of the link is detected dwc2->gintsts = GINTSTS_ENUMDNE; - - tusb_speed_t speed; - switch ((dwc2->dsts & DSTS_ENUMSPD_Msk) >> DSTS_ENUMSPD_Pos) { - case DSTS_ENUMSPD_HS: - speed = TUSB_SPEED_HIGH; - break; - - case DSTS_ENUMSPD_LS: - speed = TUSB_SPEED_LOW; - break; - - case DSTS_ENUMSPD_FS_HSPHY: - case DSTS_ENUMSPD_FS: - default: - speed = TUSB_SPEED_FULL; - break; - } - - // TODO must update GUSBCFG_TRDT according to link speed - - dcd_event_bus_reset(rhport, speed, true); + handle_enum_done(rhport); } - if (int_status & GINTSTS_USBSUSP) { + if (gintsts & GINTSTS_USBSUSP) { dwc2->gintsts = GINTSTS_USBSUSP; //dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); @@ -976,7 +1006,7 @@ void dcd_int_handler(uint8_t rhport) { #endif } - if (int_status & GINTSTS_WKUINT) { + if (gintsts & GINTSTS_WKUINT) { dwc2->gintsts = GINTSTS_WKUINT; dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); } @@ -984,7 +1014,7 @@ void dcd_int_handler(uint8_t rhport) { // TODO check GINTSTS_DISCINT for disconnect detection // if(int_status & GINTSTS_DISCINT) - if (int_status & GINTSTS_OTGINT) { + if (gintsts & GINTSTS_OTGINT) { // OTG INT bit is read-only uint32_t const otg_int = dwc2->gotgint; @@ -998,7 +1028,7 @@ void dcd_int_handler(uint8_t rhport) { dwc2->gotgint = otg_int; } - if(int_status & GINTSTS_SOF) { + if(gintsts & GINTSTS_SOF) { dwc2->gintsts = GINTSTS_SOF; const uint32_t frame = (dwc2->dsts & DSTS_FNSOF) >> DSTS_FNSOF_Pos; @@ -1010,8 +1040,9 @@ void dcd_int_handler(uint8_t rhport) { dcd_event_sof(rhport, frame, true); } +#if CFG_TUD_DWC2_SLAVE_ENABLE // RxFIFO non-empty interrupt handling. - if (int_status & GINTSTS_RXFLVL) { + if (gintsts & GINTSTS_RXFLVL) { // RXFLVL bit is read-only dwc2->gintmsk &= ~GINTMSK_RXFLVLM; // disable RXFLVL interrupt while reading @@ -1021,24 +1052,19 @@ void dcd_int_handler(uint8_t rhport) { dwc2->gintmsk |= GINTMSK_RXFLVLM; } +#endif // OUT endpoint interrupt handling. - if (int_status & GINTSTS_OEPINT) { + if (gintsts & GINTSTS_OEPINT) { // OEPINT is read-only, clear using DOEPINTn - handle_epout_irq(rhport); + handle_ep_irq(rhport, TUSB_DIR_OUT); } // IN endpoint interrupt handling. - if (int_status & GINTSTS_IEPINT) { + if (gintsts & GINTSTS_IEPINT) { // IEPINT bit read-only, clear using DIEPINTn - handle_epin_irq(rhport); + handle_ep_irq(rhport, TUSB_DIR_IN); } - - // // Check for Incomplete isochronous IN transfer - // if(int_status & GINTSTS_IISOIXFR) { - // printf(" IISOIXFR!\r\n"); - //// TU_LOG(DWC2_DEBUG, " IISOIXFR!\r\n"); - // } } #if CFG_TUD_TEST_MODE From d96461fde44398e3c3167c58a93308290b434311 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Mon, 25 Nov 2024 13:37:36 +0200 Subject: [PATCH 30/38] Update TinyUSB DCD --- .../arduino_tinyusb/patches/dcd_dwc2.patch | 22 +-- components/arduino_tinyusb/src/dcd_dwc2.c | 146 +++++++++++------- 2 files changed, 103 insertions(+), 65 deletions(-) diff --git a/components/arduino_tinyusb/patches/dcd_dwc2.patch b/components/arduino_tinyusb/patches/dcd_dwc2.patch index 0c45bb0ae..11c1c05c0 100644 --- a/components/arduino_tinyusb/patches/dcd_dwc2.patch +++ b/components/arduino_tinyusb/patches/dcd_dwc2.patch @@ -1,6 +1,6 @@ --- a/components/arduino_tinyusb/src/dcd_dwc2.c 2024-10-02 12:17:40.000000000 +0300 +++ b/components/arduino_tinyusb/src/dcd_dwc2.c 2024-10-02 12:19:48.000000000 +0300 -@@ -215,6 +215,17 @@ +@@ -243,6 +243,17 @@ //-------------------------------------------------------------------- // Endpoint //-------------------------------------------------------------------- @@ -14,11 +14,11 @@ + return 0; +} +#endif -+ - static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { ++ + static void edpt_activate(uint8_t rhport, const tusb_desc_endpoint_t* p_endpoint_desc) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); const uint8_t epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); -@@ -238,7 +249,18 @@ +@@ -266,7 +277,18 @@ depctl.bm.set_data0_iso_even = 1; } if (dir == TUSB_DIR_IN) { @@ -38,7 +38,7 @@ } dwc2_dep_t* dep = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][epnum]; -@@ -523,6 +545,10 @@ +@@ -557,6 +579,10 @@ } } @@ -49,17 +49,17 @@ dfifo_flush_tx(dwc2, 0x10); // all tx fifo dfifo_flush_rx(dwc2); -@@ -959,6 +985,9 @@ +@@ -997,6 +1023,9 @@ if (gintsts & GINTSTS_USBRST) { // USBRST is start of reset. dwc2->gintsts = GINTSTS_USBRST; +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) -+ allocated_fifos = 1; ++ _allocated_fifos = 1; +#endif handle_bus_reset(rhport); } -@@ -970,7 +999,11 @@ +@@ -1008,7 +1037,11 @@ if (gintsts & GINTSTS_USBSUSP) { dwc2->gintsts = GINTSTS_USBSUSP; @@ -67,17 +67,17 @@ + //dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); + dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) -+ allocated_fifos = 1; ++ _allocated_fifos = 1; +#endif } if (gintsts & GINTSTS_WKUINT) { -@@ -987,6 +1020,9 @@ +@@ -1025,6 +1058,9 @@ if (otg_int & GOTGINT_SEDET) { dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) -+ allocated_fifos = 1; ++ _allocated_fifos = 1; +#endif } diff --git a/components/arduino_tinyusb/src/dcd_dwc2.c b/components/arduino_tinyusb/src/dcd_dwc2.c index da4709a72..da36a144f 100644 --- a/components/arduino_tinyusb/src/dcd_dwc2.c +++ b/components/arduino_tinyusb/src/dcd_dwc2.c @@ -31,6 +31,10 @@ #if CFG_TUD_ENABLED && defined(TUP_USBIP_DWC2) +#if !CFG_TUD_DWC2_SLAVE_ENABLE && !CFG_TUH_DWC2_DMA_ENABLE +#error DWC2 require either CFG_TUD_DWC2_SLAVE_ENABLE or CFG_TUH_DWC2_DMA_ENABLE to be enabled +#endif + // Debug level for DWC2 #define DWC2_DEBUG 2 @@ -46,9 +50,6 @@ //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ - -static CFG_TUD_MEM_SECTION TU_ATTR_ALIGNED(4) uint32_t _setup_packet[2]; - typedef struct { uint8_t* buffer; tu_fifo_t* ff; @@ -60,19 +61,46 @@ typedef struct { static xfer_ctl_t xfer_status[DWC2_EP_MAX][2]; #define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir]) -// EP0 transfers are limited to 1 packet - larger sizes has to be split -static uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type -static uint16_t _dfifo_top; // top free location in DFIFO in words +typedef struct { + // EP0 transfers are limited to 1 packet - larger sizes has to be split + uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type + uint16_t dfifo_top; // top free location in DFIFO in words + + // Number of IN endpoints active + uint8_t allocated_epin_count; + + // SOF enabling flag - required for SOF to not get disabled in ISR when SOF was enabled by + bool sof_en; +} dcd_data_t; -// Number of IN endpoints active -static uint8_t _allocated_ep_in_count; +static dcd_data_t _dcd_data; -// SOF enabling flag - required for SOF to not get disabled in ISR when SOF was enabled by -static bool _sof_en; +CFG_TUD_MEM_SECTION static struct { + TUD_EPBUF_DEF(setup_packet, 8); +} _dcd_usbbuf; //-------------------------------------------------------------------- // DMA //-------------------------------------------------------------------- +#if CFG_TUD_MEM_DCACHE_ENABLE +void dcd_dcache_clean(const void* addr, uint32_t data_size) { + if (addr && data_size) { + dwc2_dcache_clean(addr, data_size); + } +} + +void dcd_dcache_invalidate(const void* addr, uint32_t data_size) { + if (addr && data_size) { + dwc2_dcache_invalidate(addr, data_size); + } +} + +void dcd_dcache_clean_invalidate(const void* addr, uint32_t data_size) { + if (addr && data_size) { + dwc2_dcache_clean_invalidate(addr, data_size); + } +} +#endif TU_ATTR_ALWAYS_INLINE static inline bool dma_device_enabled(const dwc2_regs_t* dwc2) { (void) dwc2; @@ -91,7 +119,7 @@ static void dma_setup_prepare(uint8_t rhport) { // Receive only 1 packet dwc2->epout[0].doeptsiz = (1 << DOEPTSIZ_STUPCNT_Pos) | (1 << DOEPTSIZ_PKTCNT_Pos) | (8 << DOEPTSIZ_XFRSIZ_Pos); - dwc2->epout[0].doepdma = (uintptr_t)_setup_packet; + dwc2->epout[0].doepdma = (uintptr_t) _dcd_usbbuf.setup_packet; dwc2->epout[0].doepctl |= DOEPCTL_EPENA | DOEPCTL_USBAEP; } @@ -149,27 +177,27 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t calc_device_grxfsiz(uint16_t larges static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); const dwc2_controller_t* dwc2_controller = &_dwc2_controller[rhport]; - uint8_t const ep_count = dwc2_controller->ep_count; - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + const uint8_t ep_count = dwc2_controller->ep_count; + const uint8_t epnum = tu_edpt_number(ep_addr); + const uint8_t dir = tu_edpt_dir(ep_addr); TU_ASSERT(epnum < ep_count); uint16_t fifo_size = tu_div_ceil(packet_size, 4); if (dir == TUSB_DIR_OUT) { // Calculate required size of RX FIFO - uint16_t const new_sz = calc_device_grxfsiz(4 * fifo_size, ep_count); + const uint16_t new_sz = calc_device_grxfsiz(4 * fifo_size, ep_count); // If size_rx needs to be extended check if there is enough free space if (dwc2->grxfsiz < new_sz) { - TU_ASSERT(new_sz <= _dfifo_top); + TU_ASSERT(new_sz <= _dcd_data.dfifo_top); dwc2->grxfsiz = new_sz; // Enlarge RX FIFO } } else { // Check IN endpoints concurrently active limit if(_dwc2_controller->ep_in_count) { - TU_ASSERT(_allocated_ep_in_count < _dwc2_controller->ep_in_count); - _allocated_ep_in_count++; + TU_ASSERT(_dcd_data.allocated_epin_count < _dwc2_controller->ep_in_count); + _dcd_data.allocated_epin_count++; } // If The TXFELVL is configured as half empty, the fifo must be twice the max_size. @@ -178,16 +206,16 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { } // Check if free space is available - TU_ASSERT(_dfifo_top >= fifo_size + dwc2->grxfsiz); - _dfifo_top -= fifo_size; - TU_LOG(DWC2_DEBUG, " TX FIFO %u: allocated %u words at offset %u\r\n", epnum, fifo_size, _dfifo_top); + TU_ASSERT(_dcd_data.dfifo_top >= fifo_size + dwc2->grxfsiz); + _dcd_data.dfifo_top -= fifo_size; + // TU_LOG(DWC2_DEBUG, " TX FIFO %u: allocated %u words at offset %u\r\n", epnum, fifo_size, dfifo_top); // Both TXFD and TXSA are in unit of 32-bit words. if (epnum == 0) { - dwc2->dieptxf0 = (fifo_size << DIEPTXF0_TX0FD_Pos) | _dfifo_top; + dwc2->dieptxf0 = (fifo_size << DIEPTXF0_TX0FD_Pos) | _dcd_data.dfifo_top; } else { // DIEPTXF starts at FIFO #1. - dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) | _dfifo_top; + dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) | _dcd_data.dfifo_top; } } @@ -201,11 +229,11 @@ static void dfifo_device_init(uint8_t rhport) { // Scatter/Gather DMA mode is not yet supported. Buffer DMA only need 1 words per endpoint direction const bool is_dma = dma_device_enabled(dwc2); - _dfifo_top = dwc2_controller->ep_fifo_size/4; + _dcd_data.dfifo_top = dwc2_controller->ep_fifo_size/4; if (is_dma) { - _dfifo_top -= 2 * dwc2_controller->ep_count; + _dcd_data.dfifo_top -= 2 * dwc2_controller->ep_count; } - dwc2->gdfifocfg = (_dfifo_top << GDFIFOCFG_EPINFOBASE_SHIFT) | _dfifo_top; + dwc2->gdfifocfg = (_dcd_data.dfifo_top << GDFIFOCFG_EPINFOBASE_SHIFT) | _dcd_data.dfifo_top; // Allocate FIFO for EP0 IN dfifo_alloc(rhport, 0x80, CFG_TUD_ENDPOINT0_SIZE); @@ -225,8 +253,8 @@ static uint8_t get_free_fifo(void) { return 0; } #endif - -static void edpt_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { + +static void edpt_activate(uint8_t rhport, const tusb_desc_endpoint_t* p_endpoint_desc) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); const uint8_t epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); const uint8_t dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); @@ -328,8 +356,8 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin // EP0 is limited to one packet per xfer if (epnum == 0) { - total_bytes = tu_min16(ep0_pending[dir], xfer->max_size); - ep0_pending[dir] -= total_bytes; + total_bytes = tu_min16(_dcd_data.ep0_pending[dir], xfer->max_size); + _dcd_data.ep0_pending[dir] -= total_bytes; num_packets = 1; } else { total_bytes = xfer->total_len; @@ -370,14 +398,18 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin const bool is_dma = dma_device_enabled(dwc2); if(is_dma) { + if (dir == TUSB_DIR_IN && total_bytes != 0) { + dcd_dcache_clean(xfer->buffer, total_bytes); + } dep->diepdma = (uintptr_t) xfer->buffer; - } - - dep->diepctl = depctl.value; // enable endpoint + dep->diepctl = depctl.value; // enable endpoint + } else { + dep->diepctl = depctl.value; // enable endpoint - // Slave: enable tx fifo empty interrupt only if there is data. Note must after depctl enable - if (!is_dma && dir == TUSB_DIR_IN && total_bytes != 0) { - dwc2->diepempmsk |= (1 << epnum); + // Enable tx fifo empty interrupt only if there is data. Note must after depctl enable + if (dir == TUSB_DIR_IN && total_bytes != 0) { + dwc2->diepempmsk |= (1 << epnum); + } } } @@ -388,6 +420,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { (void) rh_init; dwc2_regs_t* dwc2 = DWC2_REG(rhport); + tu_memclr(&_dcd_data, sizeof(_dcd_data)); + // Core Initialization const bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_DEVICE); const bool is_dma = dma_device_enabled(dwc2); @@ -505,7 +539,7 @@ void dcd_sof_enable(uint8_t rhport, bool en) { (void) rhport; dwc2_regs_t* dwc2 = DWC2_REG(rhport); - _sof_en = en; + _dcd_data.sof_en = en; if (en) { dwc2->gintsts = GINTSTS_SOF; @@ -530,7 +564,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; - _allocated_ep_in_count = 1; + _dcd_data.allocated_epin_count = 1; // Disable non-control interrupt dwc2->daintmsk = (1 << DAINTMSK_OEPM_Pos) | (1 << DAINTMSK_IEPM_Pos); @@ -578,7 +612,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to // EP0 can only handle one packet if (epnum == 0) { - ep0_pending[dir] = total_bytes; + _dcd_data.ep0_pending[dir] = total_bytes; } // Schedule packets to be sent within interrupt @@ -644,8 +678,8 @@ static void handle_bus_reset(uint8_t rhport) { tu_memclr(xfer_status, sizeof(xfer_status)); - _sof_en = false; - _allocated_ep_in_count = 1; + _dcd_data.sof_en = false; + _dcd_data.allocated_epin_count = 1; // 1. NAK for all OUT endpoints for (uint8_t n = 0; n < ep_count; n++) { @@ -746,12 +780,14 @@ static void handle_rxflvl_irq(uint8_t rhport) { // Global OUT NAK: do nothing break; - case GRXSTS_PKTSTS_SETUP_RX: + case GRXSTS_PKTSTS_SETUP_RX: { // Setup packet received + uint32_t* setup = (uint32_t*)(uintptr_t) _dcd_usbbuf.setup_packet; // We can receive up to three setup packets in succession, but only the last one is valid. - _setup_packet[0] = (*rx_fifo); - _setup_packet[1] = (*rx_fifo); + setup[0] = (*rx_fifo); + setup[1] = (*rx_fifo); break; + } case GRXSTS_PKTSTS_SETUP_DONE: // Setup packet done: @@ -777,8 +813,8 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count < xfer->max_size) { xfer->total_len -= epout->tsiz_bm.xfer_size; if (epnum == 0) { - xfer->total_len -= ep0_pending[TUSB_DIR_OUT]; - ep0_pending[TUSB_DIR_OUT] = 0; + xfer->total_len -= _dcd_data.ep0_pending[TUSB_DIR_OUT]; + _dcd_data.ep0_pending[TUSB_DIR_OUT] = 0; } } } @@ -797,7 +833,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepint_bm) { if (doepint_bm.setup_phase_done) { - dcd_event_setup_received(rhport, (uint8_t*) _setup_packet, true); + dcd_event_setup_received(rhport, _dcd_usbbuf.setup_packet, true); return; } @@ -809,7 +845,7 @@ static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doe if (!doepint_bm.status_phase_rx && !doepint_bm.setup_packet_rx) { xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) { + if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_OUT]) { // EP0 can only handle one packet, Schedule another packet to be received. edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT); } else { @@ -825,7 +861,7 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); if (diepint_bm.xfer_complete) { - if ((epnum == 0) && ep0_pending[TUSB_DIR_IN]) { + if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_IN]) { // EP0 can only handle one packet. Schedule another packet to be transmitted. edpt_schedule_packets(rhport, epnum, TUSB_DIR_IN); } else { @@ -873,7 +909,8 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi if (doepint_bm.setup_phase_done) { dma_setup_prepare(rhport); - dcd_event_setup_received(rhport, (uint8_t*) _setup_packet, true); + dcd_dcache_invalidate(_dcd_usbbuf.setup_packet, 8); + dcd_event_setup_received(rhport, _dcd_usbbuf.setup_packet, true); return; } @@ -882,7 +919,7 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi // only handle data skip if it is setup or status related // Normal OUT transfer complete if (!doepint_bm.status_phase_rx && !doepint_bm.setup_packet_rx) { - if ((epnum == 0) && ep0_pending[TUSB_DIR_OUT]) { + if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_OUT]) { // EP0 can only handle one packet Schedule another packet to be received. edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT); } else { @@ -899,6 +936,7 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi dma_setup_prepare(rhport); } + dcd_dcache_invalidate(xfer->buffer, xfer->total_len); dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); } } @@ -909,7 +947,7 @@ static void handle_epin_dma(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diepin xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); if (diepint_bm.xfer_complete) { - if ((epnum == 0) && ep0_pending[TUSB_DIR_IN]) { + if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_IN]) { // EP0 can only handle one packet. Schedule another packet to be transmitted. edpt_schedule_packets(rhport, epnum, TUSB_DIR_IN); } else { @@ -1016,7 +1054,7 @@ void dcd_int_handler(uint8_t rhport) { if (gintsts & GINTSTS_OTGINT) { // OTG INT bit is read-only - uint32_t const otg_int = dwc2->gotgint; + const uint32_t otg_int = dwc2->gotgint; if (otg_int & GOTGINT_SEDET) { dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); @@ -1033,7 +1071,7 @@ void dcd_int_handler(uint8_t rhport) { const uint32_t frame = (dwc2->dsts & DSTS_FNSOF) >> DSTS_FNSOF_Pos; // Disable SOF interrupt if SOF was not explicitly enabled since SOF was used for remote wakeup detection - if (!_sof_en) { + if (!_dcd_data.sof_en) { dwc2->gintmsk &= ~GINTMSK_SOFM; } From 9f26bc4f6251f281eaf5200c0856de85d4939ba8 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Mon, 25 Nov 2024 15:46:05 +0200 Subject: [PATCH 31/38] Update dcd_dwc2.c --- components/arduino_tinyusb/src/dcd_dwc2.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/components/arduino_tinyusb/src/dcd_dwc2.c b/components/arduino_tinyusb/src/dcd_dwc2.c index da36a144f..8a2b585b4 100644 --- a/components/arduino_tinyusb/src/dcd_dwc2.c +++ b/components/arduino_tinyusb/src/dcd_dwc2.c @@ -83,22 +83,19 @@ CFG_TUD_MEM_SECTION static struct { // DMA //-------------------------------------------------------------------- #if CFG_TUD_MEM_DCACHE_ENABLE -void dcd_dcache_clean(const void* addr, uint32_t data_size) { - if (addr && data_size) { - dwc2_dcache_clean(addr, data_size); - } +bool dcd_dcache_clean(const void* addr, uint32_t data_size) { + TU_VERIFY(addr && data_size); + return dwc2_dcache_clean(addr, data_size); } -void dcd_dcache_invalidate(const void* addr, uint32_t data_size) { - if (addr && data_size) { - dwc2_dcache_invalidate(addr, data_size); - } +bool dcd_dcache_invalidate(const void* addr, uint32_t data_size) { + TU_VERIFY(addr && data_size); + return dwc2_dcache_invalidate(addr, data_size); } -void dcd_dcache_clean_invalidate(const void* addr, uint32_t data_size) { - if (addr && data_size) { - dwc2_dcache_clean_invalidate(addr, data_size); - } +bool dcd_dcache_clean_invalidate(const void* addr, uint32_t data_size) { + TU_VERIFY(addr && data_size); + return dwc2_dcache_clean_invalidate(addr, data_size); } #endif From 4e28a075ca0ab686da667d0d170a9445efa7dee7 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 10 Dec 2024 12:41:55 +0200 Subject: [PATCH 32/38] Update dcd_dwc2.c --- components/arduino_tinyusb/src/dcd_dwc2.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/components/arduino_tinyusb/src/dcd_dwc2.c b/components/arduino_tinyusb/src/dcd_dwc2.c index 8a2b585b4..7df5d3792 100644 --- a/components/arduino_tinyusb/src/dcd_dwc2.c +++ b/components/arduino_tinyusb/src/dcd_dwc2.c @@ -31,8 +31,8 @@ #if CFG_TUD_ENABLED && defined(TUP_USBIP_DWC2) -#if !CFG_TUD_DWC2_SLAVE_ENABLE && !CFG_TUH_DWC2_DMA_ENABLE -#error DWC2 require either CFG_TUD_DWC2_SLAVE_ENABLE or CFG_TUH_DWC2_DMA_ENABLE to be enabled +#if !(CFG_TUD_DWC2_SLAVE_ENABLE || CFG_TUD_DWC2_DMA_ENABLE) +#error DWC2 require either CFG_TUD_DWC2_SLAVE_ENABLE or CFG_TUD_DWC2_DMA_ENABLE to be enabled #endif // Debug level for DWC2 @@ -192,8 +192,8 @@ static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { } } else { // Check IN endpoints concurrently active limit - if(_dwc2_controller->ep_in_count) { - TU_ASSERT(_dcd_data.allocated_epin_count < _dwc2_controller->ep_in_count); + if(dwc2_controller->ep_in_count) { + TU_ASSERT(_dcd_data.allocated_epin_count < dwc2_controller->ep_in_count); _dcd_data.allocated_epin_count++; } @@ -561,7 +561,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; - _dcd_data.allocated_epin_count = 1; + _dcd_data.allocated_epin_count = 0; // Disable non-control interrupt dwc2->daintmsk = (1 << DAINTMSK_OEPM_Pos) | (1 << DAINTMSK_IEPM_Pos); @@ -641,10 +641,6 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t return true; } -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - edpt_disable(rhport, ep_addr, false); -} - void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); edpt_disable(rhport, ep_addr, true); @@ -676,7 +672,7 @@ static void handle_bus_reset(uint8_t rhport) { tu_memclr(xfer_status, sizeof(xfer_status)); _dcd_data.sof_en = false; - _dcd_data.allocated_epin_count = 1; + _dcd_data.allocated_epin_count = 0; // 1. NAK for all OUT endpoints for (uint8_t n = 0; n < ep_count; n++) { From a8ed145453cacf5c0cc414e563c58c629967e59a Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Tue, 10 Dec 2024 12:42:03 +0200 Subject: [PATCH 33/38] Update copy-libs.sh --- tools/copy-libs.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/copy-libs.sh b/tools/copy-libs.sh index 1c03d55cb..cefaae02b 100755 --- a/tools/copy-libs.sh +++ b/tools/copy-libs.sh @@ -44,7 +44,12 @@ mkdir -p "$AR_SDK" mkdir -p "$AR_SDK/lib" function get_actual_path(){ - p="$PWD"; cd "$1"; r="$PWD"; cd "$p"; echo "$r"; + d="$1"; + if [ -d "$d" ]; then + p="$PWD"; cd "$d"; r="$PWD"; cd "$p"; echo "$r"; + else + echo ""; + fi } # From 72278620687bb50a91ca73cbe0a7e4634c501dc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= <90197375+P-R-O-C-H-Y@users.noreply.github.com> Date: Tue, 10 Dec 2024 11:47:41 +0100 Subject: [PATCH 34/38] Support rev 0 for P4 (#254) * Support rev 0 for P4 * Revert C6 slave idf target --- configs/defconfig.esp32p4 | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/configs/defconfig.esp32p4 b/configs/defconfig.esp32p4 index eaa692910..8b04e8469 100644 --- a/configs/defconfig.esp32p4 +++ b/configs/defconfig.esp32p4 @@ -13,3 +13,14 @@ CONFIG_ESP_SDIO_PIN_D0=14 CONFIG_ESP_SDIO_PIN_D1=15 CONFIG_ESP_SDIO_PIN_D2=16 CONFIG_ESP_SDIO_PIN_D3=17 + +# +# Chip revision +# +CONFIG_ESP32P4_REV_MIN_0=y +# CONFIG_ESP32P4_REV_MIN_1 is not set +CONFIG_ESP32P4_REV_MIN_FULL=0 +CONFIG_ESP_REV_MIN_FULL=0 +CONFIG_ESP32P4_REV_MAX_FULL=99 +CONFIG_ESP_REV_MAX_FULL=99 +# end of Chip revision From 12afeba33a78f2d511033e40a8bb9516d611da2e Mon Sep 17 00:00:00 2001 From: kvp1703 <65121235+kvp1703@users.noreply.github.com> Date: Tue, 10 Dec 2024 16:19:25 +0530 Subject: [PATCH 35/38] Fix the crash for esp32 and esp32c3 (#248) --- configs/defconfig.common | 2 +- configs/defconfig.esp32 | 1 + configs/defconfig.esp32c3 | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/configs/defconfig.common b/configs/defconfig.common index 118fc0098..ef4620bf6 100644 --- a/configs/defconfig.common +++ b/configs/defconfig.common @@ -19,7 +19,7 @@ CONFIG_ESP_IPC_TASK_STACK_SIZE=1024 CONFIG_ESP_MAIN_TASK_STACK_SIZE=4096 CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2048 CONFIG_ESP_TASK_WDT_PANIC=y -CONFIG_ESP_TIMER_TASK_STACK_SIZE=4096 +CONFIG_ESP_TIMER_TASK_STACK_SIZE=8192 CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y CONFIG_ESP_WIFI_FTM_ENABLE=y CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=8 diff --git a/configs/defconfig.esp32 b/configs/defconfig.esp32 index 2e88a27ed..db01aeab3 100644 --- a/configs/defconfig.esp32 +++ b/configs/defconfig.esp32 @@ -19,3 +19,4 @@ CONFIG_TWAI_ERRATA_FIX_TX_INTR_LOST=y CONFIG_TWAI_ERRATA_FIX_RX_FRAME_INVALID=y CONFIG_TWAI_ERRATA_FIX_RX_FIFO_CORRUPT=y CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096 diff --git a/configs/defconfig.esp32c3 b/configs/defconfig.esp32c3 index c497b562d..1baf62540 100644 --- a/configs/defconfig.esp32c3 +++ b/configs/defconfig.esp32c3 @@ -6,3 +6,4 @@ CONFIG_ESP_WIFI_11KV_SUPPORT=y CONFIG_ESP_WIFI_SCAN_CACHE=y CONFIG_ESP_WIFI_MBO_SUPPORT=y CONFIG_ESP_WIFI_11R_SUPPORT=y +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096 From ac5db7208cc8d7dcae70ddcec0f76d943f3e359e Mon Sep 17 00:00:00 2001 From: Lucas Saavedra Vaz <32426024+lucasssvaz@users.noreply.github.com> Date: Tue, 10 Dec 2024 16:02:48 -0300 Subject: [PATCH 36/38] fix(trademark): Remove 3rd party trademarks from scripts (#255) --- build.sh | 6 +- configs/{pio_end.txt => pioarduino_end.txt} | 0 .../{pio_start.txt => pioarduino_start.txt} | 2 +- tools/config.sh | 2 +- tools/copy-libs.sh | 182 +++++++++--------- ...manifest.py => gen_pioarduino_manifest.py} | 2 +- 6 files changed, 97 insertions(+), 97 deletions(-) rename configs/{pio_end.txt => pioarduino_end.txt} (100%) rename configs/{pio_start.txt => pioarduino_start.txt} (96%) rename tools/{gen_platformio_manifest.py => gen_pioarduino_manifest.py} (94%) diff --git a/build.sh b/build.sh index 9bceda087..50e376c2a 100755 --- a/build.sh +++ b/build.sh @@ -305,14 +305,14 @@ if [ "$BUILD_TYPE" = "all" ]; then if [ $? -ne 0 ]; then exit 1; fi fi -# Generate PlatformIO manifest file +# Generate pioarduino manifest file if [ "$BUILD_TYPE" = "all" ]; then - echo "* Generating PlatformIO manifest file..." + echo "* Generating pioarduino manifest file..." pushd $IDF_PATH ibr=$(git describe --all 2>/dev/null) ic=$(git -C "$IDF_PATH" rev-parse --short HEAD) popd - python3 ./tools/gen_platformio_manifest.py -o "$TOOLS_JSON_OUT/" -s "$ibr" -c "$ic" + python3 ./tools/gen_pioarduino_manifest.py -o "$TOOLS_JSON_OUT/" -s "$ibr" -c "$ic" if [ $? -ne 0 ]; then exit 1; fi fi diff --git a/configs/pio_end.txt b/configs/pioarduino_end.txt similarity index 100% rename from configs/pio_end.txt rename to configs/pioarduino_end.txt diff --git a/configs/pio_start.txt b/configs/pioarduino_start.txt similarity index 96% rename from configs/pio_start.txt rename to configs/pioarduino_start.txt index a0b780dc9..c5174173d 100644 --- a/configs/pio_start.txt +++ b/configs/pioarduino_start.txt @@ -22,7 +22,7 @@ kinds of creative coding, interactive objects, spaces or physical experiences. http://arduino.cc/en/Reference/HomePage """ -# Extends: https://github.com/platformio/platform-espressif32/blob/develop/builder/main.py +# Extends: https://github.com/pioarduino/platform-espressif32/blob/develop/builder/main.py from os.path import basename, join diff --git a/tools/config.sh b/tools/config.sh index a1be7fd97..6b5220a1a 100755 --- a/tools/config.sh +++ b/tools/config.sh @@ -49,7 +49,7 @@ AR_PATCHES="$AR_ROOT/patches" AR_PLATFORM_TXT="$AR_OUT/platform.txt" AR_GEN_PART_PY="$AR_TOOLS/gen_esp32part.py" AR_SDK="$AR_TOOLS/esp32-arduino-libs/$IDF_TARGET" -PIO_SDK="FRAMEWORK_SDK_DIR, \"$IDF_TARGET\"" +PIOARDUINO_SDK="FRAMEWORK_SDK_DIR, \"$IDF_TARGET\"" TOOLS_JSON_OUT="$AR_TOOLS/esp32-arduino-libs" if [ -d "$IDF_PATH" ]; then diff --git a/tools/copy-libs.sh b/tools/copy-libs.sh index cefaae02b..21efe1a78 100755 --- a/tools/copy-libs.sh +++ b/tools/copy-libs.sh @@ -36,8 +36,8 @@ fi if [ -e "$AR_SDK/$MEMCONF" ]; then rm -rf "$AR_SDK/$MEMCONF" fi -if [ -e "$AR_SDK/platformio-build.py" ]; then - rm -rf "$AR_SDK/platformio-build.py" +if [ -e "$AR_SDK/pioarduino-build.py" ]; then + rm -rf "$AR_SDK/pioarduino-build.py" fi mkdir -p "$AR_SDK" @@ -72,13 +72,13 @@ LD_LIBS_SEARCH="" LD_SCRIPTS="" LD_SCRIPT_DIRS="" -PIO_CC_FLAGS="" -PIO_C_FLAGS="" -PIO_CXX_FLAGS="" -PIO_AS_FLAGS="" -PIO_LD_FLAGS="" -PIO_LD_FUNCS="" -PIO_LD_SCRIPTS="" +PIOARDUINO_CC_FLAGS="" +PIOARDUINO_C_FLAGS="" +PIOARDUINO_CXX_FLAGS="" +PIOARDUINO_AS_FLAGS="" +PIOARDUINO_LD_FLAGS="" +PIOARDUINO_LD_FUNCS="" +PIOARDUINO_LD_SCRIPTS="" TOOLCHAIN_PREFIX="" if [ "$IS_XTENSA" = "y" ]; then @@ -126,7 +126,7 @@ for item in "${@:2:${#@}-5}"; do DEFINES+="$item " fi elif [ "$prefix" = "-O" ]; then - PIO_CC_FLAGS+="$item " + PIOARDUINO_CC_FLAGS+="$item " elif [[ "$item" != "-Wall" && "$item" != "-Werror=all" && "$item" != "-Wextra" ]]; then if [[ "${item:0:23}" != "-mfix-esp32-psram-cache" && "${item:0:18}" != "-fmacro-prefix-map" && "${item:0:20}" != "-fdiagnostics-color=" && "${item:0:19}" != "-fdebug-prefix-map=" ]]; then C_FLAGS+="$item " @@ -145,9 +145,9 @@ for item in "${@:2:${#@}-5}"; do if [[ "${item:0:23}" != "-mfix-esp32-psram-cache" && "${item:0:18}" != "-fmacro-prefix-map" && "${item:0:20}" != "-fdiagnostics-color=" && "${item:0:19}" != "-fdebug-prefix-map=" ]]; then AS_FLAGS+="$item " if [[ $C_FLAGS == *"$item"* ]]; then - PIO_CC_FLAGS+="$item " + PIOARDUINO_CC_FLAGS+="$item " else - PIO_AS_FLAGS+="$item " + PIOARDUINO_AS_FLAGS+="$item " fi fi fi @@ -163,8 +163,8 @@ for item in "${@:2:${#@}-5}"; do if [[ "$prefix" != "-I" && "$prefix" != "-D" && "$item" != "-Wall" && "$item" != "-Werror=all" && "$item" != "-Wextra" && "$prefix" != "-O" ]]; then if [[ "${item:0:23}" != "-mfix-esp32-psram-cache" && "${item:0:18}" != "-fmacro-prefix-map" && "${item:0:20}" != "-fdiagnostics-color=" && "${item:0:19}" != "-fdebug-prefix-map=" ]]; then CPP_FLAGS+="$item " - if [[ $PIO_CC_FLAGS != *"$item"* ]]; then - PIO_CXX_FLAGS+="$item " + if [[ $PIOARDUINO_CC_FLAGS != *"$item"* ]]; then + PIOARDUINO_CXX_FLAGS+="$item " fi fi fi @@ -172,8 +172,8 @@ done set -- $C_FLAGS for item; do - if [[ $PIO_CC_FLAGS != *"$item"* ]]; then - PIO_C_FLAGS+="$item " + if [[ $PIOARDUINO_CC_FLAGS != *"$item"* ]]; then + PIOARDUINO_C_FLAGS+="$item " fi done @@ -200,7 +200,7 @@ else fi if [ "$IDF_TARGET" = "esp32" ]; then LD_SCRIPTS+="-T esp32.rom.redefined.ld " - PIO_LD_SCRIPTS+="esp32.rom.redefined.ld " + PIOARDUINO_LD_SCRIPTS+="esp32.rom.redefined.ld " fi set -- $str for item; do @@ -235,7 +235,7 @@ for item; do is_dir=0 elif [[ "${item:0:23}" != "-mfix-esp32-psram-cache" && "${item:0:18}" != "-fmacro-prefix-map" && "${item:0:19}" != "-fdebug-prefix-map=" && "${item:0:17}" != "-Wl,--start-group" && "${item:0:15}" != "-Wl,--end-group" ]]; then LD_FLAGS+="$item " - PIO_LD_FLAGS+="$item " + PIOARDUINO_LD_FLAGS+="$item " fi fi else @@ -247,10 +247,10 @@ for item; do elif [ "$is_script" = "1" ]; then is_script=0 LD_SCRIPTS+="$item " - PIO_LD_SCRIPTS+="$item " + PIOARDUINO_LD_SCRIPTS+="$item " else LD_FLAGS+="$item " - PIO_LD_FUNCS+="$item " + PIOARDUINO_LD_FUNCS+="$item " fi else if [ "${item:${#item}-2:2}" = ".a" ]; then @@ -318,82 +318,82 @@ done mkdir -p "$AR_SDK" -# start generation of platformio-build.py -AR_PLATFORMIO_PY="$AR_SDK/platformio-build.py" -cat configs/pio_start.txt > "$AR_PLATFORMIO_PY" +# start generation of pioarduino-build.py +AR_PIOARDUINO_PY="$AR_SDK/pioarduino-build.py" +cat configs/pioarduino_start.txt > "$AR_PIOARDUINO_PY" -echo " ASFLAGS=[" >> "$AR_PLATFORMIO_PY" +echo " ASFLAGS=[" >> "$AR_PIOARDUINO_PY" if [ "$IS_XTENSA" = "y" ]; then - echo " \"-mlongcalls\"" >> "$AR_PLATFORMIO_PY" + echo " \"-mlongcalls\"" >> "$AR_PIOARDUINO_PY" else - echo " \"-march=rv32imc\"" >> "$AR_PLATFORMIO_PY" + echo " \"-march=rv32imc\"" >> "$AR_PIOARDUINO_PY" fi -echo " ]," >> "$AR_PLATFORMIO_PY" -echo "" >> "$AR_PLATFORMIO_PY" +echo " ]," >> "$AR_PIOARDUINO_PY" +echo "" >> "$AR_PIOARDUINO_PY" -echo " ASPPFLAGS=[" >> "$AR_PLATFORMIO_PY" -set -- $PIO_AS_FLAGS +echo " ASPPFLAGS=[" >> "$AR_PIOARDUINO_PY" +set -- $PIOARDUINO_AS_FLAGS for item; do - echo " \"$item\"," >> "$AR_PLATFORMIO_PY" + echo " \"$item\"," >> "$AR_PIOARDUINO_PY" done -echo " \"-x\", \"assembler-with-cpp\"" >> "$AR_PLATFORMIO_PY" -echo " ]," >> "$AR_PLATFORMIO_PY" -echo "" >> "$AR_PLATFORMIO_PY" +echo " \"-x\", \"assembler-with-cpp\"" >> "$AR_PIOARDUINO_PY" +echo " ]," >> "$AR_PIOARDUINO_PY" +echo "" >> "$AR_PIOARDUINO_PY" -echo " CFLAGS=[" >> "$AR_PLATFORMIO_PY" -set -- $PIO_C_FLAGS +echo " CFLAGS=[" >> "$AR_PIOARDUINO_PY" +set -- $PIOARDUINO_C_FLAGS last_item="${@: -1}" for item in "${@:0:${#@}}"; do if [ "${item:0:1}" != "/" ]; then - echo " \"$item\"," >> "$AR_PLATFORMIO_PY" + echo " \"$item\"," >> "$AR_PIOARDUINO_PY" fi done -echo " \"$last_item\"" >> "$AR_PLATFORMIO_PY" -echo " ]," >> "$AR_PLATFORMIO_PY" -echo "" >> "$AR_PLATFORMIO_PY" +echo " \"$last_item\"" >> "$AR_PIOARDUINO_PY" +echo " ]," >> "$AR_PIOARDUINO_PY" +echo "" >> "$AR_PIOARDUINO_PY" -echo " CXXFLAGS=[" >> "$AR_PLATFORMIO_PY" -set -- $PIO_CXX_FLAGS +echo " CXXFLAGS=[" >> "$AR_PIOARDUINO_PY" +set -- $PIOARDUINO_CXX_FLAGS last_item="${@: -1}" for item in "${@:0:${#@}}"; do if [ "${item:0:1}" != "/" ]; then - echo " \"$item\"," >> "$AR_PLATFORMIO_PY" + echo " \"$item\"," >> "$AR_PIOARDUINO_PY" fi done -echo " \"$last_item\"" >> "$AR_PLATFORMIO_PY" -echo " ]," >> "$AR_PLATFORMIO_PY" -echo "" >> "$AR_PLATFORMIO_PY" +echo " \"$last_item\"" >> "$AR_PIOARDUINO_PY" +echo " ]," >> "$AR_PIOARDUINO_PY" +echo "" >> "$AR_PIOARDUINO_PY" -echo " CCFLAGS=[" >> "$AR_PLATFORMIO_PY" -set -- $PIO_CC_FLAGS +echo " CCFLAGS=[" >> "$AR_PIOARDUINO_PY" +set -- $PIOARDUINO_CC_FLAGS for item; do - echo " \"$item\"," >> "$AR_PLATFORMIO_PY" + echo " \"$item\"," >> "$AR_PIOARDUINO_PY" done -echo " \"-MMD\"" >> "$AR_PLATFORMIO_PY" -echo " ]," >> "$AR_PLATFORMIO_PY" -echo "" >> "$AR_PLATFORMIO_PY" +echo " \"-MMD\"" >> "$AR_PIOARDUINO_PY" +echo " ]," >> "$AR_PIOARDUINO_PY" +echo "" >> "$AR_PIOARDUINO_PY" -echo " LINKFLAGS=[" >> "$AR_PLATFORMIO_PY" -set -- $PIO_LD_FLAGS +echo " LINKFLAGS=[" >> "$AR_PIOARDUINO_PY" +set -- $PIOARDUINO_LD_FLAGS for item; do - echo " \"$item\"," >> "$AR_PLATFORMIO_PY" + echo " \"$item\"," >> "$AR_PIOARDUINO_PY" done -set -- $PIO_LD_SCRIPTS +set -- $PIOARDUINO_LD_SCRIPTS for item; do - echo " \"-T\", \"$item\"," >> "$AR_PLATFORMIO_PY" + echo " \"-T\", \"$item\"," >> "$AR_PIOARDUINO_PY" done -set -- $PIO_LD_FUNCS +set -- $PIOARDUINO_LD_FUNCS for item; do - echo " \"-u\", \"$item\"," >> "$AR_PLATFORMIO_PY" + echo " \"-u\", \"$item\"," >> "$AR_PIOARDUINO_PY" done -echo " '-Wl,-Map=\"%s\"' % join(\"\${BUILD_DIR}\", \"\${PROGNAME}.map\")" >> "$AR_PLATFORMIO_PY" +echo " '-Wl,-Map=\"%s\"' % join(\"\${BUILD_DIR}\", \"\${PROGNAME}.map\")" >> "$AR_PIOARDUINO_PY" -echo " ]," >> "$AR_PLATFORMIO_PY" -echo "" >> "$AR_PLATFORMIO_PY" +echo " ]," >> "$AR_PIOARDUINO_PY" +echo "" >> "$AR_PIOARDUINO_PY" # include dirs REL_INC="" -echo " CPPPATH=[" >> "$AR_PLATFORMIO_PY" +echo " CPPPATH=[" >> "$AR_PIOARDUINO_PY" set -- $INCLUDES @@ -421,11 +421,11 @@ for item; do out_cpath="$AR_SDK/include/$fname$out_sub" REL_INC+="-iwithprefixbefore $fname$out_sub " if [ "$out_sub" = "" ]; then - echo " join($PIO_SDK, \"include\", \"$fname\")," >> "$AR_PLATFORMIO_PY" + echo " join($PIOARDUINO_SDK, \"include\", \"$fname\")," >> "$AR_PIOARDUINO_PY" else - pio_sub="${out_sub:1}" - pio_sub=`echo $pio_sub | sed 's/\//\\", \\"/g'` - echo " join($PIO_SDK, \"include\", \"$fname\", \"$pio_sub\")," >> "$AR_PLATFORMIO_PY" + pioarduino_sub="${out_sub:1}" + pioarduino_sub=`echo $pioarduino_sub | sed 's/\//\\", \\"/g'` + echo " join($PIOARDUINO_SDK, \"include\", \"$fname\", \"$pioarduino_sub\")," >> "$AR_PIOARDUINO_PY" fi for f in `find "$item" -name '*.h'`; do rel_f=${f#*$item} @@ -452,19 +452,19 @@ for item; do fi fi done -echo " join($PIO_SDK, board_config.get(\"build.arduino.memory_type\", (board_config.get(\"build.flash_mode\", \"dio\") + \"_$OCT_PSRAM\")), \"include\")," >> "$AR_PLATFORMIO_PY" -echo " join(FRAMEWORK_DIR, \"cores\", board_config.get(\"build.core\"))" >> "$AR_PLATFORMIO_PY" -echo " ]," >> "$AR_PLATFORMIO_PY" -echo "" >> "$AR_PLATFORMIO_PY" +echo " join($PIOARDUINO_SDK, board_config.get(\"build.arduino.memory_type\", (board_config.get(\"build.flash_mode\", \"dio\") + \"_$OCT_PSRAM\")), \"include\")," >> "$AR_PIOARDUINO_PY" +echo " join(FRAMEWORK_DIR, \"cores\", board_config.get(\"build.core\"))" >> "$AR_PIOARDUINO_PY" +echo " ]," >> "$AR_PIOARDUINO_PY" +echo "" >> "$AR_PIOARDUINO_PY" AR_LIBS="$LD_LIBS" -PIO_LIBS="" +PIOARDUINO_LIBS="" set -- $LD_LIBS for item; do - if [ "$PIO_LIBS" != "" ]; then - PIO_LIBS+=", " + if [ "$PIOARDUINO_LIBS" != "" ]; then + PIOARDUINO_LIBS+=", " fi - PIO_LIBS+="\"$item\"" + PIOARDUINO_LIBS+="\"$item\"" done set -- $LD_LIB_FILES @@ -472,19 +472,19 @@ for item; do cp "$item" "$AR_SDK/lib/" done -echo " LIBPATH=[" >> "$AR_PLATFORMIO_PY" -echo " join($PIO_SDK, \"lib\")," >> "$AR_PLATFORMIO_PY" -echo " join($PIO_SDK, \"ld\")," >> "$AR_PLATFORMIO_PY" -echo " join($PIO_SDK, board_config.get(\"build.arduino.memory_type\", (board_config.get(\"build.flash_mode\", \"dio\") + \"_$OCT_PSRAM\")))" >> "$AR_PLATFORMIO_PY" -echo " ]," >> "$AR_PLATFORMIO_PY" -echo "" >> "$AR_PLATFORMIO_PY" +echo " LIBPATH=[" >> "$AR_PIOARDUINO_PY" +echo " join($PIOARDUINO_SDK, \"lib\")," >> "$AR_PIOARDUINO_PY" +echo " join($PIOARDUINO_SDK, \"ld\")," >> "$AR_PIOARDUINO_PY" +echo " join($PIOARDUINO_SDK, board_config.get(\"build.arduino.memory_type\", (board_config.get(\"build.flash_mode\", \"dio\") + \"_$OCT_PSRAM\")))" >> "$AR_PIOARDUINO_PY" +echo " ]," >> "$AR_PIOARDUINO_PY" +echo "" >> "$AR_PIOARDUINO_PY" -echo " LIBS=[" >> "$AR_PLATFORMIO_PY" -echo " $PIO_LIBS" >> "$AR_PLATFORMIO_PY" -echo " ]," >> "$AR_PLATFORMIO_PY" -echo "" >> "$AR_PLATFORMIO_PY" +echo " LIBS=[" >> "$AR_PIOARDUINO_PY" +echo " $PIOARDUINO_LIBS" >> "$AR_PIOARDUINO_PY" +echo " ]," >> "$AR_PIOARDUINO_PY" +echo "" >> "$AR_PIOARDUINO_PY" -echo " CPPDEFINES=[" >> "$AR_PLATFORMIO_PY" +echo " CPPDEFINES=[" >> "$AR_PIOARDUINO_PY" set -- $DEFINES for item; do item="${item:2}" #remove -D @@ -492,17 +492,17 @@ for item; do item=(${item//=/ }) re='^[+-]?[0-9]+([.][0-9]+)?$' if [[ ${item[1]} =~ $re ]]; then - echo " (\"${item[0]}\", ${item[1]})," >> "$AR_PLATFORMIO_PY" + echo " (\"${item[0]}\", ${item[1]})," >> "$AR_PIOARDUINO_PY" else - echo " (\"${item[0]}\", '${item[1]}')," >> "$AR_PLATFORMIO_PY" + echo " (\"${item[0]}\", '${item[1]}')," >> "$AR_PIOARDUINO_PY" fi else - echo " \"$item\"," >> "$AR_PLATFORMIO_PY" + echo " \"$item\"," >> "$AR_PIOARDUINO_PY" fi done -# end generation of platformio-build.py -cat configs/pio_end.txt >> "$AR_PLATFORMIO_PY" +# end generation of pioarduino-build.py +cat configs/pioarduino_end.txt >> "$AR_PIOARDUINO_PY" # replace double backslashes with single one DEFINES=`echo "$DEFINES" | tr -s '\'` diff --git a/tools/gen_platformio_manifest.py b/tools/gen_pioarduino_manifest.py similarity index 94% rename from tools/gen_platformio_manifest.py rename to tools/gen_pioarduino_manifest.py index f02218826..9d2b99c19 100644 --- a/tools/gen_platformio_manifest.py +++ b/tools/gen_pioarduino_manifest.py @@ -53,7 +53,7 @@ def main(dst_dir, version_string, commit_hash): json.dump(MANIFEST_DATA, fp, indent=2) print( - f"Generated PlatformIO manifest file '{manifest_file_path}' with '{converted_version}' version" + f"Generated pioarduino manifest file '{manifest_file_path}' with '{converted_version}' version" ) return 0 From c1053bc1c0b421cf932518dfd3649e6ed9c7d3f8 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Thu, 12 Dec 2024 10:56:39 +0200 Subject: [PATCH 37/38] Update dcd_dwc2.c --- components/arduino_tinyusb/src/dcd_dwc2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/arduino_tinyusb/src/dcd_dwc2.c b/components/arduino_tinyusb/src/dcd_dwc2.c index 7df5d3792..d6796641a 100644 --- a/components/arduino_tinyusb/src/dcd_dwc2.c +++ b/components/arduino_tinyusb/src/dcd_dwc2.c @@ -44,7 +44,7 @@ #if TU_CHECK_MCU(OPT_MCU_GD32VF103) #define DWC2_EP_COUNT(_dwc2) DWC2_EP_MAX #else - #define DWC2_EP_COUNT(_dwc2) ((_dwc2)->ghwcfg2_bm.num_dev_ep) + #define DWC2_EP_COUNT(_dwc2) ((_dwc2)->ghwcfg2_bm.num_dev_ep + 1) #endif //--------------------------------------------------------------------+ From 0c609b1cb4afe91c5d14f4a7df830541fa4fe610 Mon Sep 17 00:00:00 2001 From: me-no-dev Date: Wed, 18 Dec 2024 15:55:03 +0200 Subject: [PATCH 38/38] Prepare for merging release/v5.3 into master --- .github/workflows/cron.yml | 2 +- tools/config.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index dff1fb9d3..30285c8bb 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -36,5 +36,5 @@ jobs: lib_builder_branch: "release/v5.1" targets: "esp32,esp32s2,esp32s3,esp32c3,esp32c6,esp32h2" - idf_branch: "release/v5.3" - lib_builder_branch: "release/v5.3" + lib_builder_branch: "master" targets: "esp32,esp32s2,esp32s3,esp32c3,esp32c6,esp32h2,esp32p4" diff --git a/tools/config.sh b/tools/config.sh index 6b5220a1a..89cd9856a 100755 --- a/tools/config.sh +++ b/tools/config.sh @@ -10,7 +10,7 @@ if [ -z $IDF_BRANCH ]; then fi if [ -z $AR_PR_TARGET_BRANCH ]; then - AR_PR_TARGET_BRANCH="release/v3.1.x" + AR_PR_TARGET_BRANCH="master" fi if [ -z $IDF_TARGET ]; then